Webpack 4 和 react loadable 似乎没有为服务器端渲染创建正确的块
Posted
技术标签:
【中文标题】Webpack 4 和 react loadable 似乎没有为服务器端渲染创建正确的块【英文标题】:Webpack 4 and react loadable does not seems to create correct chunk for server side rendering 【发布时间】:2019-02-11 22:23:51 【问题描述】:我正在尝试使用延迟加载导入创建一个 s-s-r react 应用程序。 一切正常,除了它没有获取所有需要的块。
我也想知道这是否与基于服务器响应的动态组件有关
编辑 - 它实际上渲染了所有需要的块,但是当客户端接管并再次渲染时它会清除整个东西
由于它会重新渲染所有内容,因此速度会慢很多。
解析器发生在服务器端,当客户端接管时,它会获取更多 server.js
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.preloadAll().then(() =>
app.listen(PROD_PORT, (error) =>
)
);
客户端
Loadable.preloadReady().then(() =>
hydrate(
<Provider store=store>
<ConnectedRouter history=history>
<AppRoot />
</ConnectedRouter>
</Provider>,
domRoot,
)
)
分块设置
styles:
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true
,
欢迎任何意见或建议
有人建议尝试使用 window.onload = () => 但这种方法似乎也很慢。
【问题讨论】:
好问题。但我仍然没有任何想法。 【参考方案1】:您应该使用 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
)
这可以防止 react loadable 清除内容并重新渲染它。
要配置 Webpack 以根据动态加载的组件输出正确的块,请执行以下操作:
optimization:
splitChunks:
cacheGroups:
default: false,
vendors: false,
此配置在 Webpack v4 中适用于我。
您可以在此处找到使用 React 可加载服务器端渲染的完整文档:
https://github.com/jamiebuilds/react-loadable
【讨论】:
【参考方案2】:我正在使用react-universal-component 和flush chuck 的以路由为中心的代码拆分。对不起,长代码 sn-p/伪代码,我已尽力使其更短。 :)
先建一个数组,用于react router映射对应的组件
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 Component 中渲染路由器。
class App extends React.Component
render()
return (
<div>
<Switch>
routes.map( route => <Route key= route.path ...route />)
</Switch>
</div>
);
配置 webpack 定义代码拆分名称。
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
最后,server.js
将使用flush chuck 进行代码拆分。
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>`);
【讨论】:
【参考方案3】:你应该考虑使用 ReactLoadables-s-rAddon,它比 ReactLoadable see this link for further info 提供的插件效果更好。就我而言,它有很大的不同!
【讨论】:
【参考方案4】:如果您正在使用 ts-loader 尝试设置:
tsconfig.json
.
.
.
"module" : "esnext",
"moduleResolution": "Node",
.
.
.
【讨论】:
以上是关于Webpack 4 和 react loadable 似乎没有为服务器端渲染创建正确的块的主要内容,如果未能解决你的问题,请参考以下文章
使用分块对 React s-s-r 应用程序进行 A/B 测试