使用 happypack 提升 Webpack 專案構建速度

暖生發表於2019-02-21

本文簡單介紹了 Happypack 的簡單使用,不瞭解的同學可以進來看一看。也許會有所幫助。


Happypack 作用

在使用 Webpack 對專案進行構建時,會對大量檔案進行解析和處理。當檔案數量變多之後,Webpack 構件速度就會變慢。由於執行在 Node.js 之上的 Webpack 是單執行緒模型的,所以 Webpack 需要處理的任務要一個一個進行操作。

而 Happypack 的作用就是將檔案解析任務分解成多個子程式併發執行。子程式處理完任務後再將結果傳送給主程式。所以可以大大提升 Webpack 的專案構件速度

由於 JavaScript 是單執行緒模型,要想發揮多核 CPU 的能力,只能通過多程式去實現,而無法通過多執行緒實現。

本文專案程式碼地址:webpack-happypack-demo

歡迎 Star!


Happypack 的使用

Happypack 只是作用在 loader 上,使用多個程式同時對檔案進行編譯。

安裝

$ npm install happypack --save-dev
複製程式碼

使用(三步操作即可完成)

一、安裝完成之後引入 HappyPack

webpack.config.js

const HappyPack = require('happypack');

module.exports = {
    ...
}
複製程式碼

二、將常用的 loader 替換為 happypack/loader

webpack.config.js

const HappyPack = require('happypack');

module.exports = {
    ...
    module: {
        rules: [
            test: /\.js$/,
            // use: ['babel-loader?cacheDirectory'] 之前是使用這種方式直接使用 loader
            // 現在用下面的方式替換成 happypack/loader,並使用 id 指定建立的 HappyPack 外掛
            use: ['happypack/loader?id=babel'],
            // 排除 node_modules 目錄下的檔案
            exclude: /node_modules/
        ]
    }
}
複製程式碼

三、建立 HappyPack 外掛

webpack.config.js

const HappyPack = require('happypack');

module.exports = {
    ...
    module: {
        rules: [
            test: /\.js$/,
            // use: ['babel-loader?cacheDirectory'] 之前是使用這種方式直接使用 loader
            // 現在用下面的方式替換成 happypack/loader,並使用 id 指定建立的 HappyPack 外掛
            use: ['happypack/loader?id=babel'],
            // 排除 node_modules 目錄下的檔案
            exclude: /node_modules/
        ]
    },
    plugins: [
        ...,
        new HappyPack({
            /*
             * 必須配置
             */
            // id 識別符號,要和 rules 中指定的 id 對應起來
            id: 'babel',
            // 需要使用的 loader,用法和 rules 中 Loader 配置一樣
            // 可以直接是字串,也可以是物件形式
            loaders: ['babel-loader?cacheDirectory']
        })
    ]
}
複製程式碼

這樣 Happypack 的使用就配置完了,執行專案,可以看到控制檯列印如下提示:

Happy[babel]: Version: 5.0.1. Threads: 3
Happy[babel]: All set; signaling webpack to proceed.
複製程式碼

說明配置生效了。

Happypack 示例

使用單個 loader

上面的使用中就是單個 loader 時的配置,這裡再寫一次

exports.module = {
    rules: [
        {
            test: /.js$/,
            use: 'happypack/loader?id=babel'
        }
    ]
};

exports.plugins = [
    new HappyPack({
        id: 'babel',
        loaders: [ 'babel-loader?cacheDirectory' ]
    });
];
複製程式碼

使用多個 loader

exports.module = {
    rules: [
        {
            test: /\.(css|less)$/,
            use: 'happypack/loader?id=styles'
        },
    ]
};

exports.plugins = [
    new HappyPack({
        id: 'styles',
        loaders: [ 'style-loader', 'css-loader', 'less-loader' ]
    });
];
複製程式碼

Happypack 配置項

  • id: String型別,對於 happypack 來說唯一的 id 標識,用來關聯 module.rules 中的 happypack/loader

  • loaders: Array型別,設定各種 loader 配置,與 module.rulesloader 的配置用法一樣

// 無配置時,可直接使用字串形式
new HappyPack({
    id: 'babel',
    loaders: ['babel-loader?cacheDirectory']
})

// 有配置項時,可以使用物件形式
new HappyPack({
    id: 'babel',
    loaders: [
        {
            loader: 'babel-loader',
            options: {
                cacheDirectory: true
            }
        }
    ]
})
複製程式碼
  • threads: Number型別,指示對應 loader 編譯原始檔時同時使用的程式數,預設是 3

  • threadPool: HappyThreadPool物件,代表共享程式池,即多個 HappyPack 例項都使用同一個共享程式池中的子程式去處理任務,以防止資源佔用過多

// 建立一個 HappyThreadPool,作為所有 loader 共用的執行緒池
const happyThreadPool = HappyPack.ThreadPool({ size: 5 });

...
new HappyPack({
    id: 'babel',
    loaders: [
        {
            loader: 'babel-loader',
            options: {
                cacheDirectory: true
            }
        }
    ],
    threadPool: happyThreadPool
})
複製程式碼
  • verbose: 是否允許 happypack 輸出日誌,預設是 true

  • verboseWhenProfiling: 是否允許 happypack 在執行 webpack --profile 時輸出日誌,預設是 false

  • debug: 是否允許 happypack 列印 log 分析資訊,預設是 false


個人總結

個人的一點小總結,不足以作為參考依據

  • 在測試 Demo 或者小型專案中,使用 happypack 對專案構建速度的提升不明顯,甚至會增加專案的構建速度

  • 在比較複雜的大中型專案中,使用 happypack 才能看到比較明顯的構建速度提升

  • 因此,在使用 happypack 時請根據具體情況進行選擇,如果反而延長了專案的構建速度,就沒有必要使用 happypack


本文 Demo 地址

本文專案程式碼地址:webpack-happypack-demo

歡迎 Star!

相關文章