vue cli4 几个常用打包优化技巧
前言
这是我参与新手入门的第3篇文章
咬咬牙,你会发现有些东西没那么难。这里就个人角度而言,总结几个项目上遇到的需求,所做的打包优化。
需求1 ———— 打包压缩
故事是这么开始的。我们升级打包的前端包,本地nginx代理怎样都没有问题,可是放到某核现场,登录之后就是进不去内容首页。现场反应界面请求js失败,而我硬杠打包文件无错,且其他项目现场均无此问题。也许实在无招,人家摆出了升级前的文件,说我们升级后打包后的单个文件过大,会不会是此原因导致的。再刚的我,面对这种质疑也熄了火,没招,好好研究下怎么减少打包的单个文件体积呗。苍天不负苦心人,CompressionPlugin 进入了我的视野。
使用前的打包文件
对超出10K的css、js、html文件进行打包压缩。代码如下
//vue.config.js
const CompressionPlugin = require("compression-webpack-plugin");
configureWebpack: config => {
if (process.env.NODE_ENV === "production") {
return {
plugins: [
new CompressionPlugin({
test: /\.js$|\.html$|.\css/, //匹配文件名
threshold: 10240, //对超过10k的数据压缩
deleteOriginalAssets: false //不删除源文件
}),
]
};
}
},
使用后的打包文件
通过对比发现,大文件都生成了对应的压缩gz文件,我们再通过nginx代理,让浏览器请求对应的gz文件,对应的文件体积立马就下去了。就这样,我把文件体积压缩了下来,心想,这会某核现场没话说了吧。最终问题解决了,可不是因为体积的问题,是因为网络限制,某个依赖加载失败了。过程很陶醉,这里就不细说了。
需求2 ———— 去掉注释代码
这天,经理又找到了我。他说,宝啊,咱打包文件的注释想个法子去掉呗,某某项目因为国家网络安全,对某些敏感字段有较为严格的规范。我说:"行,给我点时间"。废话不多说,不懂就度,是我们‘百度人’最良好的品质。这不,它 uglifyjs-webpack-plugin就来了。
去掉注释前
去掉注释
configureWebpack: config => {
if (process.env.NODE_ENV === "production") {
return {
new UglifyJsPlugin({
uglifyOptions: {
mangle: false,
output: {
beautify: true,
},
}
})
]
};
}
},
去掉注释后,这里代码比较多,可以看右侧无明显注释分割了,效果杠杠滴。
需求3 ———— 去掉网页预加载
这个需求算是自己给自己提的。一次偶然,我对打包后的文件产生了好奇,我就在想打包后的html上都有些啥呢?
仔细看的话,你会发现,你的html上多了很多你在实际html界面并没有写入的引用文件。那么这些又都是些什么呢?可以去掉么?再仔细观察,你会找到 prefetch和preload这两个关键字。通过一番查找,我找到了这么一段解释:
Prefetch: 用于标记浏览器在页面加载完成后,利用空闲时间预加载的内容。Vue CLI 应用默认为所有作为 async chunk 生成的 JavaScript 文件 (通过动态 import() 按需 code splitting 的产物) 自动生成prefetch提示。
Preload: 用于标记页面加载后即将用到的资源,浏览器将在主体渲染前加载preload标记文件。Vue CLI 应用会为所有初始化渲染需要的文件自动生成 preload 提示
什么意思呢,就是我们浏览器会预加载一些我们需要的资源文件,如果我们不主动设置,文件过大,过多时,整个浏览器的加载速度在此界面就会降下来。这时,我们就需要告诉浏览器,我没允许你做的,你别做!
chainWebpack: config => {
entryConfig.pagelists.forEach(page => {
config.plugins.delete(`preload-${page}`);
config.plugins.delete(`prefetch-${page}`);
});
}
优化4 ———— 打包依赖分析之剥离
这点也是我最推崇的一点,希望每个前端人都能对自己打包的文件进行一个体积的分析。话不多说,先上代码:
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
chainWebpack: config => {
config.plugin('webpack-bundle-analyzer').use(BundleAnalyzerPlugin);
}
加上这个插件依赖,每次运行你的项目,都会看到这么一个界面
拿到这个我们能干什么呢?这里,我以element-ui为例。通过上图,我们可以发现,element-ui在分析图上占据着很大的面积,这也意味着此文件包的体积很大。通过模块性原则,这个时候,我们想的肯定是,那么能将此类大文件单独放置一个包内么?而不是和所有的node_modules在一起。答案肯定是可以的。
这里你需要了解splitChunks。因为所有引入的第三方库,都会默认被打包进vendors模块,引入的越多,文件越大,性能也就越差。而splitChunks则实现了对vendors模块的分割,减少了vendors文件的体积大小。 这里我添加了大量的注释,希望能对你有帮助。具体代码如下,
chainWebpack: config => {
config.optimization.splitChunks({
//chunks————>决定要提取那些模块
//默认async, 提取异步加载的模块【异步:通过import('xxx')或require(['xxx'],() =>{})加载的模块】
//initial, 提取同步加载和异步加载模块,若xxx在项目组异步加载也同步加载了,那么会被提取两次,打包到不同文件中【同步:import xxx 或 require('xxx')加载的模块】
//all, 不管异步加载还是同步加载的模块都提取出来,打包到一个文件中
chunks:"initial",
//minSize————>提取模块的最小值
//30000为默认值,压缩前模块大小超过此字节大小的才会提取
minSize:30000,
//maxSize————>提取文件最大值
//0为默认,打包生成的文件最大值,超过即分割
maxSize:0,//不限制大小
//minChunks————>最小提取次数
//要提取的模块最少被引入的次数,未达到不提取
minChunks:2,
//maxAsyncRequests————>最大异步加载次数,默认为6
maxAsyncRequests:6,
//maxInitialRequests————>打包的入口文件加载时,还能同时加载的js文件数量(包括入口文件)
maxInitialRequests:4,
//优先级:maxInitialRequests / maxAsyncRequests <maxSize<minSize。
//automaticNameDelimiter————>打包生成的js文件名的分割符
//automaticNameDelimiter:"~",//默认
//name————>打包生成的js文件的名称
/*
* === cacheGroups ===
* 配置提取模块的方案。除了以下特有选项,其它选项均与外面一致,有以自己为主,没有应用外部配置
*
* test。 匹配要提取的模块的资源路径或名称。值是正则或函数。
*
* priority。 方案的优先级,值越大表示提取模块时优先采用此方案。默认值为0
*
* reuseExistingChunk。 true/false。为true时,如果当前要提取的模块,在已经在打包生成的js文件中存在,则将重用该模块,而不是把当前要提取的模块打包生成新的js文件。
*
* enforce。 true/false。为true时,忽略minSize,minChunks,maxAsyncRequests和maxInitialRequests外面选项
*
*/
cacheGroups:{
common: {
//抽取所有入口页面都需要的公共chunk
name: "chunk-common",
chunks: "initial",
minChunks: 2,
maxInitialRequests: 5,
minSize: 0,
priority: 1,
reuseExistingChunk: true,
enforce: true
},
vendors: {
name: `chunk-vendors`,
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial'
},
icons:{
minChunks:1,
name:"chunk-icons",
priority:4,
test:/[\\/]src[\\/]style[\\/]font/
},
vueUI: {
name: `vueUI`,
test: /[\\/]node_modules[\\/]vue[\\/]/,
priority: 4,
chunks: 'all',
reuseExistingChunk: true,
enforce: true
},
element: {
name: "elementUI",
test: /[\\/]node_modules[\\/]element-ui[\\/]/,
chunks: "all",
priority: 3,
reuseExistingChunk: true,
enforce: true
}
}
})
}
配置之后,我们再来看看打包后的体积占比
对比发现,我们的element-ui生成了自己的单独文件。这里大家也可以看看vue单独生成的对比,代码我已经放上去了。
整体来说,这几点都可以通用的用在我们脚手架上打包的配置中来优化我们打包后的文件,当然,这里还有很多我还未涉及到的点,希望大家一起分享完善,互相学习,也希望我的分享能够帮到大家,谢谢。
转载自:https://juejin.cn/post/6982859424813563941