Created
September 8, 2018 08:45
-
-
Save ndelitski/0a526c14c28ba067f5668e000c19bfa6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { matchRoutes } from 'react-router-config' | |
import { flatMap, values } from 'lodash' | |
import { createMemoryHistory } from 'history' | |
import { wrapRootEpic } from 'react-redux-epic' | |
import createStore from 'app/createStore' | |
import { featureTypes } from 'client/checkFeature' | |
import renderHtmlPage from './renderHtml' | |
import { normalizeAssets, orderAssets, normalizeStore } from './utils' | |
import renderRoute from './renderRoute' | |
export default ({ routes, frankTheme, muiTheme, reducer, epic }) => { | |
const ssrOnlyRoutes = routes.filter(route => route.ssr) | |
const isSSREnabled = process.env.SSR === 'true' | |
const isProduction = process.env.NODE_ENV === 'production' | |
const defaultFeatures = isProduction | |
? '' | |
: [featureTypes.layoutGrids].join(',') | |
const enabledClientFeatures = ( | |
process.env.CLIENT_FEATURES || defaultFeatures | |
).split(/[,\s]/g) | |
const fontsUrls = frankTheme.fontFaces.map(({ resources }) => resources.woff) | |
function getWebpackData(stats) { | |
const assets = stats.assetsByChunkName | |
const publicPath = stats.publicPath | |
const manifest = {} | |
// if (process.NODE_ENV === 'production') { | |
// // eslint-disable-next-line import/no-dynamic-require,global-require | |
// manifest = require(path.join( | |
// __dirname, | |
// '..', | |
// 'src', | |
// 'server', | |
// 'manifest.json' | |
// )) | |
// } else { | |
// manifest = JSON.parse( | |
// fs.readFileSync( | |
// path.join(__dirname, '..', 'src', 'server', 'manifest.json') | |
// ) | |
// ) | |
// } | |
const jsAssets = orderAssets( | |
flatMap(values(assets).map(normalizeAssets)) | |
.filter(file => file.match(/\.js$/)) | |
.map(filePath => publicPath + filePath) | |
) | |
const prefetchScripts = [...jsAssets] | |
return { | |
jsAssets, | |
webpackManifest: manifest, | |
prefetchScripts, | |
} | |
} | |
function getWebpackProdData(stats) { | |
// const publicPath = __PUBLIC_PATH || '/assets/' // TODO | |
// eslint-disable-next-line global-require | |
// eslint-disable-next-line global-require | |
// const webpackManifest = require('./manifest.json') | |
const jsAssets = orderAssets(values(stats).map(({ js }) => js)) | |
const prefetchScripts = [ | |
...jsAssets, | |
// ...values(webpackManifest).map(filePath => publicPath + filePath), | |
] | |
return { | |
jsAssets, | |
webpackManifest: {}, | |
prefetchScripts, | |
} | |
} | |
return ({ clientStats }) => (req, res, next) => { | |
const { url, httpClient, graphqlClient, user } = req | |
const isSSRUrl = !!matchRoutes(ssrOnlyRoutes, req.path).length | |
const memoryHistory = createMemoryHistory({ initialEntries: [url] }) | |
const wrappedEpic = wrapRootEpic(epic) | |
const initialState = { auth: { user } } | |
const csrfToken = req.csrfToken() | |
const nonce = res.locals.nonce | |
if (isSSREnabled && isSSRUrl) { | |
const store = createStore({ | |
reducer, | |
initialState, | |
history: memoryHistory, | |
epic: wrappedEpic, | |
dependencies: { | |
http: httpClient, | |
graphql: graphqlClient, | |
}, | |
isServer: true, | |
}) | |
renderRoute({ | |
url, | |
frankTheme, | |
muiTheme, | |
store, | |
httpClient, | |
graphqlClient, | |
wrappedEpic, | |
}) | |
.then(({ markup, helmet, criticalPathCSS, context: routerContext }) => { | |
if (routerContext.url) { | |
res.redirect(routerContext.url) | |
return | |
} | |
if (routerContext.status) { | |
res.status(routerContext.status) | |
} | |
const html = renderHtmlPage({ | |
markup, | |
csrfToken, | |
inlineScriptNonce: nonce, | |
helmet, | |
criticalPathCSS, | |
fontsUrls, | |
store: normalizeStore(store), | |
features: enabledClientFeatures, | |
// TODO normalize clientStats to one format and make single function | |
...(isProduction | |
? getWebpackProdData(clientStats) | |
: getWebpackData(clientStats)), | |
}) | |
res.send(html) | |
}) | |
.catch(next) | |
} else { | |
const html = renderHtmlPage({ | |
csrfToken, | |
inlineScriptNonce: nonce, | |
store: initialState, | |
fontsUrls, | |
features: enabledClientFeatures, | |
...(isProduction | |
? getWebpackProdData(clientStats) | |
: getWebpackData(clientStats)), | |
}) | |
res.send(html) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment