简体   繁体   English

React SSR 闪烁页面

[英]React SSR blinks page

I created a project with React, react-router, @loadable/component.我用 React、react-router、@loadable/component 创建了一个项目。

Now I'm trying to add SSR to this project.现在我正在尝试将 SSR 添加到这个项目中。 I did server side rendering with react-router.我使用 react-router 进行了服务器端渲染。

And then I added @loadable/component to import all pages component:然后我添加了 @loadable/component 来导入所有页面组件:

import loadable from '@loadable/component';

const routersConfig = [
  {
    path: '/',
    component: loadable(() => import('./Home')),
    exact: true,
  },
  {
    path: '/2',
    component: loadable(() => import('./Home2')),
    exact: true,
  },
];

Then I added all this parts of code: https://www.smooth-code.com/open-source/loadable-components/docs/server-side-rendering/然后我添加了所有这部分代码: https : //www.smooth-code.com/open-source/loadable-components/docs/server-side-rendering/

And now it works.现在它起作用了。 But It works with the problem: a content blinks while loading.但它适用于问题:加载时内容闪烁。

How I understand the page's loading process:我如何理解页面的加载过程:

  1. Browser gets a content generated by SSR (the first query in network tab)浏览器获取 SSR 生成的内容(网络选项卡中的第一个查询)
  2. Browser renders a content (with left and top margins )浏览器呈现内容(带有左和上边距)
  3. Browser downloads two enterpoints and vendors from html (app.js, normalizer.js, vendor.js)浏览器从html(app.js、normalizer.js、vendor.js)下载两个enterpoint和vendor
  4. Browser executes app.js and normalizer.js.浏览器执行 app.js 和 normalizer.js。 Left and top margins are removed.左边距和上边距被移除。
  5. App.js starts downloading page's chunk - home.js. App.js 开始下载页面的块 - home.js。 In this moment content disappears这一刻内容消失了
  6. When home.js is downloaded, the content appears again.下载 home.js 时,内容再次出现。

I shoot a video to illustrate this process.我拍了一段视频来说明这个过程。 (I'm sorry for quality, stackoverflow forbides files which size is more then 2MB ). (我很抱歉质量,stackoverflow 禁止大小超过 2MB 的文件)。 I'm throttling network speed to imagine all page's download process.我正在限制网络速度以想象所有页面的下载过程。

在此处输入图片说明

My question is why the content disappears?我的问题是为什么内容消失了? How to fix it?如何解决?

My code我的代码

server.js服务器.js

const sheetStyledComponents = new ServerStyleSheet();
  const sheetsJssRegistry = createSheetsRegistry();
  const statsFile = path.resolve(process.cwd(), './build-ssr/dist/loadable-stats.json');

  const extractor = new ChunkExtractor({
    statsFile,
    entrypoints: [
      'app',
      'normalize',
    ],
  });


  try {
    const client = ApolloSSRClient();

    const tree = (
      <ApolloProvider client={client}>
        <ApplyTheme sheetsRegistry={sheetsJssRegistry}>
          <StaticRouter location={req.url}>
            <Home />
          </StaticRouter>
        </ApplyTheme>
      </ApolloProvider>
    );

// there is combination of Apollo graphql, jss, styledComponent functions
    const body = await getMarkupFromTree({
      renderFunction: flow(
        sheetStyledComponents.collectStyles.bind(sheetStyledComponents),
        extractor.collectChunks.bind(extractor),
        renderToString
      ),
      tree,
    });

    const scriptTags = extractor.getScriptTags(); 
    // It isn't used yet
    const linkTags = extractor.getLinkTags(); 

    const styleTags = sheetStyledComponents.getStyleTags();

    const html = (await rawHtml)
      .replace(
        '</head>',
        ` 
          ${styleTags}
          <style type="text/css" id='jss-server-side-styles'>
              ${sheetsJssRegistry.toString()}
          </style>
          <script>
            window.__APOLLO_STATE__ = ${JSON.stringify(client.extract())};
          </script>
          ${scriptTags}
          </head>
        `
      )
      .replace('<div id="app"></div>', `<div id="app">${body}</div>`);


    res.send(html);

index.jsx索引.jsx

const SSRApp = (
  <ApolloProvider client={ApolloClient}>
    <ApplyTheme>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </ApplyTheme>
  </ApolloProvider>
);

loadableReady(() => (
  ReactDOM.hydrate(
    SSRApp,
    document.getElementById('app'),
  )
));

It was my fault.这是我的错。

The hydration version of app contained BrowserRouter -> Switch -> Router -> HomePage水化版app包含BrowserRouter -> Switch -> Router -> HomePage

And the SSR version contained only StaticRouter -> HomePage并且 SSR 版本仅包含StaticRouter -> HomePage

Because of this, after rendering SSR version, react removed all DOM and created new one with Router.因此,在渲染 SSR 版本后,react 移除了所有 DOM 并使用 Router 创建了新的 DOM。

i changed in server.js.我在 server.js 中改变了。 its worked for me它对我有用

yours maybe (server/index.js or server.js or server/app.js..etc)你的可能(server/index.js 或 server.js 或 server/app.js..etc)

import Express from 'express';
import Loadable from 'react-loadable';

// from //


  app.listen(3000, () => {
    console.log('app now listening on port', port);
  });


// to //

  import Loadable from 'react-loadable';

  Loadable.preloadAll().then(() => {
     app.listen(port, () => {
     console.log('app now listening on port', port);
   });
  });

for more config understanding you can see有关更多配置的理解, 您可以看到

The first step to rendering the correct content from the server is to make sure that all of your loadable components are already loaded when you go to render them.从服务器渲染正确内容的第一步是确保在渲染它们时所有可加载组件都已加载。

To do this, you can use the Loadable.preloadAll method.为此,您可以使用 Loadable.preloadAll 方法。 It returns a promise that will resolve when all your loadable components are ready.它返回一个承诺,当您的所有可加载组件准备就绪时,该承诺将得到解决。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM