Server-side rendering and async routing, blank flash on client side with react@16

Viewed 1729

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.

image

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

image

According to this next screenshot, the generated node from server side rendering will be remove. This node (div.home-page) is a dynamic component of the current route

image

So, 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 image

Before the blank frame, it's the rendered html, after it's the chunked HomePage.123456.js that is rendered

0 Answers
Related