webpack
可优化配置教程
量化
如何直观的查看优化的效果,这时就需要用到 speed-measure-webpack-plugin 插件,该插件可以测量各个插件和loader所花费的时间,使用之后,构建时,会得到类似下面这样的信息:
使用方法:
1 | //webpack.config.js |
exclude/include cache-loader alias noParse extensions resolve
alias
- 当我们代码中出现 import ‘vue’ 时, webpack 会采用向上递归搜索的方式去node_modules 目录下找。为了减少搜索范围我们可以直接告诉webpack去哪个路径下查找。也就是别名(alias)的配置
exclude/include
- exclude的优先级要高于include,支持正则或指定路径传入
noParse
- 如果一些第三方模块没有 AMD/CommonJS 规范版本,可以使用 noParse 来标识这个模块,这样 Webpack 会引入这些模块,但是不进行转化和解析,从而提升 Webpack 的构建性能 ,例如:jquery 、lodash。
extensions
- webpack会根据extensions定义的后缀查找文件(频率较高的文件类型优先写在前面)
resolve
- resolve 配置 webpack 如何寻找模块所对应的文件。
cache-loader
在一些性能开销较大的 loader 之前添加 cache-loader,将结果缓存中磁盘中。默认保存在 node_modueles/.cache/cache-loader 目录下。
首先安装依赖:npm install cache-loader -D
cache-loader 的配置很简单,放在其他 loader 之前即可。修改Webpack 的配置如下:
1 | module.exports = { |
也可以不使用cache-loader,而给对应 loader 添加 cacheDirectory 配置也能实现缓存
cacheDirectory:默认值为 false。当有设置时,指定的目录将用来缓存 loader 的执行结果。之后的 Webpack 构建,将会尝试读取缓存,来避免在每次执行时,可能产生的、高性能消耗的 Babel 重新编译过程。设置空值或者 true 的话,使用默认缓存目录:node_modules/.cache/babel-loader 。开启 babel-loader 的缓存和配置 cache-loader,我比对了下,构建时间很接近。
happyPack
在 webpack 构建过程中,实际上耗费时间大多数用在 loader 解析转换以及代码的压缩中。日常开发中我们需要使用 Loader 对js,css,图片,字体等文件做转换操作,并且转换的文件数据量也是非常大。由于js单线程的特性使得这些转换操作不能并发处理文件,而是需要一个个文件进行处理。HappyPack 的基本原理是将这部分任务分解到多个子进程中去并行处理,子进程处理完成后把结果发送到主进程中,从而减少总的构建时间
thread-loader
除了使用 Happypack 外,我们也可以使用 thread-loader ,把 thread-loader 放置在其它 loader 之前,那么放置在这个 loader 之后的 loader 就会在一个单独的 worker 池中运行。
在 worker 池(worker pool)中运行的 loader 是受到限制的。例如:
- 这些 loader 不能产生新的文件。
- 这些 loader 不能使用定制的 loader API(也就是说,通过插件)。
- 这些 loader 无法获取 webpack 的选项设置。
安装:npm install thread-loader -D
1 | module.exports = { |
thread-loader 和 Happypack构建时间没什么区别,不过 thread-loader 配置更简单一些。
externals
我们可以将一些JS文件存储在 CDN 上(减少 Webpack 打包出来的 js 体积),在 index.html 中通过 <script>
标签引入,如:
1 | <!DOCTYPE html> |
我们希望在使用时,仍然可以通过 import 的方式去引用(如 import $ from ‘jquery’ ),并且希望 webpack 不会对其进行打包,此时就可以配置 externals 。
1 | //webpack.config.js |
DLL
DllPlugin 和 DLLReferencePlugin 可以实现拆分 bundles,并且可以大大提升构建速度,DllPlugin 和 DLLReferencePlugin 都是 webpack 的内置模块。
我们新建一个 webpack 的配置文件,来专门用于编译动态链接库,例如名为: webpack.config.dll.js
1 | //webpack.config.dll.js |
在 package.json 的 scripts 中增加: "build:dll": "webpack --config webpack.config.dll.js"
manifest.json 用于让 DLLReferencePlugin 映射到相关依赖上。
接着更改 webpack.config.js 中的配置:
1 | //webpack.config.js |
使用 npm run build 构建,可以看到 bundle.js 的体积大大减少
修改 index.html 文件,在其中引入 react.dll.js
<script src="/dll/react.dll.9dcd9d.js"></script>
包的体积
splitChunks
splitChunks
对于项目越来越大,抽离公共代码就越显得重要,公共代码只需要下载一次就缓存起来了,避免了重复下载。
抽离公共代码对于单页应用和多页应该在配置上没有什么区别,都是配置在 optimization.splitChunks 中。假如我们不配置splitChunks,默认打包出来的是 bundle.js
1 | //webpack.config.js |
runtimeChunk
runtimeChunk 的作用是将包含 chunk 映射关系的列表从 main.js 中抽离出来,在配置了 splitChunk 时,记得配置 runtimeChunk.
1 | module.exports = { |
最终构建出来的文件中会生成一个 manifest.js。
webpack-bundle-analyzer
此时借助 webpack-bundle-analyzer 可以分析项目中哪些包可以拆分
使用方法:
1 | //webpack.config.prod.js |
这时我们可以对 vender 拆分
1 | module.exports = { |
重新构建,结果如下所示:
结语
参考帖子: