基于CRA与React Router v3,如何拆分公共/登录用户双代码包?
实现CRA+react-router v3下的两类代码包拆分
嘿,刚好有过类似的实践经验,给你捋捋怎么在react-router v3 + CRA里实现这个拆分需求!核心思路是利用webpack的动态导入+命名chunk特性,把登录后页面统一打包到一个单独的chunk里,公共首页留在主bundle中。
核心原理
CRA默认支持webpack的动态导入语法import(),并且通过/* webpackChunkName: "xxx" */注释可以指定chunk名称——所有用同一个名称的动态导入模块,会被webpack合并到同一个chunk文件里。而react-router v3的getComponent方法刚好支持异步加载组件,完美适配这个需求。
具体实现步骤
1. 封装异步加载组件(可选但推荐)
先写一个复用的高阶组件,避免每个路由都重复写异步加载逻辑,还能处理加载状态:
// src/utils/asyncComponent.js import React from 'react'; const asyncComponent = (importComponent) => { return React.createClass({ getInitialState() { return { component: null }; }, componentDidMount() { importComponent() .then(module => this.setState({ component: module.default })) .catch(err => console.error('组件加载失败:', err)); }, render() { const TargetComponent = this.state.component; return TargetComponent ? <TargetComponent {...this.props} /> : <div>加载中...</div>; }, }); }; export default asyncComponent;
2. 配置路由拆分
把公共首页直接引入作为主bundle的一部分,登录后的所有页面都用上面的异步组件加载,并且指定同一个chunk名称(比如"logged-in"):
// src/routes.js import React from 'react'; import { Route, IndexRoute } from 'react-router'; import Home from './pages/Home'; // 公共首页,主bundle import asyncComponent from './utils/asyncComponent'; // 登录后页面:统一指定chunk名为"logged-in" const Dashboard = asyncComponent(() => import(/* webpackChunkName: "logged-in" */ './pages/Dashboard')); const Profile = asyncComponent(() => import(/* webpackChunkName: "logged-in" */ './pages/Profile')); const Settings = asyncComponent(() => import(/* webpackChunkName: "logged-in" */ './pages/Settings')); // 路由配置 export default ( <Route path="/"> <IndexRoute component={Home} /> {/* 登录后路由,加上登录校验的onEnter钩子 */} <Route path="/dashboard" component={Dashboard} onEnter={requireAuth} /> <Route path="/profile" component={Profile} onEnter={requireAuth} /> <Route path="/settings" component={Settings} onEnter={requireAuth} /> </Route> ); // 示例登录校验钩子 function requireAuth(nextState, replace) { if (!localStorage.getItem('userToken')) { replace('/'); } }
3. 验证拆分结果
运行npm run build打包后,进入build/static/js目录,你会看到:
- 主bundle文件(比如
main.xxxxxx.js):包含首页、公共组件、路由配置等核心代码 - 命名chunk文件(比如
logged-in.xxxxxx.js):包含所有登录后页面的代码
这样就完美实现了你要的“公共首页包+登录用户页面包”的拆分需求!
注意事项
- react-router v3的
getComponent方法本身也支持直接写异步逻辑,如果你不想封装高阶组件,也可以直接在路由里用getComponent:
<Route path="/dashboard" getComponent={(nextState, callback) => { import(/* webpackChunkName: "logged-in" */ './pages/Dashboard') .then(module => callback(null, module.default)) .catch(err => callback(err)); }} onEnter={requireAuth} />
- CRA不需要额外配置webpack,它已经默认支持
webpackChunkName注释,直接用就行。
内容的提问来源于stack exchange,提问作者Hedge
相关产品推荐
相关产品推荐

