当我导航到嵌套路由时使用 React.js 延迟加载主包未加载
Using React.js lazy loading when I navigate to a nested route the main bundle doesn't load
我正在使用带有组件延迟加载的 React 路由器,并使用 Webpack 作为 bundler,当我访问主页时 /
我可以在网络选项卡中看到 bundle.js
已加载,并且当我单击侧边栏中的特定项目时,通讯组件已成功加载其文件名,例如 0.bundle.js
,但是,当我直接从搜索栏导航到嵌套路线(示例 http://127.0.0.1:8080/forms/select
)时,我收到如下错误:
GET http://127.0.0.1:8080/forms/bundle.js
net::ERR_ABORTED 404 (Not Found)
此错误表明 bundle.js
未加载,这意味着它无法加载其他块。
webpack.config.js
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
module: {
rules: [],
},
resolve: {
extensions: ['*', '.js', '.jsx'],
},
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: 'bundle.js',
},
plugins: [new webpack.HotModuleReplacementPlugin()],
devtool: 'cheap-module-eval-source-map',
devServer: {
contentBase: './dist',
hot: true,
historyApiFallback: true,
},
};
.babelrc
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": ["@babel/plugin-syntax-dynamic-import"]
}
routes.js
import { lazy } from 'react';
const Forms = lazy(() => import('../components/uiViews/Forms'));
const SelectForm = lazy(() => import('../components/uiViews/Forms/SelectForm'));
const FormValidation = lazy(() => import('../components/uiViews/Forms/FormValidation'));
const routes = [
{
icon: 'form',
label: 'forms',
path: '/forms',
component: Forms,
children: [
{
icon: 'select',
label: 'selectInput',
path: '/forms/select',
component: SelectForm,
},
{ icon: 'issues-close', label: 'formValidation', path: '/forms/validation', component: FormValidation },
{
icon: 'form',
label: 'wizardForm',
path: '/forms/wizard',
component: WizardForm,
}],
},
];
export default routes;
路由渲染
<Suspense fallback={<div className="spin-loading"> <Spin size="large" /></div>}>
{routes.map((route, i) => {
return route.component ? RouteWithSubRoutes( {...route},`r${i}`) : null;
})}
</Suspense>
....
function RouteWithSubRoutes(route,key) {
return route.children ? (
route.children.map((subRoute,j) => {
return RouteWithSubRoutes(subRoute,`sr${j}`);
})
) : (
<Route key={key} path={route.path} exact component={() =>route.component? <route.component />:<ComingSoon/>} />
);
}
经过几天尝试不同的解决方案后,我终于找到了 this one 来拯救我的一天:
... I finally figured out the actual issue and it is not directly related to either Webpack or React Hot Loader or React Router or any other library at least for now at least for me. When using HTML5 push state to manipulate browsers history WE MUST PROVIDE tag in our html head section. After providing to the head section of my html, HMR works like a charm even in nested routes.
<!DOCTYPE html>
<html>
<head>
<base href="/" /> <!-- THIS TINY LITTLE THING -->
<meta charset="UTF-8" />
<title>Hello React!</title>
</head>
<body>
<div id="root"></div>
<script src="/main.bundle.js"></script>
</body>
</html>
我正在使用带有组件延迟加载的 React 路由器,并使用 Webpack 作为 bundler,当我访问主页时 /
我可以在网络选项卡中看到 bundle.js
已加载,并且当我单击侧边栏中的特定项目时,通讯组件已成功加载其文件名,例如 0.bundle.js
,但是,当我直接从搜索栏导航到嵌套路线(示例 http://127.0.0.1:8080/forms/select
)时,我收到如下错误:
GET
http://127.0.0.1:8080/forms/bundle.js
net::ERR_ABORTED 404 (Not Found)
此错误表明 bundle.js
未加载,这意味着它无法加载其他块。
webpack.config.js
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
module: {
rules: [],
},
resolve: {
extensions: ['*', '.js', '.jsx'],
},
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: 'bundle.js',
},
plugins: [new webpack.HotModuleReplacementPlugin()],
devtool: 'cheap-module-eval-source-map',
devServer: {
contentBase: './dist',
hot: true,
historyApiFallback: true,
},
};
.babelrc
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": ["@babel/plugin-syntax-dynamic-import"]
}
routes.js
import { lazy } from 'react';
const Forms = lazy(() => import('../components/uiViews/Forms'));
const SelectForm = lazy(() => import('../components/uiViews/Forms/SelectForm'));
const FormValidation = lazy(() => import('../components/uiViews/Forms/FormValidation'));
const routes = [
{
icon: 'form',
label: 'forms',
path: '/forms',
component: Forms,
children: [
{
icon: 'select',
label: 'selectInput',
path: '/forms/select',
component: SelectForm,
},
{ icon: 'issues-close', label: 'formValidation', path: '/forms/validation', component: FormValidation },
{
icon: 'form',
label: 'wizardForm',
path: '/forms/wizard',
component: WizardForm,
}],
},
];
export default routes;
路由渲染
<Suspense fallback={<div className="spin-loading"> <Spin size="large" /></div>}>
{routes.map((route, i) => {
return route.component ? RouteWithSubRoutes( {...route},`r${i}`) : null;
})}
</Suspense>
....
function RouteWithSubRoutes(route,key) {
return route.children ? (
route.children.map((subRoute,j) => {
return RouteWithSubRoutes(subRoute,`sr${j}`);
})
) : (
<Route key={key} path={route.path} exact component={() =>route.component? <route.component />:<ComingSoon/>} />
);
}
经过几天尝试不同的解决方案后,我终于找到了 this one 来拯救我的一天:
... I finally figured out the actual issue and it is not directly related to either Webpack or React Hot Loader or React Router or any other library at least for now at least for me. When using HTML5 push state to manipulate browsers history WE MUST PROVIDE tag in our html head section. After providing to the head section of my html, HMR works like a charm even in nested routes.
<!DOCTYPE html> <html> <head> <base href="/" /> <!-- THIS TINY LITTLE THING --> <meta charset="UTF-8" /> <title>Hello React!</title> </head> <body> <div id="root"></div> <script src="/main.bundle.js"></script> </body> </html>