项目背景
项目模板使用的是基于Vue-cli3的vue-admin-template
项目是单页后台
项目属于中小型项目
问题 - 首屏加载非常慢
让我们看看没任何处理的测试包
首屏加载竟然需要5-10s的加载时间! 这肯定是不符合线上要求的
分析一下加载的资源,明确发现以下问题
elementUI的js文件太大了,严重影响速度
整体代码未压缩
某张图片,静态资源过大,应减小该图片体积,或者优化静态资源加载速度
如何优化
前端开启gzip
关于这一点作者文档中分析构建文件体积有提到,但是却没有给出解决方案,配置如下
服务器开启nginx后,代码经过压缩就会小很多,但是如果我们打包后的代码没有压缩过,那就是服务端来负责压缩,自然会拖慢服务端加载速度,我们应该在webpack中开启压缩
生成压缩代码的webpack插件
npm install compression-webpack-plugin -D
复制代码
修改vue.config.js
该对象将会被 webpack-merge 合并入最终的 webpack 配置。具体请看webpack相关
configureWebpack: config => {
const baseConfig = {
name: name,
resolve: {
alias: {
'@': resolve('src')
}
}
}
if (process.env.NODE_ENV === 'production') {
return {
plugins: [
// 压缩代码
new CompressionPlugin({
test: /\.js$|\.html$|.\css/, // 匹配文件名
threshold: 10240, // 对超过10k的数据压缩
deleteOriginalAssets: false // true 不删除源文件 false 删除源文件
})
],
...baseConfig
}
} else {
return { ...baseConfig }
}
}
复制代码
配置完成后再次打包代码,就会发现js文件夹里面多出了 .js.gz文件,那就是压缩后的js代码
首页图进行优化
关于图片部分,因为这个后台仅仅有一张登录背景图很大,所以对于小项目,只要将png图片转成jpg图片即可所以大量的图片体积,这个交给ui来完成
去除console.log与警告
注意: 去除警告现在为插件 TerserWebpackPlugin webpack-parallel-uglify-plugin不在提供去除log与警告功能
线上项目自然不应该被看到控制台的打印日志,所以我们需要将console.log都去除掉
npm install compression-webpack-plugin -D
复制代码
修改vue.config.js configureWebpack部分
configureWebpack: config => {
const baseConfig = {
name: name,
resolve: {
alias: {
'@': resolve('src')
}
}
}
if (process.env.NODE_ENV === 'production') {
return {
plugins: [
// 压缩代码
new CompressionPlugin({
test: /\.js$|\.html$|.\css/, // 匹配文件名
threshold: 10240, // 对超过10k的数据压缩
deleteOriginalAssets: false // 不删除源文件
}),
// 去除console.log
new TerserPlugin({
terserOptions: {
compress: {
warnings: false,
drop_console: true,
drop_debugger: true,
pure_funcs: ['console.log']
}
}
})
],
...baseConfig
}
} else {
return { ...baseConfig }
}
}
复制代码
将elementUI改为按需加载
这一块官方坑比较大,花了比较久的时间
安装按需引入插件
npm install babel-plugin-component -D
复制代码
配置
这里因为babel的升级,按element官方配置,会报错,presets部分增加会报错
module.exports = {
presets: ['@vue/app'],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk'
}
]
]
}
复制代码
然后我们开始修改main.js里面的按需引入代码
代码来自官方文档https://element.eleme.cn/#/zh-CN/component/quickstart#an-xu-yin-ru
import {
Pagination,
Dialog,
Autocomplete,
....
} from 'element-ui'
Vue.use(Pagination)
Vue.use(Dialog)
Vue.use(Autocomplete)
.....
Vue.prototype.$loading = Loading.service;
Vue.prototype.$msgbox = MessageBox;
Vue.prototype.$alert = MessageBox.alert;
Vue.prototype.$confirm = MessageBox.confirm;
Vue.prototype.$prompt = MessageBox.prompt;
Vue.prototype.$notify = Notification;
Vue.prototype.$message = Message;
复制代码
这里重启项目,会报错
google了很久,终于找到了类似问题
Uncaught ReferenceError: _MessageBox is not defined,没解决方案elementUI非常棒,作为开发者非常感谢维护者大大们,但是麻烦官方也把出现的问题解决一下啊,这个issue多久了,还是去年的,一点回复都没有,官方案例又跑不通,同时社区形同虚设,隔壁Antd的gitter,在线聊天室维护者会回复问题,Taro社区有微信群,element的gitter就和只是用来聊天的gitter,全都是问题,却没有答案,这样真的不好
问题解决
element改为按需引入后会报错,来自vue-element-admin的issues,问题提出者的解决方案
亲测可用
import {
Pagination,
Dialog,
Autocomplete,
....
} from 'element-ui'
Vue.use(Pagination)
Vue.use(Dialog)
Vue.use(Autocomplete)
.....
Vue.prototype.$msgbox = MessageBox
Vue.prototype.$alert = Vue.prototype.$msgbox.alert
Vue.prototype.$confirm = Vue.prototype.$msgbox.confirm
Vue.prototype.$prompt = Vue.prototype.$msgbox.prompt
Vue.prototype.$message = Message
复制代码
优化后
最后来看一下,优化后,项目启动速度是多久
element的js包由638kb减小为110kb
图片改为jpg格式,不降低质量的情况下 422kb减小到253kb
整体代码包体积减小了50%
在模拟3g网络下,页面第一次进入3s就会基本完成了全部加载
模拟4g网速的情况下,1s完成页面的加载
小结
关于Vue打包文件使用静态sdn来减小项目体积,个人而言不太赞同,毕竟静态cdn是别人的东西,假如cdn掉线了,项目出现问题,责任谁都承担不起
本文是比较浅层的优化,项目依旧可以继续优化,但是提升效果可能不太明显
但是经过上面的步骤,基本满足大部分项目的需求,可以达到自己想要的效果