專案背景
- 專案模板使用的是基於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與警告功能
該外掛的配置 minify-options
線上專案自然不應該被看到控制檯的列印日誌,所以我們需要將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掉線了,專案出現問題,責任誰都承擔不起
本文是比較淺層的優化,專案依舊可以繼續優化,但是提升效果可能不太明顯
但是經過上面的步驟,基本滿足大部分專案的需求,可以達到自己想要的效果