SSR: dynamic import in react app how to deal with html miss match when component is loading on the client
Asked Answered
A

1

6

I'm just starting on server side rendering a react 16 app using code splitting and dynamic import thanks to webpack 4 and react-loadable.

My question might sound stupid but there's something I don't quite get.

On the server side, I'm waiting that webpack has loaded all modules before spitting out the html to the client.

On the client side I have a kind of loading component rendered, before rendering the loaded component.

So basically the server renders the loaded component:

<div>loaded component</div>

And the client hydrates the loading component:

<div>loading...</div>

Obviously, The problem is that React complains after hydrate() because there is a miss match between server and client.

During a few seconds the client first renders

<div>loading...</div>

whereas server has rendered and sent to the client, the html of the loaded component.

Can someone enlighten me ? how does it work exactly ? How can I prevent a mismatch at first render when the component is being loaded ?

Abatement answered 7/11, 2018 at 18:16 Comment(0)
S
3

Looks like you're not preloading the assents in you client.

Loadable.preloadReady().then(() => {
  ReactDOM.hydrate(<App/>, document.getElementById('app'));
});

This is also a required step to avoid the hydration mismatch.

Reason:

This issue is caused on your client because the initial request, your chunks were not loaded, so the html output for those components would be loading... instead of the component content itself. Only after the chunks are fetched and loaded that this initial state loading... will be replaced by the desired content.

So, Loadable.preloadReady method creates a Promise that will be resolved once the application chunks were preloaded, in that way, having all assets needed for the initial stage, ReactDOM.hydrate will generate the same output as your server did.


TIP

Also I recommend you to take a look at React Loadable SSR Add-on, it is a very handy add-on that will enhance your server side assets management, giving you the same benefits as it was CSR (Client Side Render).

Server Side Render add-on for React Loadable. Load splitted chunks was never that easy.

See https://github.com/themgoncalves/react-loadable-ssr-addon

Stander answered 19/11, 2018 at 12:11 Comment(4)
Goncalves I do preload chunks on the client. What I've found out is that __webpack_modules__[moduleId] is always undefined so resolveWeak does not happen. You can reproduce the issue there: github.com/jaybe78/react-loadable.Abatement
It's still quite confusing to me, but from what i've understood resolveWeak used in combination with import, would allow to render the chunk on the client synchronously, after component has been loaded, without that mismatch would occur. Because basically at initial rendering on the client, it will render <loading /> which is different than what server rendered, but then it will render again, (this time the loadable component), and this is resolveWeak comes in action to synchronously render on client side. Am right !?Abatement
@Abatement have you imported react-loadable/babel too .babelrc plugin configuration? Basically this issue of resolveWeak is related to the loadable configuration.Worsham
The correct way to use react-loadable is as following bellow: Loadable({ loader: () => import('./Bar'), modules: ['./Bar'], webpack: () => [require.resolveWeak('./Bar')], }); But if you just adds the react-loadable/babel to you babel configuration, you don't have to specify modules and webpack keys every single time, it will be handled automatically by this plugin. Documentation: github.com/jaybe78/…Worsham

© 2022 - 2024 — McMap. All rights reserved.