I am trying to create an ssr react app with lazy loading import. Everything works fine except it does not fetch all the required chunks.
I am also wondering if this is related to a dynamic component, which is base on server response
Edit - It actually renders all the required chunks but it wipes out the whole thing when client-side takes over and renders again
Since it re-renders all it slows down by a lot.
The parser happens on server-side and when client-side takes over it fetches more server.js
const history = createHistory({
initialEntries: [urlPath],
})
// const history = createHistory()
const store = configureStore(history, {
location: {
...
},
})
const context = {}
const htmlRoot = (
<Provider store={store}>
<StaticRouter location={urlPath} context={context}>
<AppRoot />
</StaticRouter>
</Provider>
)
// pre fetching data from api
store
.runSaga(rootSaga)
.done.then(() => {
const RTS = renderToString(htmlRoot) + printDrainHydrateMarks()
const head = Helmet.renderStatic()
console.log(printDrainHydrateMarks())
res.status(code).send(renderDom(RTS, port, host, storeState, head))
}
})
.catch(e => {
console.log(e.message)
res.status(500).send(e.message)
})
renderToString(htmlRoot)
console.log(printDrainHydrateMarks())
store.close()
} else {
res.status(500).send(_err)
}
Prod Server
Loadable.preloadAll().then(() => {
app.listen(PROD_PORT, (error) => {
})
});
Client side
Loadable.preloadReady().then(() => {
hydrate(
<Provider store={store}>
<ConnectedRouter history={history}>
<AppRoot />
</ConnectedRouter>
</Provider>,
domRoot,
)
})
Split Chunks setup
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true
},
Any opinion or advice is welcome please
Someone suggested to try with window.onload = () => { but this approach seems slow down as well.
You should use ReactLoadablePlugin to have a list of loadable imports:
new ReactLoadablePlugin({
filename: './build/react-loadable.json',
})
Using "react loadable capture", you can find out which dynamic components are needed while rendering and you can add their bundles to your header file:
const content = ReactDOMServer.renderToString(
<Loadable.Capture report={moduleName => modules.push(moduleName)}>
<Provider store={configureStore()}>
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
</Provider>
</Loadable.Capture>
);
let bundles = getBundles(stats, modules);
bundles.map((item) => {
//add js to header
})
This prevents react loadable from wiping out the content and rerendering it.
To config the Webpack to output right chunk based on dynamically loaded component do this:
optimization: {
splitChunks: {
cacheGroups: {
default: false,
vendors: false,
}
}
}
This configuration works for me in Webpack v4.
You can find a complete documentation to work with React loadable server-side rendering here:
https://github.com/jamiebuilds/react-loadable
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With