如何讓webpack打包的速度提升50%?

SBDavid發表於2018-05-10

隨著前端應用包含的模組數量日益增長,程式碼打包的耗時也越來越長。公司很多專案打包耗時超過了10秒,對於一般人來說超過10秒的等待是比較難受的,雖然後續增量編輯的速度很快。於是我想結合實際開發環境提升一下首次打包的速度。

1. 實際開發環境

我碰到大多數處於維護狀態的網站都有一下幾個特性:

  • 模組數量龐大
  • 模組中主要分為js模組和css模組,並且less模組最後使用extract-text-webpack-plugin打包出單獨的css檔案
  • webpack入口檔案包含了js和less,所以每次打包都需要處理js和less模組
  • 許多需求只涉及到js模組的修改,並不涉及樣式修改。反之亦然。

2. 優化思路

既然許多情況下編譯less模組不是必須的,那在這些情況下單獨編譯js模組就能大幅提升webpack的效能。畢竟less的編譯、以及css的抽出都非常消耗時間。

3. 優化步驟

優化包含以下兩步:

  • 區分編譯目標,單獨編譯js? 還是單獨編輯css? 還是js+css?
  • 入口檔案分離js和css

3.1 區分編譯目標

這一步比較簡單,我們需要使用cross-env這個外掛,例如下面兩條編譯命令區分了編譯js和編譯js+css。

{
	"scripts": {
	    "build:js": "cross-env ctarget=all webpack",
	    "biuld:js+css": "cross-env ctarget=js webpack"
  }
}
複製程式碼

這樣我們就可以在webpack配置檔案中通過process.env.ctarget區分當前編譯目標了。

3.2 分離js和css

這一步需要通過webpack的loader來實現,可以使用現有的輪子string-replace-loader

這個loader可以在編譯階段修改程式碼,並且可以使用正規表示式進行替換。可以使用它來載入js檔案,然後刪除部分程式碼。下面的例子的作用是刪除js檔案中所有的less程式碼匯入。

{
	module: {
		rules: [
			{
            test: /.js$/,
            use: (function(){
                var list = ['這裡可以加上其他需要的loader']; 
                // 更具編譯目標刪除less的匯入
                if (process.env.ctarget === 'js') {
                    list.push({
                        loader: 'string-replace-loader',
                        options: {
                            search: '^.+?require\\(.+(\\.less).+$',
                            replace: '',
                            flags: 'm'
                        }
                    })
                }
                return list;
            })()
        }
		]
	}
}
複製程式碼

這裡在使用string-replace-loader一定要加上flags: 'm',否則無法進行多行匹配。

如果要單獨打包css我們可以寫一個和string-replace-loader作用相反的loader,只保留樣式部分而刪除其他js程式碼。

4. 效果

經過實際測試,這個優化可以節省50%的時間。當然具體到每一個專案還要看js和css模組數量的比例。

相關文章