VUE项目性能优化
一、 使用webpack-bundle-analyzer 分析打包后的生成的文件结构进行优化;
在package.json配置 "analyz": "NODE_ENV=production npm_config_report=true npm run build" ,然后运行 npm run analyz 即可;
image.png
image.png
通过分析图,可以查看哪些有重复的文件或者哪个文件较大从而相应的进行优化;
这里提一下,左上角的stat、parsed及gzip表示什么意思:
stat表示文件的输入大小,parsed表示文件的输出大小,gzip表示通过gzip压缩运行解析的包/模块的大小;https://github.com/webpack-contrib/webpack-bundle-analyzer#size-definitions
这三个状态文件体积相差很大,可见使用gzip的重要性。
二、启用 gzip压缩;
1、安装 compression-webpack-plugin
npm install compression-webpack-plugin --save-dev,
这里有个坑,就是如果你的vue版本为2.5.2 及以下 webpack版本为3.6.0及以下时,建议安装compression-webpack-plugin的版本为1.0.0-beta.1 而不是2.0.0,否则可能打包时会报
ValidationError: Compression Plugin Invalid Options
options should NOT have additional properties
2、将vue项目中的 config/index.js中productionGzip: false改为 productionGzip: true;
打包后,可以看到.gz后缀文件了:
image.png
3、然后后台开启gzip模式:
开启 nginx gzip ,在 nginx.conf 配置文件中 配置
http { //在 http中配置如下代码,
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 8; #压缩级别
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 100; #不压缩临界值
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
}
保存退出 ,并 重启 nginx
systemctl reload nginx.service
systemctl restart nginx.service
4、测试访问
a、未开启gzip的情况
未开启gzip的情况
未开启gzip的体积
b、开启gzip的情况
开启了gzip的情况
开启了gzip的体积
可以看到 开启后响应头里有 content-encoding: gzip,且体积减少了一半还多。
三、解决vendor.js体积过大的问题
上面我们可以看到未经过gzip压缩,vendor.js体积有730kb,体积挺大的,vendor.js是第三方库经webpack打包而生成的集合;如下面的main.js 引用的第三方库ElementUI 、axios会被打包在vendor.js中
image.png
其实 我们可以使用cdn来引入第三方库:
1、选用cdn服务商
如 选用unpkg来作为第三方提供 https://unpkg.com 或者 https://www.bootcdn.cn/ 如我想要axios包则输入网址为 https://unpkg.com/axios/ (末尾加斜杠代表你要查询该库的所有版本列表)
2、在index.html中将你所需的第三方库的链接加入即可:
我以axios为例:
image.png
注:应该加入到
3、启用DNS预解析
在index.html的header中加入
image.png
5、去除原有的引用
包括 import axios from 'axios'; 和Vue.use(axios )
,当然如果为了避免去除import axios from 'axios';后导致很多eslint 警告,你可以保留import axios from 'axios';; 参考依据: 外部扩展(externals)
https://webpack.js.org/configuration/externals/
完成后打包一下观察vendor.js的体积变化:
未使用cdn的情况
使用cdn以后
可以看到vendor.js减少了12kb;也就是axios.min.js的大小。这里其实还可以将vue、element ui 都拎出来,可以减少很多体积;
题外话:
a、app.js
app.js 入口文件打包的结果,里面将项目中的api接口名及请求和响应等拦截器、路由组件关系等文件全部压缩打包了,大部分为我们自己编写的代码
b、manifest.js
manifest.js 模块化的应用程序的所有代码,里面是 建立hash映射关系的文件
image.png
c、vendor.js 第三方库,一般是node_modules里面的依赖进行打包
d、vendor-async.js
vue中mixin里的所有代码都会打包至vendor-async.js中
四、采用webpack.DllReferencePlugin将不常变更的库免二次打包编译;
这个可大大减少编译时间,同时可使用未变更的文件的缓存;
具体可参考
1、 Webpack的dll功能
2、webpack进阶——DllPlugin优化打包性能(基于vue-cli)
其实采用webpack.DllReferencePlugin跟上面介绍的--解决vendor体积过大的问题中的 externals方法存在异曲同工之处,貌似它们间有差别,但这个差别有待考证:
image.png
经过查看的回答发现webpack.DllReferencePlugin可以由autodll-webpack-plugin完美替代,这点待后面有时间再研究;
五、路由懒加载
使用
// 官方写法
const CardActConsume = () => import('@/components/club/CardActConsume')
// 自己的写法
const CardBuyConsume = (resolve) => {
import('@/components/club/CardBuyConsume').then((module) => {
resolve(module)
});
}
...
{
path: '/club/:id/cardactconsume',
name: 'clubcardactconsume',
component: CardActConsume,
}
...
替代原有的
import CardActConsume from '@/components/club/CardBuyConsume'
这个就不多说了 ,可见官方文档: https://router.vuejs.org/zh/guide/advanced/lazy-loading.html#把组件按组分块;另外可以把组件按组分块打包成一个js:
image.png
六、webpack 配置文件记得区分开发环境和生产环境
生产环境不要包含HotModuleReplacementPlugin 等没有必要的插件;