[英]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/
現在它起作用了。 但它適用於問題:加載時內容閃爍。
我如何理解頁面的加載過程:
我拍了一段視頻來說明這個過程。 (我很抱歉質量,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.