随着项目的发展,项目目录会越来越大,各种库也会越来越多,会直接导致Webpack的构建效率极低,比如下面的例子:1
2
3
4
5
6
7$ webpack
Hash: 6aa4a418e100b6563347
Version: webpack 3.5.5
Time: 20199ms
Asset Size Chunks Chunk Names
index.js 4.27 MB 0 [emitted] index
+ 395 hidden modules
可以看到,在这个项目中有大量的模块,构建一次的时间长达20秒,这显然是不可接受的。
慢在哪里
有很多工具提供了可视化的分析,如Webpack-bundle-analyzer、webpack-chart、 webpack-analyse。
以Webpack-bundle-analyzer为例,它提供了一个下图所示的图表,展示了引入的所有模块的大小、路径等信息,可以针对性的做出优化。
使用上也很简单:
1 | // 全局安装: |
1 | // webpack.config.js 配置 |
运行webpack
命令,会自动在浏览器中打开http://127.0.0.1:8888/
页面,展示可视化图表。
具体优化
1. 使用DllPlugin
拆分模块
开发过程中,我们经常需要引入大量第三方库,这些库并不需要随时修改或调试,我们可以使用DllPlugin
和DllReferencePlugin
单独构建它们。
具体使用如下:
1 | const HtmlWebpackPlugin = require('html-webpack-plugin'); |
执行webpack
命令,build
目录下即可生成 dll.js
文件和对应的 manifest
文件,使用 DLLReferencePlugin
引入:
1 | plugins: [ |
2. 使用 externals
通过CDN引入第三方库
Webpack提供了 externals
的方式来引入第三方库,我们可以在 HTML 文件中直接使用 script 标签的形式来引入:
1 | <script src="//cdn.bootcss.com/react.min.js"></script> |
在 Webpack 中如下配置即可:
1 | externals: { |
和 dll 的打包方式相比,主要有以下几点区别:
- 并非所有依赖库都提供了打包好的生产环境的文件,对于这种只能通过npm来引入的库, externals 无能为力。
- 部分依赖库中会存在循环依赖的现象,在一些 React 相关的库中尤为明显,使用 externals 处理会造成路径混乱无法识别。
- 使用dll的方式打包好的静态文件在生产环境中需要额外处理,同步到build目录中。(可以使用 CopyWebpackPlugin 等插件)。
3. 使用 happypack
开启多线程构建
HappyPack可以将原有的 webpack 对 loader 的执行过程,从单一进程的形式扩展为多进程的模式,从而加速代码构建。使用方式如下:
1 | const HappyPack = require('happypack'); |
更多配置可以参考文档:https://github.com/amireh/happypack
4. 增强代码压缩工具
Webpack默认提供的UglifyJS
插件速度很慢,可以使用webpack-parallel-uglify-plugin
替换。配置如下:
1 | const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin'); |
5. 缩小文件搜索范围
Node.js的模块的载入及缓存机制如下:
- 载入内置模块
- 载入文件模块
- 载入文件目录模块
- 载入node_modules里的模块
- 自动缓存已载入模块
如果模块名不是路径,也不是内置模块,Node将试图去当前目录的node_modules文件夹里搜索。如果当前目录的node_modules里没有找到,Node会从父目录的node_modules里搜索,这样递归下去直到根目录。
我们可以对搜索过程进行一些优化,比如可以直接指定node_modules的路径:
1 | module.exports = { |
6. Webpack3 新功能: Scope Hoisting
在Webpack3.0 版本中,提供了一个新的功能:Scope Hoisting
,又译作“作用域提升”。在Webpack2中,打包后的文件里每个模块都会被包装在一个单独的闭包中,这些闭包会导致JS执行速度变慢,Scope Hoisting则可以将所有模块打包进一个大的闭包中。只需在配置文件中添加一个新的插件,就可以让 Webpack 打包出来的代码文件更小、运行的更快:
1 | module.exports = { |
7. 合理配置 babel-loader
在balel的官方文档中有一句话:babel-loader is slow!
。
我们在babel的配置中,也要尽量注意这一点。
比如,使用 /\.js$/
来匹配文件的话,可能会将node_modules中的文件一起处理,我们需要使用exclude、include等尽可能准确的来指定需要转换的内容。
我们还可以开启babel的缓存配置(cacheDirectory)来提升一倍以上的效率,配置如下:
1 | test: /\.js$/, |