簡體   English   中英

React SSR 閃爍頁面

[英]React SSR blinks page

我用 React、react-router、@loadable/component 創建了一個項目。

現在我正在嘗試將 SSR 添加到這個項目中。 我使用 react-router 進行了服務器端渲染。

然后我添加了 @loadable/component 來導入所有頁面組件:

import loadable from '@loadable/component';

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

然后我添加了所有這部分代碼: https : //www.smooth-code.com/open-source/loadable-components/docs/server-side-rendering/

現在它起作用了。 但它適用於問題:加載時內容閃爍。

我如何理解頁面的加載過程:

  1. 瀏覽器獲取 SSR 生成的內容(網絡選項卡中的第一個查詢)
  2. 瀏覽器呈現內容(帶有左和上邊距)
  3. 瀏覽器從html(app.js、normalizer.js、vendor.js)下載兩個enterpoint和vendor
  4. 瀏覽器執行 app.js 和 normalizer.js。 左邊距和上邊距被移除。
  5. App.js 開始下載頁面的塊 - home.js。 這一刻內容消失了
  6. 下載 home.js 時,內容再次出現。

我拍了一段視頻來說明這個過程。 (我很抱歉質量,stackoverflow 禁止大小超過 2MB 的文件)。 我正在限制網絡速度以想象所有頁面的下載過程。

在此處輸入圖片說明

我的問題是為什么內容消失了? 如何解決?

我的代碼

服務器.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);

索引.jsx

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

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

這是我的錯。

水化版app包含BrowserRouter -> Switch -> Router -> HomePage

並且 SSR 版本僅包含StaticRouter -> HomePage

因此,在渲染 SSR 版本后,react 移除了所有 DOM 並使用 Router 創建了新的 DOM。

我在 server.js 中改變了。 它對我有用

你的可能(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);
   });
  });

有關更多配置的理解, 您可以看到

從服務器渲染正確內容的第一步是確保在渲染它們時所有可加載組件都已加載。

為此,您可以使用 Loadable.preloadAll 方法。 它返回一個承諾,當您的所有可加載組件准備就緒時,該承諾將得到解決。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM