這標題一點營銷號味道都沒有,怎么會有人看啊!(笑)
沒人看也無所謂的文章背景:
八月份入職了新公司,是個老項目了,公司產品是存在了很久,但我接觸到的代碼版本估計應該是只有個2年到3年前的提交記錄,所以期間應該是換工具重構了一遍。產品最開始是多頁面vue應用,分功能模塊打包,后來被把我招進來的大哥(也是前端的負責人)改成了單頁面應用,但改造應該是不太完整,導致留下了些后遺症,表面上主要體現在熱重載速度極慢,以及打包體積巨大、編譯耗時長,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,我們有機會——當然有機會——所以我們下期內容再見——下周開始出差,希望目的地那邊不會那么忙。
——“雖然我在經濟艙”!
