Code Splitting
是什么
code splitting(代码分离)是 webpack 中最引人注目的特性之一。此特性能够把代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件。代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间。
首先,我们先不管webpack中的code splitting,我们先说一下日常开发中我们会做出的code splitting的操作。
我们就拿熟识的插件库 **lodash.js **来做下试验。
先安装一下lodash
npm install lodash -S
然后在 **main.js **中引入,并使用其中的一个方法
import _ from 'lodash'
console.log(_.join(['a', 'b', 'c']))
为了方便测试,我们新增一种打包命令
"dev-build": "webpack --config ./build/webpack.dev.js"
执行完命令后我们查看一下dist目录下的main.js,可以发现,lodash的内容被打包到里面了。
假如说,lodash的体积为(1MB)我们的业务代码比较大(1MB)
那么用户访问一次main.js就要加载 1MB+1MB=2MB的文件。这个文件的加载时间就会很长。
还有一种问题。lodash我们引入后通常是不会改变的,但是我们的业务代码改变很频繁,这意味着我们每改一次业务代码,用户就要重新加载一遍 lodash + 业务代码 。这不是我们所期望的,下面就说一下如何解决这个问题。
首先我们新建一个lodash.js,在其中引入并挂载到window上。
import _ from 'lodash'
window._ = _
然后我们修改一下webpack配置文件的entry配置项
entry: {
lodash: path.resolve(__dirname, '../src/lodash.js'),
main: path.resolve(__dirname, '../src/main.js')
},
然后我们执行打包命令,可以看到,index.html中分别引入了lodash.js和main.js,这样我们就解决了刚才说的那个问题。
entry的顺序影响index.html的引入顺序
以上就是我们在日常开发中可以进行的手动的code splitting,但是这样做的话会很麻烦,有没有一种插件能够自动帮我们实现代码分离的功能,接下来介绍一下webpack4中能为我们自动进行代码分离的插件。
SplitChunksPlugin
是什么
起初,chunks(代码块)和导入他们中的模块通过webpack内部的父子关系图连接.在webpack3中,通过CommonsChunkPlugin来避免他们之间的依赖重复。而在webpack4中CommonsChunkPlugin被移除,取而代之的是 optimization.splitChunks 和 optimization.runtimeChunk 配置项,下面展示它们将如何工作。
简而言之就是“公共模块抽取插件”
怎么使用
首先,将main.js 恢复到最开始引入lodash时候的样子,把webpack中配置的lodash也删除掉。
import _ from 'lodash'
console.log(_.join(['a', 'b', 'c']))
然后在 **webpack.common.js **中新增配置项
optimization:{
splitChunks:{
chunks: 'all'
}
}
执行打包命令,可以看到dist下面多出来一个文件**vendorsmain.js **。main.js **发现 lodash 相关代码这这里。
然后查看 **main.js **中已经没有 **lodash 相关的代码。
查看vendors
main.js
vendors~main.js
也就是说我们的配置已经生效了,通过上面的配置,webpack可以自动的把这样的类库识别,并单独打包生成一个文件。
懒加载
在main.js中我们也可以这么写
const getLodash = () => import('lodash')
getLodash()
这样的引入是异步,让我们来看一下会不会正常打包,执行以下打包命令
可以看到是可以正常打包的,并且这个文件里面是lodash相关代码。
现在这个文件名字是 code splitting产生的id值+.js,我们能不能给目标文件设置一个我们预设的名字。
在异步加载的组件中有一种语法叫做 **Magic Comment **(魔法注释)可以实现我们的想法。我们这么写
const getLodash = () => import(/* webpackChunkName:"lodash" */ 'lodash')
getLodash()
这样的话进行打包后原来的 0.js 改变为 vendors~lodash.js
文件名还不是我们想要的干净的lodash.js,怎么改呢,下一章会介绍SplitChunksPlugin的配置项来解决这个问题。
dynamic-import-webpack是非官网插件 在最新的babel中可以通过@babel/plugin-syntax-dynamic-import来实现这以功能,也可以通过@babel/preset-env配合core-js@3来实现此功能。
总结
- 代码分割,和webpack无关
- webpack中实现代码分割,两种方式
- 同步代码: 只需要在webpack.common.js中做optimization的配置即可
- 异步代码(import): 异步代码,无需做任何配置,会自动进行代码分割,放置到新的文件中