(原文在這裡,如果對你有幫助的話,動動你的小手手給個星星呀)
注意:本文有點標題黨了,圖很多很羅嗦,不想看圖的同學可以直接看加粗的內容和最後的總結
第一次在掘金寫文章,哪裡有不對的地方或者更好的方案請不要給我面子,馬上提出來
最近在做一個專案,技術棧為vue全家桶 + element-ui + echarts,打包後發現有1.44M,首屏體驗很差。這能忍?果斷開始優化。下面說說我是如何將一個打包後1.44MB的專案變成打包後只有0.42MB,效能提升70% 的。
優化過程
-
準備:
vue-cli
提供了一個很方便的檢視程式碼打包後體積的命令,只需在正常的打包命令後加一個--report
即可,這樣打包完成後會自動開啟一個頁面,展示各個依賴包的大小。npm run build --report 複製程式碼
-
優化前:
先看看優化前的大小吧
這是打包前本地localhost中首屏載入的js檔案,只有一個app.js
(3.2MB
)(注意是本地,未打包,未壓縮) 這是打包後的截圖,體積為1.44MB
,打包時間為72s
-
第一次優化:路由懶載入
說到優化,第一個肯定考慮的是懶載入啦,馬上在vue和vue-router的官方文件裡找到了解決方案
結合 Vue 的非同步元件和 Webpack 的程式碼分割功能,輕鬆實現路由元件的懶載入
具體做法的話如下:
首先要安裝一個外掛Syntax Dynamic Import使專案支援
動態import
cnpm install -S babel-plugin-syntax-dynamic-import 複製程式碼
然後修改
.babelrc
檔案// .babelrc 中的plugins陣列中多加一個"syntax-dynamic-import" { "plugins": ["syntax-dynamic-import"] } 複製程式碼
最後修改
router.js
,將所有路由都改為動態載入//router.js //原來的寫法:import Home from '@/components/PC/Home' //改成下面這種形式(其他路由同理) const Home = () => import('@/components/PC/Home') 複製程式碼
OK,第一次優化完成。讓我們打包看看結果如何吧。
上面兩張圖分別是本地打包前首屏載入的js資源(經計算大約為
3.1MB
)的截圖和打包後的截圖(1.44MB
),打包時間為55s
。注意我紅色框出來的部分,和優化前相比較打包的結果多了幾個以0
1
等數字開頭的js檔案,這其實就是我們的路由檔案被分離了出來,首屏只載入了需要的0.js
和3.js
檔案,等到我們切換到其他路由的時候才會載入其他的2.js
或者4.js
,而不是像以前那樣全部包含在了app.js
中一次性全載入出來。和優化前相比,打包後大小沒變,但是打包時間減少了,首屏載入的js資源也少了
0.1MB
(坑爹麼不是!!)。打包體積沒變,首屏才少了0.1MB?效果這麼差,你特麼在逗我?
彆著急打我,聽我解釋。打包體積沒變是因為不管路由怎麼懶載入,實質上需要的路由檔案還是那麼多,大小是不變的,所以體積沒變。而首屏才少了
0.1MB
,是因為這個專案本來就是個很小的專案,只有4個頁面,而且這個專案的首頁引入了echarts
本來就相對來說比較大。所以說這一步路由懶載入的優化是完全ok的,效果不好是因為是我專案的原因,少了的那
0.1MB
是剩餘未載入的路由檔案大小。如果你的專案有很多個頁面,那麼路由懶載入的效果應該會不差。
我們再次看看這個圖
發現左邊黃色的框echarts
和右邊藍色的框element-ui
體積佔了大頭,我們先看element-ui
佔了556KB
,現在開始針對element-ui
進行第二次優化 -
第二次優化:element-ui元件按需載入
針對
element-ui
的優化,沒啥好說的,具體做法,直接看文件裡面的按需引入吧。 照著文件優化了以後,再次打包檢視結果:這次優化後,打包用了
而且45s
,總大小由1.44MB
變成了1.16MB
element-ui
模組所佔的大小也由556kb
變成了267kb
,效果還行。但是這點提升怎麼滿足的了我?解決了element-ui
,我們看看另外一個模組echarts
: 比element-ui
還要過分!!足足佔了606kb
,馬上針對最大的boss----echarts
進行優化。 -
第三次優化:使用 CDN 外部載入資源
這次優化主要是針對
echarts
,在其文件裡也有提到按需載入,但是這次我們不用按需載入了,我想把echarts
徹底幹掉!我們這次要使用webpack
的externals,參考這裡防止將某些 import 的包(package)打包到 bundle 中,而是在執行時(runtime)再去從外部獲取這些擴充套件依賴(external dependencies)。具有外部依賴(external dependency)的 bundle 可以在各種模組上下文(module context)中使用,例如 CommonJS, AMD, 全域性變數和 ES2015 模組。
具體做法:
首先在
index.html
中引入echarts
的外部CDN(如果需要地圖元件,也需要一併引入)//index.html <script src="https://cdn.bootcss.com/echarts/4.1.0/echarts.min.js"></script> 複製程式碼
然後在
webpack.base.config.js
中,做如下改動//webpack.base.config.js module.exports中增加externals物件 module.exports = { externals: { "echarts": "echarts" //預設是配置引用的庫(這裡是echarts)暴露出的全域性變數 }, } 複製程式碼
檢視優化結果:
這是打包前的本地首屏載入資源的截圖,可算出這次一共載入了1.31MB
(沒有算上echarts.min.js
,因為那是CDN資源),相對於第一次優化後的3.1MB
已經少了很多了。打包後的截圖如下
可以看到打包後的體積只有434.7KB
,而且這次打包只花了34s
,最重要的是echarts
也真的被幹掉了!!驚不驚喜!!意不意外!!
各次優化的表格
懶得看圖的同學可以直接看下面這張表格
# 打包後體積 壓縮後體積 首屏js資源 打包耗時 優化前 1.44M 425K 3.2M 72s 第一次優化(路由懶載入) 1.44M 434K 3.11M 55s 第二次優化(element-ui按需載入) 1.16M 381K 1.3M 45s 第三次優化(引入外部CDN) 434K 121K 1.3M 34s 可以看出,我們的優化還是很有成效的,各種體積和打包耗時差不多減少了70% 左右。
總結
這部分一定要看啊啊啊
- 遇到webpack打包效能問題,先執行
npm run build --report
分析一波,然後根據分析結果來做相應的優化,誰佔體積大就幹誰 - 路由很多的複雜頁面,路由懶載入是肯定要做的
- 現在很多庫都有提供按需載入的功能,有需要的話可以按照官方文件的做法來按需載入
- webpack提供的
externals
可以配合外部資源CDN輕鬆大幅度減少打包體積,適用於echarts
、jQuery
、lodash
這種暴露了一個全域性變數的庫 - 千萬不要忘了開啟Gzip壓縮
- 本文講的只是針對於
webpack
層面的優化,效能優化不只這些,還有其他方面的優化,比如頁面渲染優化(減少重排)、網路載入優化等。 - 本文的內容只適用於瀏覽器環境
- 遇到webpack打包效能問題,先執行