Webpack5構建效能優化:構建耗時從150s到60s再到10s

2023-05-11 12:00:47

作者:京東科技 牛志偉

近期對Webpack5構建效能進行了優化,構建耗時從150s到60s再到10s,下面詳細講解下優化過程。

優化前現狀

1.歷史專案基於Vue3 + Webpack5技術棧,其中webpack設定項由開發者自己維護(沒有使用@vue/cli-service),並且做了環境分離。

2.專案體量大約5000個modules左右,每次本地構建build時耗時約150s左右。

優化細節

環境分離

之前已經設計了環境分離,但是一些優化細節沒有處理好:

•基礎組態檔:webpack.base.js,主要設定了基礎的loader和plugin等

•本地開發組態檔:webpack.dev.js,主要設定了devServer和樣式、圖片資源loader等,並merge基礎設定

•生產環境組態檔:webpack.prod.js,主要設定了樣式、圖片資源loader以及資源壓縮和樣式抽離等,並merge基礎設定

優化點:

•熱載入相關設定,從base移到dev設定中,生產環境中不需要熱更新

new webpack.HotModuleReplacementPlugin()

•dev設定中devtool型別選擇,inline-source-map修改為eval-cheap-module-source-map,map檔案使用內聯方式構建速度更快。

devtool: 'eval-cheap-module-source-map'

•filename調整:js/[name].[fullhash].js去掉hash,本地開發環境啟用熱更新,不需要hash(生產環境需要hash重新整理快取)

output: {
    filename: 'js/[name].js',
    path: path.resolve(__dirname, '../dist'),
    publicPath: '/',
}

持久化快取

base設定中開啟持久化快取(Webpack5新特性),首次構建耗時增加15%左右,但是二次構建耗時減少90%左右

cache: {
    type: 'filesystem'
}

Loader相關優化

•儘量減少loader,比如使用Asset modules(Webpack5新特性)替換url-loader、file-loader、raw-loader

// 字型和小於8kb的圖片
{
    test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
    type: 'asset',
    parser: {
        dataUrlCondition: {
            maxSize: 8 * 1024,
        },
    }
}
// 圖片資源
{
    test: /\.(png|svg|jpg|gif|cur)$/,
    type: 'asset/resource',
    exclude: [path.resolve(__dirname, '../../../assets/svg')],
}

•thread-loader耗時任務開啟多執行緒

{
    test: /\.vue$/,
    use: ['thread-loader', 'vue-loader'],
},
{
    test: /\.(t|j)s$/,
    exclude: /node_modules/,
    use: ['thread-loader', 'babel-loader'],
},
{
    test: /\.(sa|sc|c)ss$/,
    use: ['thread-loader', 'style-loader', 'css-loader', 'sass-loader'
},

•esbuild-loader替換babel-loader(由於改動較大,沒有嘗試)

Plugin相關優化

•使用speed-measure-webpack-plugin分析各個plugin、loader編譯時間

•儘量減少plugin,比如HotModuleReplacementPlugin只在dev開啟

•升級老舊plugin,比如terser-webpack-plugin版本從2升級到5,構建效能直接提升50%左右,具體原因有了解的同學可以打在評論區。

優化後效果

•不啟用快取情況下耗時從150s減少到60s以內

•優化後speed-measure-webpack-plugin編譯速度分析

•啟用持久化快取情況下,二次構建減少到10s以內

Webpack5總結

以下是從基礎、進階、優化、外掛使用以及打包原理幾個方面做的Webpack5總結,有遺漏之處歡迎評論留言討論