實戰剖析-vue項目首屏加載時長優化

現狀分析:

首屏速度是用戶體驗的最關鍵一環,而首屏速度最大的決定性因素就是資源的加載速度,資源加載速度等於資源大小 + 網速,老的前端項目隨着不斷增長,代碼可能會變得混亂,冗餘難以理解,不斷的做加法,久而久之,前端性能上就會受到影響,相信大家在工作當中一定遇到,頁面加載時間慢,響應時間長等問題,本文將以具體項目爲例(vue 2.51.7 webpack:4.23.1),一點一點分析,通過實戰的角度,介紹如何對Vue項目的首屏加載時間進行優化。

首先我們分析一下頁面加載時間的構成:

(1)資源加載;

(2)代碼執行;

(3)頁面繪製;



 

 

打開chrome開發者模式面板,爲了更好的還原用戶的使用場景,我在設置-節流配置中添加模擬5G的性能分析選項,對網絡狀況做最大限度還原,開始錄製頁面加載過程,

通過性能分析工具,我們就能看到一共有哪些執行,花了多長時間,通過查看網絡面板,可以查看到每一個資源的加載時間,腳本執行,頁面渲染和繪製時間,可以看出等待加載資源過大,執行腳本時長是佔據白屏時間的首要因素。也可利用window.performance,以數據化的形式查看頁面的各種時間,甚至可以把這些時間指標通過接口的形式發送給服務端,可以監控我們的項目在用戶的終端設備中的表現;

window.onload = function(){
    axios({
        url: "xxx",
        data: window.perfoformace
    })
}



 

 




問題找到了,就解決它

針對資源加載太慢的問題我先尋找大佬賞賜了一些思路:

1、找到是哪個文件過大導致,是否可以拆包;2、如果不是馬上需要的資源,可以異步加載;3、利用tree-shaking,儘量使用按需引入;4、定期實效數據可以緩存在cookies/localstorage中;5、進行gzip壓縮;6、利用webpack / vite對代碼進行壓縮;

作爲一隻資深笨鳥,對大佬的思路領悟只有一二成,用最笨的方法,一條一條排查😬

爲了直觀的發現文件打包體積問題,可以查看打包時生成的報告,有兩種方式:通過命令行參數的形式生成報告,也通過可視化的 UI 面板直接查看報告, npm run build --report的命令就可以生成報告,如圖所示:在加上 --report命令後,可以生成 report.html來幫助分析包的內容,通過 http://127.0.0.1:8888/ 就可以查看打包報告裏面的內容了 ,如圖所示:



 

 

通過面板分析,app.js壓縮後有960kb,發現nutui佔據主包體積過大,pinyin.js文件重複多次引入,lodash需要實現按需引入等問題。。。

一、大文件拆包壓縮

- 首先將索引文件通過cdn的方式引入,避免多模塊重複引入問題,其次對nutui模塊優化,不是首屏加載必須的模塊可以按需引入,有一點我們需要注意在對nuti實現外部引入的時候,需要先對vue進行一個引入,因爲如果不先引入vue,他就會在console裏面報一個錯誤,原因與elementUI外部引入問題相同,採用cdn的方式引入後,我發現unpkg cnd負優化壓縮比gzip還慢,參考大佬建議後,還是決定使用按需引入方式優化。

- 其次lodashi默認是全包引入的

//全包引入
import { cloneDeep } from "lodash"; 

//只引入cloneDeep函數
import cloneDeep from "lodash/cloneDeep";

通過--report參數 找到具體引入文件,發現儘管只用到了lodash的一個函數,但打包的體積也有幾百k,應該就是整包打的,沒有按需打包,按照上述方式修改爲按需打包,減少包體積,之後需要在.babelrc裏做一些配置,安裝 npm install babel-plugin-lodash 插件,設置plugins: ["lodash"]參數,之後打包文件就是按需打包的形式了。

- 說到神兵利器,不得不推薦 https://tinify.cn/ 圖片無損壓縮工具,由於平時習慣直接從UI站點下載配圖,對圖片體積不是很敏感,它可以一次性導入批量無損壓縮,一波操作下來,img資源從1.3M變成649K,着實很香。🤓

