服务器端渲染和异步路由,客户端使用 react@16 的空白 flash

Mic*_*ngo 8 reactjs server-side-rendering react-router-v4

当我在服务器端呈现同步路由,然后客户端对 dom 进行水合时,我收到警告,因为客户端异步路由找不到组件。

图片

另一方面,反应纤维和解试图去除这个不可水合的节点。所以该页面在客户端产生一个空白的闪光:(

图片

根据下一个屏幕截图,服务器端渲染生成的节点将被删除。这个节点(div.home-page)是当前路由的动态组件

图片

那么,如何告诉reconciler不要移除这个节点,因为它会被动态导入的对应组件补水呢?

一些代码片段以获得更多解释

路线定义

import {
  HomePage,
} from '../bundles/Bundles';

export default [
  {
    component: HomePage,
    path: '/',
    exact: true,
    strict: true,
  },
];
Run Code Online (Sandbox Code Playgroud)

服务器端使用的 Bundles.js

export const HomePage = syncComponent('HomePage', require('../views/HomePage/HomePage'));
Run Code Online (Sandbox Code Playgroud)

客户端使用的 AsyncBundles.js

export const HomePage = asyncComponent('HomePage', () => Promise.all([
  import('../views/HomePage/HomePage' /* webpackChunkName: 'HomePage' */),
  importCss('HomePage'),
]));
Run Code Online (Sandbox Code Playgroud)

感谢NormalModuleReplacementPlugin webpack 插件,我可以从 Bundles.js 和 AsyncBundles.js 切换到服务器和客户端渲染

new webpack.NormalModuleReplacementPlugin(/Bundles\.js/, 'AsyncBundles.js')
Run Code Online (Sandbox Code Playgroud)

HomePage.js 组件渲染一个简单的 div

<div className="home-page">Home Page</div>
Run Code Online (Sandbox Code Playgroud)

渲染路由的主要 Wrapper.js

  <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>
    )}
  />
Run Code Online (Sandbox Code Playgroud)

服务器端生成的 html 如下所示:

<div class="app__wrapper">
  <div class="home-page">
    Home Page
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

当我打开 chrome 调试器时间线时,我得到一个闪烁的空白图片

在空白帧之前,它是呈现的 html,之后是呈现的分块 HomePage.123456.js