webpack优化实践
# webpack优化打包速度
前端圈分享的webpack优化实践 (opens new window)
打包性能分析插件speed-measue-webpack-plugin
# webpack打包流程
- 根据配置文件找到入口文件
- 通过loader对入口文件进行解析
- 通过acorn解析
js
代码,生成ast语法树,根据语法树找到依赖文件,生成依赖图{id,filename,dependency,code} - 根据依赖图打包生成chunk包
可以通过importDeclaration下的source下的value获取引用模块。直到文件没有任何依赖时停止
耗时步骤:loader解析耗时、搜索耗时、打包耗时
# 缩短解析时间
有二个思路:😉
- 减少处理的文件、缩小查找的范围
- 开启多进程解析
一、减少处理文件、缩小查找的范围
- noParse忽略不需要解析的文件,忽略的模块文件中不能使用import、require等语法
- 指定
resolve.extensions
这样在不加扩展名的时候会依次尝试对添加的扩展名进行匹配 - 设置
resolve.alias
指定具体路径及文件也可以加快查找速度 resolve.modules
指定查找目录module.rules
加入oneOf这样规则只匹配一次找到一个后就不再继续查找- 当文件想在浏览器中全局能用时加入externals。比如引jquery可以通过模块访问
jquery
也可通过window
访问 rules.include exclude
指写哪些文件需要与不需要解析
二、开启多进程
多进程加速loader解析时间
因为happyPack作者已经不再维护,所以推荐使用thread-loader
put this loader in front of other loaders. the following loaders run in a worker pool.
可以通过预热worker pool将指定模块载入缓存
To prevent the high delay when booting workers it possible to warmup the worker pool.
This boots the max number of workers in the pool and loads specified modules into the node.js module cache.
cache-loader
也要放在最前面,如果与thread-loader同时的时候,建议thread-loader先开启。
开启webpack的cache
Cache the generated webpack modules and chunks to improve build speed.
cache-loader
根据版本号文件名生成cacheKey做为文件的文件名,看文件是否存在,存在则通过对比mtime(modify time)
,如果相同return缓存,如果不同走下面的loader,它是一个轻量的,不对比内容的。babel-loader
通过文件内、option、版本号生成cacheKey做为文件的文件名,读文件是否已经存在,存在则使用缓存,不存在用bable-core
转义、zlib压缩、fs写入缓存,它根据文件内容来缓存。它不影响其它loader。
# webpack loader详解点击 (opens new window)
loader先从左往右执行它的pitch
方法,再去执行它们的normal
方法从右往左
# 缩短搜索时间
- 指定
resolve.extensions
这样在不加扩展名的时候会依次尝试对添加的扩展名进行匹配 - 设置
resolve.alias
指定具体路径及文件也可以加快查找速度 resolve.modules
指定查找目录
# 缩短打包时间
- 生成缓存chunk
当mode是development时默认配置
cache:true
smaller == faster
使用数量更少、体积更小的library。 在多页面程序中使用SplitChunksPlugin移除未引用代码
optimization:{
splitchunks: {
chunks: 'all', // 默认只分割异步代码
minSize: 0, // 分割出去的代码块的最小体积,0表示不限制
maxSize: 0, // 分割出去的代码块的最大体积,0表示不限制
minRemainingSize: 0, // 分割后剩下的体积,0表示不限制 webpack5新参数
minChunks: 1,// 被多个入口引入几次会被分割
maxAsyncRequest: 6, // 异步请求最大分割几个代码块
maxInitialRequesta:6, // 同步请求,入口并行加载的最大请求数
automaticNameDelimiter: '~', // 名称的分隔符
enforceSizeThreshold: 50000, // 强制阈值, webpack5新参数
cacheGroups: { // 缓存组配置, 配置如何对模块分组,相同分组会分到一个代码块中
defaultVendors: { // 第三方模块
test: /[\\/]node_modules[\\/]/, // 如果模块的路径匹配此正则
priority: -10, // 优先级, 有很多缓存组,如果一个模块同属于多个缓存组,则哪个优先级高分到哪里
reuseExitsingChunk: true, // 是否复用现有的代码块
},
default: {
minChunks: 2, // 此模块被最少2次引用会被提取
priority: -20,
reuseExistingChunk: true
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 其他
DLL 在webpack4性能提升的情况下,它已经作用不大了,也可以用hard-source-webpack-plugin
noParse 不用解析的文件
IgnorePlugin 忽略语言文件之类的
# webpack编译体积优化
压缩js
、css
、html
和图片
mini-css-extract-plugin
将js
代码中混合的css抽离出来(不然执行js
才能解析css)在将
style-loader
改为miniCssExtractPlugin.loader
module:{ rules:[ // 抽离 css { test: /\.css$/, loader: [ MiniCssExtractPlugin.loader, // 注意,这里不再用 style-loader 'css-loader', 'postcss-loader' ] }, // 抽离 less --> css { test: /\.less$/, loader: [ MiniCssExtractPlugin.loader, // 注意,这里不再用 style-loader 'css-loader', 'less-loader', 'postcss-loader' ] }] }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22在plugins中
plugins: [ new miniCssExtractPlugin({ filename: 'css/main.[contentHash:8].css' }) ]
1
2
3
4
5optimize-css-assets-webpack-plugin
优化和压缩css资源的文件optimization:{ minimize: true, // 开启最小化 minimizer:[new TerserJSPlugin({}), // 压缩js new OptimizeCSSAssetsPlugin({}) // 压缩css ] }
1
2
3
4
5
6terser-webpack-plugin
优化和压缩js资源image-webpack-plugin
对图片进行压缩和优化module:{ rules: [ { test: /\.(png|jpg|jp?g|gif)$/, use: [{ loader: 'url-loader', options: { // 小于 5kb 的图片用 base64 格式产出 // 否则,依然延用 file-loader 的形式,产出 url 格式 limit: 5 * 1024, // 打包到 img 目录下 outputPath: '/img1/', // 设置图片的 cdn 地址(也可以统一在外面的 output 中设置,那将作用于所有静态资源) // publicPath: 'http://cdn.abc.com' } },{ { loader:'image-webpack-loader', options:{ mozjpeg:{ progressive: true, }, optipng: { enabled: false }, pngquant: { quality: [0.65, 0.90], speed: 4 }, gifsicle:{ interlaced: false, }, webp: { quality: 75 } }, } }] }, ] }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43压缩html文件
plugins:[ new HtmlWebpackPlugin({ template:'./src/index.html', minify:{ collapseWhitespace: true, // 去掉空格 removeComments: true // 去掉注释 } }) ]
1
2
3
4
5
6
7
8
9purgecss-webpack-plugin 清除用不到的css
new PurgecssWebpackPlugin({ paths: global.blob.sync(`${PATHS.src}/**/*`,{nodir: true}); // ** 匹配任意字符,包括路径分割符。 * 匹配任意字符,但不包括路径分隔符 // const glob = require('glob') // 文件的匹配模式 // const PATHS = { // src: path.resolve(__dirname, 'src'), // } })
1
2
3
4
5
6
7