作者:京東科技 牛志偉
近期對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總結,有遺漏之處歡迎評論留言討論