[英]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:我如何理解页面的加载过程:
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.