webpack打包体积优化,减少白屏时间
webpack打包体积优化
加载慢原因分析及解决
一个是打包体积的优化,另一个是代码层面的优化
1》首先通过Network面板发现vendor.js体积过大,网路良好情况下加载时间太长),vendor体积太大,加载花了3s?后来发现 js 没开启nginx压缩
2》通过 webpack-bundle-analyzer 来具体分析,进一步体积过大的原因,进一步进行打包优化
打包体积优化方案
1》开启gzip压缩
压缩原理:简单的理解就是将相同的内容,用两者之间的距离和相同内容的长度来替换后面的内容,从而使整个文件变小。所以文件中代码的重复率越高,那么压缩的效率就越高,使用 gzip 的收益也就越大
如何判断是否开启:
请求头:服务端会通过客户端发送的请求头中的 Accept-Encoding 字段来确定是否支持
Accept-Encoding:gzip, deflate, br
响应头:表示当前资源会使用 gzip 压缩,提示客户端解压使用。
Content-Encoding:gzip
nginx中开启gzip
http {
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
}
属性 | 说明 |
---|---|
gzip | on/off,是否开启gzip压缩 |
gzip_types | 压缩哪些文件类型 |
gzip_min_length | eg:10k;大于10k的文件才会进行压缩(小于10k可能压缩后反而变大) |
gzip_buffers | 获取多少内存用于缓存压缩结果,eg: 16 8k 表示使用16个缓冲区,每个缓冲区大小为8KB |
gzip_comp_level | 压缩比(1~9),越小压缩效果越差,但是越大处理越慢,所以一般取中间值 |
gzip_static on | 优先匹配 gzip 文件来返回,如果没有就寻找相应资源进行 gzip 压缩再返回 |
优点:减小文件体积,页面加载更快
缺点:开启 gzip 后会额外的增加很多 cpu 的开销,会对服务器产生一定压力,(客户端解压也需要cpu
开销不过客户端还好),这也是不建议把压缩率设置太高的原因。另外,对图片的压缩支持不太好,会出现体积变大或图片失真的问题
webpack开启gzip打包
通过插件compression-webpack-plugin
来生成.gz
文件
npm i -D compression-webpack-plugin
webpack增加配置
// 最好是先判断以下环境变量是否是生产环境的打包
const CompressionWebpackPlugin = require('compression-webpack-plugin')
if (process.env.NODE_ENV === 'production') {
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
// 目标资源名称。 [file] 会被替换成原始资源。[path] 会被替换成原始资源的路径, [query] 会被替换成查询字符串。默认值是 "[path].gz[query]"。
algorithm: 'gzip',
// 算法,默认'gzip'
test: '\\.(js|css))$',
// 所有匹配该正则的资源都会被处理。默认值是全部资源。
// 这里只匹配了js、css文件
threshold: 10240,
//只有大小大于该值的资源会被处理。单位是 bytes。默认值是 0。
minRatio: 0.8
// 只有压缩率小于这个值的资源才会被处理。默认值是 0.8。
})
)
}
添还需要在nginx配置gzip_static on;
,这样nginx
会优先匹配 gzip
文件来返回,如果没有就寻找相应资源进行 gzip
压缩再返回
优点:减少了服务器压缩文件的压力
缺点:打包时间变长
2》代码压缩
对于js:terser-webpack-plugin
optimization: {
minimize: true,
,
},
minimizer: [
new TerserPlugin({
parallel: true, //开启并行压缩,可以加快构建速度
}),
],
对于css: css-minimizer-webpack-plugin
optimization: {
minimizer: [new cssMinimizerPlugin({
parallel: true
}
)],
},
3》分包优化
webpack5中splitChunks可以进行分包优化
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
echarts: {
name: 'chunk-echarts',
priority: 20,
test: /[\\/]node_modules[\\/]_?echarts(.*)/,
},
},
},
},
4》通过cdn方式引入外部库
**externals **引入外部库, 无需webpack打包处理
externals: {
echarts: 'echarts',
},
在html中引入
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js"></script>
组件中无需引入,可以直接使用echarts
const myChart = echarts.init(dom)
5》source-map
测试环境:
devtool: 'eval-cheap-module-source-map'
生产环境:
devtool: false
devtool: "nosources-source-map"
不同source-map的选择
false不会有sourcemap
eval- :生成source-map,不会生成额外的 .map文件,而是在eval 函数内附加 source map推荐在开发环境中使用
inline-:不会生成 .map文件,但是会将SourceMap内联到原始文件中
hidden- : source map 但是不会将其关联
nosources- sourcemap 中不带源码, 但会有准确的错误行列信息, 避免源码泄露
cheap- 忽略”列“信息,source map 只有“行”映射,可以加快打包速度
对于开发环境,通常希望更快速的 source map,需要添加到 bundle 中以增加体积为代价,但是对于生产环境,则希望更精准的 source map,需要从 bundle 中分离并独立存在
6》tree-shaking
在webpack5之前,如果一个文件中引用多个函数,却使用一个函数,那么多个函数都会被打包
但是webpack5能解析出依赖图谱,去除最终没有被使用的代码,生产模式下会进行 tree-shaking
复制代码
webpack5是有自动的tree-shaking
7》路由懒加载
路由懒加载可以将不同的路由对应的内容打包到不同文件中,而且用户访问对应路由时才会加载相应的组件(静态导入时,所有路由组件都会被打包到同一个文件中)
为什么按需引入没有是打包体积减小反而更大?
在使用ant-design-vue的时候,发现按需引入组件,打包体积反而更大了
原因是一些公用的东西,依赖等,如果是一起打包,就只要引用打包一次,按需引入则每个组件需要引用一份,就会打包进去一次
对于只用了很少组件的第三方库,比如本测试的echarts,按需引入会有很明显的优化效果,但是如果使用了很多,按需引入不一定更好