一次webpack小規模優化經歷
這標題一點營銷號味道都沒有,怎麼會有人看啊!(笑)
沒人看也無所謂的文章背景:
八月份入職了新公司,是個好幾年的老專案了,公司產品是存在很久了,但我接觸到的程式碼版本保守估計應該是有個三年到四年這樣的歷史,所以期間應該是換工具重構了一遍。公司最開始沒前端,然後不知道哪位大哥建專案的時候選擇建成多頁面應用,分功能模組打包,後來被招我進來的大哥(也是前端的負責人)改成了單頁面應用,但因為改造不完整,導致留下了些後遺症,表面上主要體現在熱過載速度極慢,以及打包體積巨大、編譯耗時長,jenkins完整推一次包要差不多半小時;在這種優化已經成為剛需的前提下,雖然組裡有三四個前端同事,但他們好像都沒想過去搞這種事情,在我加入後不久,前端的負責人就離職了...沒有形式上的領導,更不會有人想著去做這種耗時不確定的還不一定會有效果的事情。公司對新人的期待並沒有那麼迫切,所以前期基本上除了日常安排的功能開發之外基本上是放養狀態,進公司一個月後,按慣例經理跟前端負責人(彼時前端大哥還沒離職)要找新人做個談話,瞭解一些融入狀態以及這段時間內的工作內容,我就提到了公司專案目前的這些硬傷和優化的想法,在得到授意之後,日常開發之餘,就進行優化工作。
基本配置(優化前): 前端框架vue2.5.x+element-ui,構建工具webpack1.x+gulp, express+中介軟體實現der-server
正文:
前面說了那麼多無關緊要的,可沒打算跑題,本文意為拋磚引玉,從個人的實踐觸發,通過具體的一些優化操作,覆盤一下優化思路。由於是做成了一段時間之後才回頭寫的文章,有些當時的疑問現在不一定有印象,有些操作不一定是最優解,有疑惑或者不同觀點的歡迎留言,期待能與各位同道交流學習。
那麼我們現在開始。
既然已經存在問題,而需求則是提高開發體驗、減小打包體積與編譯耗時,那麼在這個前提下,個人認為做優化的第一步,是分析問題,大體上,評估一套構建配置的質量的多個維度中,打包速度跟包體積這些指標是比較直觀的,所以接下來我打算介紹兩個外掛speed-measure-webpack-plugin與webpack-bundle-analyzer,量化分析打包耗時和前端包體積,用來幫助我們找到優化的正確方向。
那麼我先拿入職時候接手的專案程式碼開始做視覺化的分析。
(多圖警告)
首先我們在管理生產模式的配置檔案webpck.prod.conf的程式碼中新增這兩個外掛:
然後跑一遍打包命令,專案打包後,資源的檢視關係是這樣類似echarts的treemap的結構:
而負責速度分析的外掛speed-measure-webpack-plugin也在控制檯輸出了他的統計情況:
dist目錄50M,耗時約270s,前端頁面其實不是特別多,所以這個成績可以說慘不忍睹,那麼接下來我們單純從檢視上來分析,看看能不能找出一些異常。
webpack-bundle-analyzer的分析結果有三個維度,stat\parsed\Gzipped;
對於這三個維度,官方的解釋為:
stat
This is the "input" size of your files, before any transformations like minification.
It is called "stat size" because it's obtained from Webpack's stats object.
parsed
This is the "output" size of your files. If you're using a Webpack plugin such as Uglify, then this value will reflect the minified size of your code.
gzip
This is the size of running the parsed bundles/modules through gzip compression.
可以理解為分別對應著webpack從入口檔案打包遞迴到的所有模組體積、解析與程式碼壓縮優化後輸出到dist目錄的體積、開啟Gzip之後的體積,後兩個維度的值一般來說接近真實的前端包體積,但不會跟他們佔用的硬碟空間完全一致,隨優化手段不同也有所差異。
現在這個專案的stat狀態下體積為: ……接近400M
同時,我們可以發現有多個bundle存在結構相似的情況,比如:
查詢一個被多個檔案引用的普通頁面元件,能看到這個原始檔被打包進多個bundle:
而之前的另一份截圖也表示用於壓縮css程式碼的extract-text-webpack-plugin與用於壓縮js程式碼的UglifyJsPlugin,在打包過程中的大部分時間裡保持著運作,總結以上幾個現象,可以得出這麼一個結論:有一部分公共模組,沒有正確地被提取出來;
而在webpack4以下,官方提供的負責提取公共模組的外掛為:webpack.optimize.CommonsChunkPlugin,而這是我當前的CommonsChunkPlugin配置:
第一個commons chunk的含義是從根目錄下的node_modules目錄去抽取所有被引用的js檔案,這個chunk被命名為vendor,無引用次數限制;
第二個commons chunk的含義是從剛剛定義vendor的chunk中抽取公共模組,預設minChunk是2
這兩個chunk都是針對node_modules的第三方庫進行公共模組抽取,缺少了對專案自建公共模組的管理,因此我們嘗試著新增一個新的commons chunk:
new webpack.optimize.CommonsChunkPlugin({ name: 'index', async: true, children: true, }),
加上這段配置後,重新打包,這回看起來就比較正常了:
速度雖然還是比較慢,但相比之前,也不是那麼難以接受:
到這裡體積跟編譯時間這兩個痛點就算是解決了,我在做完這個版本的優化後,專案暴露出來比較明顯的還有一些問題:
1.瀏覽器首屏載入速度一般,單個檔案體積過大,常導致單個資源請求耗時較長
2.開發環境下專案啟動/熱過載還是很慢,我對中介軟體+本地起服務那一套不怎麼熟,個人在短時間內沒找到突破口
第一個問題關係到業務需求、以往業務程式碼寫法還有webpack拆包,而由於以上的第二個問題,開發體驗還是沒有得到提升,單個檔案改動觸發的熱過載耗時動輒十多秒,著實有些折磨,所以在完成第一個版本不久,我決定在這個基礎之上升級構建工具,webpack1.x升級到4.x的過程中也遇到了很多坑,這些我打算整理一下再更新到下期的內容中。
關於視覺化分析的工具,還有多種選擇,比如:
webpack自己的視覺化分析工具(線上):https://webpack.github.io/analyse/
儀表盤形式的webpack-dashboard: https://github.com/Exodia/webpack-dashboard
同樣是儀表盤形式,但視覺效果更出色,然而更新不是很勤快的:https://github.com/zouhir/jarvis
ok,我們有機會——當然有機會——所以我們下期內容再見——下週開始出差,希望目的地那邊不會那麼忙。
——“雖然我在經濟艙”!