code split代码分包(路由懒加载)
前言,在应用打包结果过大时,按照设置的规则打包到不同的bundle中,提高应用响应速度。也就是当一个页面进行加载的时候如果太慢,那么你就可以考虑对工程进行一个代码分包。
一、分包的作用
下面的截图就是不分包和分包的打包结果,可以很明显的看出
1、代码在没分包之前,整个工程的代码全部被打包到一个main.js里面,那么在访问某一个页面时,必然就会造成资源的浪费,和延长页面的加载时间。
2、代码分包之后,各个模块分开进行打包,main.js被拆分之后变的体积很小,页面在进行加载的时候,也会按需进行加载。
没有分包之前的打包结果:
分包后打包结果:
二、分包的方法
说起分包,其实总而言之,了解的方法主要就是两种。
i、Multi Entry 通过配置多入口,提取公共组件,来实现分包,这种一般情况是基于webpack配置。
ii、通过懒加载来实现代码分包,这种实现不需要在底层配置,操作起来也是比较方便的。
1、Multi Entry 通过配置多入口(基于webpack配置)
多入口打包Multi Entry 适用多页面应用 一个页面对应一个打包入口 公共部分提取
entry设置为对象{} 配置文件设置
module.exports = {
mode: 'none',
entry: {
index: './src/index.js', // 名称 : 路径
album: './src/album.js'
},
output: {
filename: '[name].bundle.js' // 动态生成打包结果的文件名 [name] 会自动获取入口文件名称
},
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'Multi Entry',
template: './src/index.html',
filename: 'index.html',
chunks: ['index'] // 用来设置生成的html使用指定的打包结果js
}),
new HtmlWebpackPlugin({
title: 'Multi Entry',
template: './src/album.html',
filename: 'album.html',
chunks: ['album']
})
]
}
提取公共模块部分配合多入口打包 这样重复的模块导入的模块就会被打包到一个文件中
optimization: {
splitChunks: {
// 自动提取所有公共模块到单独 bundle
chunks: 'all'
}
},
2、懒加载的方法(主要是针对于路由懒加载)
简单的来说下懒加载的方法(基于react,vue在路由中通过import动态导入组件就可以实现了),也比较实用。
i、require.ensure+getComponent方法,这种方法比较早,官方好像没有推荐这种。
routeConfig.js
const routeConfig = {
name1: (location, callback) => {
require.ensure([], (require) => {
callback(null, require('../containers/driver-appeal/entry/index').default);
}, 'code-split01');
},
name2: (location, callback) => {
require.ensure([], (require) => {
callback(null, require('../containers/driver-appeal/detail/index').default);
}, 'code-split02');
},
};
export default routeConfig;
index.js
import React from 'react';
import { Route } from 'react-router';
import Index from '../containers/index';
import routeConfig from './routeConfig';
export default (
<Route path="/service-center" component={Index}>
<Route path="new-customer-order/index" getComponent={routeConfig.name1} />
<Route path="driver-appeal/index" getComponent={routeConfig.name2} />
</Route>
);
ii、lazy+Suspense方法再配合import动态导入,官方比较推荐这种
index.js
/* eslint-disable max-len */
import React, { Suspense, lazy } from 'react';
import {
BrowserRouter as Router, Route, Switch,
} from 'react-router-dom';
import { createBrowserHistory } from 'history';
import Index from '@/containers/index';
const Home = lazy(() => import(/* webpackChunkName: "Home" */ '@/containers/home/entry'));
const Register = lazy(() => import(/* webpackChunkName: "Register" */ '@/containers/register/entry'));
const Login = lazy(() => import(/* webpackChunkName: "Login" */ '@/containers/login/entry'));
const history = createBrowserHistory();
const routes = (
<Router basename="/m-enterprise" history={history}>
<Index>
{/* fallback必填 可以设置页面跳转等待样式 */}
<Suspense fallback={<></>}>
<Switch>
<Route path="/home" component={MainHome} />
<Route path="/register" component={Register} />
<Route path="/login" component={Login} />
</Switch>
</Suspense>
</Index>
</Router>
);
export default routes;