# webpack 和 Code Splitting
今天讲一下 webpack 中的代码分割,
对于大的 Web 应用来讲,将所有的代码都放在一个文件中显然是不够有效的,特别是当你的某些代码块是在某些特殊的时候才会被使用到。webpack 有一个功能就是将你的代码库分割成 chunks(语块),当代码运行到需要它们的时候再进行加载。
显而易见能帮我们提升代码的性能,使用户体验更好。
实际上和 webpack 无关,webpack 只是可以帮助我们更简单的实现代码分割。两种方式:
# 举个🌰
首先我们安装一个 lodash ,
npm install lodash -D
接着我们在 index.js 中引入:
import _ from 'lodash';
console.log(_.join(['a', 'b', 'c'], '***'));
接着我们运行一下 npm run dev,开启服务:
我们看到:

我们也会发现打包后的 main.js 是 1.39MB:

我们会发现一个问题,如果我们引入了很多的第三方包,并同时都打包到 main.js 中的时候,main.js 会变得很大,用户加载这个文件也会变慢,所以我们在想如果这个类库能打包到各自的 js 中,并分别引入的话,这样就能提高性能,我们的 main.js 只需要管好自己的代码就行。
我们新建一个 lodash.js,这个文件的作用就是将 lodash 挂到 window 上。
// 加载lodash,挂载window 上
import _ from 'lodash';
window._ = _;
我们修改一下 index.js:
// import _ from 'lodash';
console.log(_.join(['a', 'b', 'c'], '***'));
接着我们修改一下 webpack 配置文件 webpack.common.js:
// ...
module.exports = {
entry: {
lodash: './src/lodash.js',
main: './src/index.js',
},
// ...
}
// ...
我们打包一下 npm run bundle,我们可以 dist 目录多生成了 lodash.js
我们可以看到各自的大小:

以及他们在 index.html 中的引入:

我们重新运行 npm run dev:我们可以看到在代码成功运行:


我们将 工具库函数 lodash 抽取到了 lodash.js,main.js 只负责我们的业务代码,这样当我们修改了相关的业务代码的时候,就不需要重新去打包 lodash.js 了,浏览器会缓存不变的代码,或者我们可以将其放到 cdn 上,
这样能使,性能更快,体验更好。
这是我们自己手动做的,我们看看 webpack 如何帮我们做代码分割。
# 两种方式
使用 webpack 帮我们做代码分割有两种方式。
# 同步引入,分割代码:
这个很简单只需要在 webpack.dev.js 中做 optimization 的配置即可。
// ...
optimization: {
splitChunks: {
chunks: 'all', // 公用的类库拆分,默认全部
}
},
// ...
我们将 webpack.common.js 中的 entry 中配置的 lodash 去掉。
// ...
module.exports = {
entry: {
main: './src/index.js',
},
// ...
}
// ...
接着我们重新打包一下 npm run bundle,我们可以看到 dist 下面的内容:
多了一个 vendors~main.js,我们打开看一波,其实这个文件就是对 lodash 的打包:

# 异步引入,分割代码(import):
异步代码引入切割代码,我们无需做任何配置,会自动进行代码分割,放置到新的文件中。
# 实现方式
CommonJs:使用require.ensure来实现ES6:动态import,我们接下去的例子
我们新建一个 async.js 文件,用于异步导入 lodash:
export default function getComponent() {
return import('lodash').then(({ default: _ }) => {
var element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'Darrell'], '-');
return element;
})
}
接着我们在 index.js 中引入使用:
import getComponent from './async.js'
getComponent().then(element => {
document.body.appendChild(element);
});
在打包出来的 dist 目录下多出了 0.js:
里面的内容就是 lodash.js:

# 注意点:
在早些 webpack 版本中是不支持 import('lodash').then() 这种方法的,打包过程中会报错,我们需要借助 babel 的一个插件 babel-plugin-dynamic-import-webpack 帮我们解决这个问题。
安装:
npm i babel-plugin-dynamic-import-webpack -D
在 .babelrc 中进行配置:
{
"presets": [
[
"@babel/preset-env",
{
useBuiltIns: 'usage'
}
],
"@babel/preset-react"
],
"plugins": ["dynamic-import-webpack"]
}
接着我们重新打包就可以使用这类语法了。
# 相关链接:
# 示例代码
示例代码可以看这里: