/** * Copyright (c) 2019 Paul Armstrong */ import { AppRegistry } from 'react-native-web'; import Favicon from '../images/favicon.png'; import Main from '../screens/Main'; import makeStore from '../store'; import { Provider } from 'react-redux'; import React from 'react'; import ReactDOMServer from 'react-dom/server'; import { searchParamsToStore } from '../store/utils'; import { Store } from 'redux'; import toSource from 'tosource'; import { Actions, State } from '../store/types'; import { Request, RequestHandler, Response } from 'express'; interface AppProps { store: Store; } const App = (props: AppProps): React.ReactElement => (
); AppRegistry.registerComponent('App', () => App); export function getPageHTML(nonce: string, state: Partial, scripts: Array): string { const store = makeStore(state); const { name } = store.getState(); const { element, getStyleElement } = AppRegistry.getApplication('App', { initialProps: { store } }); const html = ReactDOMServer.renderToString(element); const css = ReactDOMServer.renderToStaticMarkup(getStyleElement({ nonce })); return ` ${name === 'Build Tracker' ? name : `${name} : Build Tracker`} ${css}
${html}
${scripts.map((script) => ``).join('')} `; } interface Stats { assetsByChunkName: { [key: string]: string | Array }; name: string; } interface ProdStats { children: Array; } interface DevStats { clientStats: Stats; } const getAssetByName = (asset: Array | string): Array => { return Array.isArray(asset) ? asset : [asset]; }; const serverRender = (stats: ProdStats | DevStats): RequestHandler => (req: Request, res: Response): void => { const { nonce, props } = res.locals; const appStats = 'clientStats' in stats ? stats.clientStats : 'children' in stats ? stats.children.find((child) => child.name === 'client') : null; if (!appStats) { res.status(500); res.send('Internal Server Error: no application configured'); return; } const state = { ...props, ...searchParamsToStore(req.originalUrl.split('?')[1] || '') }; const { assetsByChunkName } = appStats; res.send( getPageHTML( nonce, state, [...getAssetByName(assetsByChunkName.vendor), ...getAssetByName(assetsByChunkName.app)].filter(Boolean) ) ); }; export default serverRender;