Reactjs Webpack 4和react loadable似乎无法为服务器端呈现创建正确的块
我正在尝试创建一个带有延迟加载导入的ssr react应用程序。 一切正常,除了它不能获取所有必需的块之外 我还想知道这是否与基于服务器响应的动态组件有关 Edit-它实际上渲染了所有需要的块,但当客户端接管并再次渲染时,它会抹去整个内容 因为它会重新渲染所有的内容,所以速度会慢很多 解析器发生在服务器端,当客户端接管时,它会获取更多信息 server.jsReactjs Webpack 4和react loadable似乎无法为服务器端呈现创建正确的块,reactjs,webpack,lazy-loading,webpack-4,Reactjs,Webpack,Lazy Loading,Webpack 4,我正在尝试创建一个带有延迟加载导入的ssr react应用程序。 一切正常,除了它不能获取所有必需的块之外 我还想知道这是否与基于服务器响应的动态组件有关 Edit-它实际上渲染了所有需要的块,但当客户端接管并再次渲染时,它会抹去整个内容 因为它会重新渲染所有的内容,所以速度会慢很多 解析器发生在服务器端,当客户端接管时,它会获取更多信息 server.js const history = createHistory({ initialEntries: [urlPath], })
const history = createHistory({
initialEntries: [urlPath],
})
// const history = createHistory()
const store = configureStore(history, {
location: {
...
},
})
const context = {}
const htmlRoot = (
<Provider store={store}>
<StaticRouter location={urlPath} context={context}>
<AppRoot />
</StaticRouter>
</Provider>
)
// pre fetching data from api
store
.runSaga(rootSaga)
.done.then(() => {
const RTS = renderToString(htmlRoot) + printDrainHydrateMarks()
const head = Helmet.renderStatic()
console.log(printDrainHydrateMarks())
res.status(code).send(renderDom(RTS, port, host, storeState, head))
}
})
.catch(e => {
console.log(e.message)
res.status(500).send(e.message)
})
renderToString(htmlRoot)
console.log(printDrainHydrateMarks())
store.close()
} else {
res.status(500).send(_err)
}
客户端
Loadable.preloadReady().then(() => {
hydrate(
<Provider store={store}>
<ConnectedRouter history={history}>
<AppRoot />
</ConnectedRouter>
</Provider>,
domRoot,
)
})
欢迎提出任何意见或建议
有人建议尝试使用window.onload=()=>{但这种方法似乎也会变慢。您应该使用ReactLoadablePlugin来创建可加载导入的列表:
new ReactLoadablePlugin({
filename: './build/react-loadable.json',
})
使用“react loadable capture”,您可以找出渲染时需要哪些动态组件,并可以将它们的包添加到头文件中:
const content = ReactDOMServer.renderToString(
<Loadable.Capture report={moduleName => modules.push(moduleName)}>
<Provider store={configureStore()}>
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
</Provider>
</Loadable.Capture>
);
let bundles = getBundles(stats, modules);
bundles.map((item) => {
//add js to header
})
此配置在WebpackV4中适用
您可以在此处找到使用React可加载服务器端渲染的完整文档:
我正在使用以路由为中心的代码拆分和。很抱歉,代码片段/伪代码太长,我已尽最大努力将其缩短。:) 首先构建一个阵列,用于映射相应的组件
let routeConfig = [
{path: '/foo', component: 'Foo'},
{path: '/bar', component: 'Bar'}
];
universal
函数确保可以在服务器端和客户端正确导入组件及其子组件。它足够智能,可以相应地延迟加载拆分的代码
import universal from 'react-universal-component';
const routes = routeConfig.map((item) =>{
let route = {};
route.path = item.path;
route.component = universal(import(`./container/${item.component}`), options);
return route;
});
在React组件中渲染路由器
class App extends React.Component {
render() {
return (
<div>
<Switch>
{routes.map( route => <Route key={ route.path } { ...route } />)}
</Switch>
</div>
);}}
最后,server.js
将用于代码拆分
const chunkNames = flushChunkNames();
const {js, styles, cssHash, scripts, stylesheets} = flushChunks(clientStats, {chunkNames});
res.send(`<!doctype html>
<html>
<head>
${styles}
</head>
<body>
<div id="root">${app}</div>
${cssHash}
${js}
</body>
</html>`);
const chunkNames=flushChunkNames();
const{js,styles,cssHash,scripts,stylesheets}=flushChunks(clientStats,{chunkNames});
res.send(`
${style}
${app}
${cssHash}
${js}
`);
你应该考虑使用RealAtdiabrRead RADON,它比ReaCudioLoad提供的插件工作得更好。在我的例子中,它产生了巨大的差异!
< P>如果你使用TS加载程序尝试设置:
tsconfig.json
{
.
.
.
"module" : "esnext",
"moduleResolution": "Node",
.
.
.
}
问得好,但我还是不知道。
class App extends React.Component {
render() {
return (
<div>
<Switch>
{routes.map( route => <Route key={ route.path } { ...route } />)}
</Switch>
</div>
);}}
output: {
filename: '[name].js',
chunkFilename: '[name].js',
path: path.resolve(__dirname, '../dist/client'),
publicPath: '/xxxxxx/'
},
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: '[name].css',
chunkFilename: '[id].css'
})],
optimization: {
splitChunks: {
chunks: 'initial',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor' // bundle all the npm module as vendor.js
}}}}
const chunkNames = flushChunkNames();
const {js, styles, cssHash, scripts, stylesheets} = flushChunks(clientStats, {chunkNames});
res.send(`<!doctype html>
<html>
<head>
${styles}
</head>
<body>
<div id="root">${app}</div>
${cssHash}
${js}
</body>
</html>`);
{
.
.
.
"module" : "esnext",
"moduleResolution": "Node",
.
.
.
}