文章目錄
前言
最近在做項目時,測試提出了在App端的H5項目入口加載時間過長,白屏等待過久,需要優化的問題,於是着手開始分析:
- 項目技術棧:基於Vue全家桶做的一個移動端類似WebApp的項目,使用到的第三方庫有:mint-ui, echarts,momentjs。
- 項目痛點:白屏時間過長
一、白屏時間過長分析
通過訪問線上環境,結合Chrome devtool中Network和Performance功能可以具體分析整個白屏的耗時主要在哪一塊兒
- Network耗時記錄:
- Performance性能面板
- 通過上面兩張圖分析,從瀏覽器發起請求到解析HTML完成這一過程中:
animate.css, mini-ui.css
的請求耗時最長。- 圖片過大耗時。
二、針對性優化
針對animate.css
animate.css
由於使用的是第三方CDN(國外服務器)所有請求時間相對較長,所以如果必須要用animate.css那麼可以下載下來作爲本地資源,也可以使用國內CDN,或者不用animate.css,而是針對使用到的幾個CSS動畫,直接自己造輪子
針對mint-ui的優化
由於mint-ui在原項目中使用的是全局引用的方式,這才導致打包資源過大,css單獨請求耗時過長的問題,所以主要解決方案是
按需引入mint-ui
,藉助babel-plugin-component,
我們可以只引入需要的組件,以達到減小項目體積的目的。
- 安裝babel-plugin-component, 若已安裝可忽略
npm install babel-plugin-component -D
- 修改 .babelrc (重點在plugins中):
{
"presets": [
["env", { "modules": false }],
"stage-2"
],
"plugins": ["transform-runtime",["component", [
{
"libraryName": "mint-ui",
"style": true
}
]]],
"comments": false,
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": [ "istanbul" ]
}
}
}
- 在main.js中引用使用到的插件
import Vue from 'vue'
import { Button, Cell } from 'mint-ui'
import 'mint-ui/lib/style.min.css' // 引用CSS
import App from './App.vue'
Vue.component(Button.name, Button)
Vue.component(Cell.name, Cell)
/* 或寫爲
* Vue.use(Button)
* Vue.use(Cell)
*/
new Vue({
el: '#app',
components: { App }
})
- 在使用的組件中改爲按需引用組件
import Vue from 'vue'
var Popup = Vue.component('mt-popup')
var Swipe = Vue.component('mt-swipe')
var SwipeItem = Vue.component('mt-swipe-item')
export default {
name:'my-component',
components:{
Popup,
Swipe,
SwipeItem
}
}
此按需引入方案也同樣適用於其他第三方UI組件庫
針對圖片的優化
圖片小圖通過webpack可以直接轉爲base64,而大圖可以通過壓縮或者換格式的方式來優化,這裏推薦一個好用的圖片壓縮工具,工具:tinyPNG,如下是圖片轉換前後對比
三、webpack打包優化與分析
在完成了上述優化以後,下面着重關注下webpack打包後生成的文件大小,看還有沒有可以優化的餘地。由於項目中已經通過
路由按需加載
的方式來做了功能拆分,所以通過webpack打包後生成了很多分散的js文件,如下圖:
通過上圖分析可以知道打包後有幾個文件相對較大,vendor.js都知道是第三方庫文件打包形成,之前通過mint-ui按需加載會有一定的變化,後面記錄。這裏着重看另兩個帶hash的js文件,這裏並看不出來它爲什麼這麼大,所以這裏需要用到webpack打包分析工具來做進一步的打包文件分析:webpack-bundle-analyzer
webpack-bundle-analyzer打包分析
它的作用如下圖,即在打包後生成打包文件大小分析圖,方便我們更加直觀的看到文件大小和引用情況
- 這裏先介紹下webpack-bundle-analyzer的簡單使用
- 安裝
npm intall -D webpack-bundle-analyzer
- 修改
webpack.pro.conf.js
. (這裏由於只是用於生產打包分析且是通過vue-cli生成的項目框架)
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
module.exports = {
// ...
plugins:[
new BundleAnalyzerPlugin()
]
}
- 運行
npm run build
,(webpack默認會在打包完成時生成分析圖)
更新:vue-cli3中webpack-bundle-analyzer配置變化
在vue-cli3中,webpack配置向不再對外暴露,而是集中在vue.config.js中進行修改,下面是新的配置項
// vue.config.js
module.exports={
//...
chainWebpack: config => {
config
.plugin('webpack-bundle-analyzer')
.use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
},
}
打包優化
通過上面的分析圖可以看到打包文件過大是由於第三方庫引用的問題,如
mint-ui, moment.js, echarts.js,zrender,Vue
等
1. mint-ui按需加載改造
通過之前的按需引用加載後,再次webpack打包可以看到vendor.js中mint-ui
包的大小明顯縮小
之前 95.31K
之後 34.96K
2. 第三方庫引用優化-使用CDN
對於像Vue,Vue-router,echarts等都可以使用CDN的方式來引入,目前使用的是Bootcdn相對其他免費CDN還是比較穩定的
// 1. 在index.html中通過CDN方式引用第三方
<script src="https://cdn.bootcss.com/vue/2.6.11/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.1.3/vue-router.min.js"></script>
// 2.修改webpack.base.conf.js
module.exports = {
// ...
externals: {
'vue': 'Vue',
'vue-router': 'VueRouter',
},
}
- 優化後的vendor.js。從原來的
254.38K 壓縮到了 69.56K
- 功能模塊js的優化
通過分析圖可以看到,剩下比較大的就是單文件js中引入了echarts.js, moment.js的包了,moment.js通過CDN引用方式也可以直接優化
而echarts.js由於項目中使用了一個第三方的組件庫vue-charts
導致echarts被直接打包到了文件中,使用CDN的方式也無法把echarts抽離,這裏採用的方式是重寫圖表組件,再使用CDN引入。
- 問題:
- 解決後,文件體積從201.75K降到了36.51K:
四、優化後線上測試速度提升
- Network優化後:
從發起到請求結束共350ms,相比於優化前的3.5s快了很多。總結:3.5s–>0.35s
- Performance面板:
通過performance可以看到整個過程從發起請求拿到index.html開始(3900ms處),到FMP位置(timestamp:4569.8 ms)結束,耗時約0.669s。總結:3.5s-> 0.669s
五、優化總結
此次優化大致用到以下幾種方案:
- 路由按需加載
- mint-ui按需引入(配合
babel-plugin-component
縮小項目打包體積) - Vue,VueRouter,momentjs等使用CDN訪問(配合webpack,externals)
- 圖片壓縮優化
- 公共代碼抽離(這一步vue-cli其實已經在webpack中配置了CommonsChunkPlugin)