我正在尝试使用延迟加载导入创建ssr react应用。 一切正常,除了不获取所有必需的块
我还想知道这是否与基于服务器响应的动态组件有关
enter code here
编辑-实际上,它渲染了所有必需的块,但是当客户端接管并再次渲染时,它会擦除整个内容
由于它重新渲染了所有内容,因此减慢了很多速度。
解析器发生在服务器端,当客户端接管它时,它将获取更多信息 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 =()=> {,但是这种方法似乎也很慢。
答案 0 :(得分:0)
您应该使用ReactLoadablePlugin来获得可加载导入的列表:
new ReactLoadablePlugin({
filename: './build/react-loadable.json',
})
使用“可加载的反应捕获”,您可以找出渲染时需要哪些动态组件,并将其捆绑包添加到头文件中:
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
})
这可以防止可加载的反应擦除内容并重新呈现。
要将Webpack配置为基于动态加载的组件输出正确的块,请执行以下操作:
optimization: {
splitChunks: {
cacheGroups: {
default: false,
vendors: false,
}
}
}
此配置在Webpack v4中对我有效。
您可以在此处找到与React可加载服务器端渲染一起使用的完整文档:
答案 1 :(得分:0)
我正在使用react-universal-component和flush chuck进行以路由为中心的代码拆分。很抱歉,很长的代码段/伪代码,我已尽力将其缩短。 :)
首先构建一个数组,用于反应路由器映射相应的组件
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>`);
答案 2 :(得分:0)
您应该考虑使用ReactLoadableSSRAddon,它比ReactLoadable see this link for further info提供的插件更好。就我而言,这有很大的不同!
答案 3 :(得分:0)
如果您使用的是 ts-loader 尝试设置:
tsconfig.json
{
.
.
.
"module" : "esnext",
"moduleResolution": "Node",
.
.
.
}