Hi!
When I render a synchronous route on server-side and then the client side hydrate the dom, I get a warning because client side asynchronous route doesn't find the component.

In other hand react fiber reconciliation tries to remove this non hydratable node. So the page makes a blank flash on client side :(


According to this screenshot, the generated node from server side rendering will be remove. This node (div.home-page) is a dynamic component of the current route
How can I tell the reconciler to not remove this node, because it will be hydrated by the dynamic imported corresponding component?
Some code snippets for more explanations
Routes definition
import {
HomePage,
} from '../bundles/Bundles';
export default [
{
component: HomePage,
path: '/',
exact: true,
strict: true,
},
];
The Bundles.js used on server side
export const HomePage = syncComponent('HomePage', require('../views/HomePage/HomePage'));
The AsyncBundles.js used on client side
export const HomePage = asyncComponent('HomePage', () => Promise.all([
import('../views/HomePage/HomePage' /* webpackChunkName: 'HomePage' */),
importCss('HomePage'),
]));
Thanks to the NormalModuleReplacementPlugin webpack plugin I'm able to switch from Bundles.js and AsyncBundles.js for server and client rendering
new webpack.NormalModuleReplacementPlugin(/Bundles\.js/, 'AsyncBundles.js'),
HomePage.js component renders a simple div
<div className="home-page">Home Page</div>
The main Wrapper.js that renders the routes
<Route
render={({ location }) => (
<div className="app__wrapper">
<Switch location={location}>
{routes.map((route, index) => (
<Route
key={route.path}
path={route.path}
exact={route.exact}
render={route.component}
/>
))}
<Route
key={'not found'}
path={'*'}
render={NotFound}
/>
</Switch>
</div>
)}
/>
The html generated on server-side looks like this:
<div class="app__wrapper">
<div class="home-page">
Home Page
</div>
</div>
When I open the chrome debugger timeline, I get a flashing blank frame

Before the blank frame, it's the rendered html, after it's the chunked HomePage.123456.js that is rendered
That is fiber warning on client side: Did not expect server HTML to contain div.home-page in div.app__wrapper ... and removes it before rendering the exact same dynamic imported HomePage.js
This pattern has never worked correctly. In React 15 it would still blow away your server rendered markup and replace it on the client.
The solution is to render the same thing both on the client and the server side (just like before). If you're using Promises on the client side, you need to wait for them to resolve before doing hydration. This is not an easy problem, but it's outside of scope of React. Projects like https://github.com/thejameskyle/react-loadable can help you with handling this correctly.
Thanks! I am looking at another one https://github.com/ctrlplusb/react-async-component
Most helpful comment
This pattern has never worked correctly. In React 15 it would still blow away your server rendered markup and replace it on the client.
The solution is to render the same thing both on the client and the server side (just like before). If you're using Promises on the client side, you need to wait for them to resolve before doing hydration. This is not an easy problem, but it's outside of scope of React. Projects like https://github.com/thejameskyle/react-loadable can help you with handling this correctly.