Webpack 2 中一些常見的優化措施

發表於2017-05-31

Webpack 是一款強大的前端構建工具, 社群對其介紹的相關文章已經很多了, 本文不再贅述. 基於 Webpack 2, 本文是對我在搭建團隊前端腳手架的過程中, 蒐羅的 Webpack 2 常見的優化措施的一個總結.

如果你還不瞭解 Webpack 2, 可以先看下 Webpack 2 快速入門

1. 分離第三方依賴

開發環境下, 通常會採取 HMR 模式來提高開發效率. 但一般情況下, 我們只會更改自身的業務檔案, 不會去更改第三方的依賴, 但 webpack 在 rebuild 的時候, 依舊會 build 所有的依賴. 因而, 為減少 rebuild 的時間, 我們可以分離第三方依賴, 在專案啟動之前, 將其單獨打包和引入.

這要藉助 DllPlugin 外掛.

我們定義一份生成 dll 的配置檔案:

生成 dll 檔案之後, 可以根據環境變數在頁面的靜態檔案中引入:

這樣, 在每次 rebuild 的時候, webpack 都不會去重新 build vendor, 能極大減少 rebuild 的時間, 提升開發效率.

僅在開發環境下使用

2. 多程式構建

Webpack的構建過程是單程式的, 利用 HappyPack 可讓 loader 對檔案進行多程式處理, 其原理圖如下:

在業務檔案依賴越多和複雜的情況下, HappyPack 對 Webpack 構建效率的提升會越明顯. 下圖是我在專案使用 HappyPack 前後的一張構建時間對比圖:

HappyPack 會充分利用系統的資源來提升 Webpack 的構建效率, 所以系統本身的硬體配置會對 HappyPack 的使用有一定的影響.

HappyPack 不限於處理 js 檔案, 也可以同時處理 css/vue 等其它型別檔案. HappyPack 支援多個例項, 可以建立多個例項來分別處理不同的型別檔案:

此外, HappyPack 同時還利用快取來使得 rebuild 更快.

開發環境和生產環境下均可使用. 關於其原理分析, 請看 HappyPack 原理解析

3. 提取公共的依賴模組

無論是單頁還是多頁應用, 在生產環境下, 通常都會利用 CommonsChunkPlugin 外掛來提供公共的依賴模組:

上述的配置會提取 node_modules 下的所有模組, 打包出來的結果可能是這樣的:

打包結果分析圖由 webpack-bundle-analyzer 提供

這樣提取了公共模組之後, 的確會減少業務包的大小, 但是, 這種方式會導致兩個問題:

  • 業務越複雜, 三方依賴會越多, vendor 包會越大
  • 沒有隔離業務路由元件, 所有的路由都有可能會去載入 vendor, 但並不是所有的路由元件都依賴 node_modules 下的所有模組

所以, 上述提取公共依賴的方式不可取. 我們應該去分析業務依賴和路由, 儘可能將所有路由元件的公共依賴提取出來:

前後兩種方式打包出來的 vendor 大小對比:

既要去提取公共依賴, 也要避免 vendor 包過於太大.

4. 檔案分離

檔案分離主要是將圖片和 CSS 從 js 中分離. 圖片和 CSS 都是 Webpack 需要構建的資源, 通過某種配置, 圖片可以以 base64 的方式混淆在 js 檔案中, 這會增加最終的 bundle 檔案的大小. 在 生產環境下, 應該將圖片和 CSS 從 js 中分離:

  • 在生產環境下, 通過自定義外掛, 將圖片的本地引用替換為 CDN 的連結
  • 在生產環境下, 通過 ExtractTextPlugin 來 提取 CSS.

5. 資源混淆和壓縮

Webpack提供的 UglifyJS 外掛由於採用單執行緒壓縮, 速度比較慢,
可以使用 Parallel 外掛進行優化:

6. Gzip 壓縮

生產環境下, 如果想進一步減小 bundle 檔案的大小, 可以使用 Gzip 壓縮.

Gzip 壓縮能有效減少 bundle 的檔案大小:

部署上線時, 服務端也需要開啟 gzip 壓縮

7. 按需載入

在單頁應用中, 一個應用可能會對應很多路由, 每個路由都會對應一個元件; 如果將這些元件全部全部放進一個 bundle, 會導致最終的 bundle 檔案比較大(看上圖的 app bundle 檔案). 因而, 我們需要利用 Webpack 的 Code Splitting 功能, 將程式碼進行分割, 實現路由的按需載入.

在 Vue 中, 利用 vue-router懶載入功能, 是比較容易實現按需載入的:

當訪問首頁時, 會去載入 Index 元件, 此時並不會載入 Info 元件; 只有當路由切換為 /info 時, Info 元件才會被載入.

以上是個人的一些總結, 如有不足請指正, 如有遺漏, 歡迎補充.

vue-startup 是基於上述的一些優化措施寫的一個 Vue 的腳手架, 歡迎 star.

相關文章