二、異步引入

目前來說比較新的腳手架版本,它生成的項目裏面用到的一種prefetch 加載方案,簡單介紹一下這種方案,假設有page1 page2 page3三個頁面,1和2是同步加載的,3是異步加載的,那麼異步加載的page3就會從app.js中單獨拆出來作爲一個文件模塊,首頁馬上需要加載的文件都會放到app.js裏,vendor.js裏面就是page1和page2需要用到第三方庫,page3中用到的第三方庫就會標記一個perfecth,它都會在首屏打開的時候創建link標籤去加載,有這個標記的資源會進入隊列等待加載。

Vue 2.5.17 版本本身並不直接支持 prefetch 加載,然而,2.x 版本支持異步組件,這可以在某種程度上實現類似 prefetch 的行爲,通過動態導入組件來按需加載。例如,可以使用 webpackrequire.ensure 語法或者 import() 函數來異步加載組件。

components: {
..//
  InsCalc: () => import('@/components/insCalc/insCalc')
..//
}

三、按需引入

- 現在的打包工具都有一個神兵利器叫做tree-shaking,可以把我們那些第三方庫中只用到了的方法打包進去,但是很多庫的老版本是不支持tree-shaking,比如我引入的xlsx的用來渲染excel表格,老的版本0.11.2的版本就不支持,我只使用 XLSX.utils.encode_cell / XLSX.utils.encode_range 的方法,打包的代碼在壓縮前體積就有七百kb,時間怎麼也得延長几毫秒吧,升級到0.18之後就可以支持tree-shaking,一般情況下只要支持 import { utils } from "XLSX",都可以利用tree-shaking實現按需引入,這時候打包體積就變成了90kb了。👋

這一系列優化操作下來,再次通過分析工具,app.js主包文件已經有500kb了,雖然不算小,但也有進步了😝 ,加載時長已經變成了4秒左右了。

四、數據緩存

- 項目中有通過路由攔截的方式實現對用戶授權數據進行分析的邏輯,這會直接導致在微信環境下二次跳轉到微信生態獲取code,由於網絡或設備等因素有的用戶可能出現三次刷新的情況

beforeRouteEnter(to, from, next) {
 if (//非微信環境) {
   next();
   return;
 }
 const code = to.query.code;
 if (!code) {
     const redirectUrl = `https://jlkauth.jd.com/view?xxxx`;
     const url = `https://open.weixin.qq.com/connect/oauth2/xxxxxx`;
     
 } else {
 //then 邏輯後才next() }
 },

這個問題不解決,再多的優化都沒有用,二次刷新的問題可能直接逼退一部分用戶,於是開始着手改實現方案,第一步通過原生js實現內部依賴的功能(axios,路由取參,環境判斷等...),脫離對項目中npm包的依賴,鑑於多個項目都在使用這個功能,採用cdn文件引入的方式,統一管理,項目內採用對構造函數的實例進行傳參的方式,在index.html中引入,可以在最早的加載時機觸發換code的邏輯,減短白屏等待時間,第二步通過對已授權用戶的數據緩存,避免刷新頁面請求,最大程度的降低了授權操作帶來的耗時影響。



<script src="https://cdn.../js/wxShareTrack.js"></script>
<script>
 const wxTrack = new WxShareTrack();
 const visit = {
     visitTitle: '標題信息',
     visitType: '類型'
};
 wxTrack.wechatTrajectoryReport(visit);
../
</script>

- 第五點和第六點一般我們不會有什麼工作量,利用nginx訪問資源的時候,一般都是會開啓壓縮的,利用webpakc或vite對代碼進行壓縮,也是我們利用npm打包的時候,自動進行壓縮的,可以在chrome的network面板中的Content-Encoding這一欄中看到是否開啓gizp壓縮。





 

 

結尾

總的來說,性能優化是一個涵蓋多個層面的綜合性概念,對於不同業務場景下的前端項目而言,適用的方法也各不相同,上述的各種優化措施,是通過分析實際情況,定位性能瓶頸,並選取的適合的優化策略,感謝閱讀😘
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章