前端項目啟動慢瘩将?項目打包體積大吟税?跟著陳教練一起凹耙,項目的肥油咔咔掉。
1. 背景
項目經(jīng)過幾年的迭代肠仪,項目的啟動速度隨著項目的迭代肖抱,肉眼可見的變慢,打包的產(chǎn)物也是一天比一天大藤韵。啟動項目的時間虐沥、打包的時間是越來越久了。如同一個胖子泽艘,速度跟不上欲险,體重蹭蹭漲。
接下來就跟著陳教練來兩套健身操匹涮,減減脂天试,去去油。
2. 項目啟動提速
第一套健身操 —— 提速操
所有的優(yōu)化然低,都是需要針對問題進行優(yōu)化喜每,少數(shù)的優(yōu)化是通用優(yōu)化。
首先要知道雳攘,項目啟動的慢带兜,是因為什么慢。
開始前吨灭,先看一波目前我手上這個巨大項目的啟動時間:將近190s刚照,3分10秒+,陳教練已經(jīng)跟著劉畊宏教練跳了一首《本草綱目》了喧兄!
2.1. speed-measure-webpack-plugin
直接上工具 speed-measure-webpack-plugin无畔, 跟著配置完后,運行項目既可看到如下的分析報告:
從分析報告可以看出吠冤,項目諸多 loader 占用了大半的時間浑彰,而 loader 一般又是基本不會變的,于是乎第一個針對本項目的優(yōu)化方案就出來了拯辙,那就是給這些 loader 加上緩存,方法也很簡單涯保,就是使用 cache-loader 進行緩存。
npm install --save-dev cache-loader
在 webpack 配置文件內(nèi)對需要緩存的 loader 進行緩存
const cacheLoader = { // 新增代碼
loader: 'cache-loader' // 新增代碼
} // 新增代碼
module.exports = {
module: {
rules: [
{
test: /\.vue$/,
use: [
cacheLoader, // 新增代碼
{
loader: 'vue-loader',
options: vueLoaderConfig
}
]
},
{
test: /\.js$/,
use: [
cacheLoader, // 新增代碼
{
loader: 'babel-loader',
}
],
include: [
resolve('src'),
]
},
... ...
... ...
]
}
}
或者也可以像下面遭赂,我寫的這樣,在配置文件內(nèi)劫持 webpack 的配置横辆,調(diào)用 dynamicWebpackConfig 方法撇他,批量緩存
/**
*
* @param {*} rules
* @returns rules
* @description 按需緩存需要緩存的loader
*/
function rules (rules) {
const shouldCache = ['vue-loader', 'eslint-loader', 'babel-loader']
const cacheLoader = {
loader: 'cache-loader'
}
rules = rules.map(rule => {
if (
rule.use &&
rule.use[0] &&
shouldCache.includes(rule.use[0].loader)
) {
rule.use.unshift(
cacheLoader
)
}
return rule
})
return rules
}
/**
*
* @param {*} devWebpackConfig
* @returns devWebpackConfig
* @description 完整的webpack配置
*/
function dynamicWebpackConfig (devWebpackConfig) {
devWebpackConfig.module.rules = rules(devWebpackConfig.module.rules)
return devWebpackConfig
}
module.exports = dynamicWebpackConfig
做完這一步茄猫,需要正常啟動一次項目,此時會建立 loader 的緩存困肩。緩存內(nèi)容在可以在 node_modules/.cache 下看到划纽。再次啟動項目,看看啟動時間:提速了近80秒锌畸!此時不知道你是否還記得勇劣,在上面我說的這樣一句話:
“所有的優(yōu)化,都是需要針對問題進行優(yōu)化潭枣,少數(shù)的優(yōu)化是通用優(yōu)化比默。”
針對問題的優(yōu)化盆犁,已經(jīng)舉了一個例子說明了命咐,那么有沒有通用優(yōu)化的?
通用優(yōu)化谐岁,他來了
2.2. hard-source-webpack-plugin
hard-source-webpack-plugin 中間緩存醋奠,不管三七二一,只要 webpack 配置不變伊佃,通通緩存窜司,這種這種提速方法過于簡單暴力,有其他個性化的需求可以看文檔進行配置
hard-source-webpack-plugin航揉,
要注意: ip變化塞祈,端口變化也是 webpack 配置的變化
使用方法也很簡單:
const hardSourceWebpackPlugin = require('hard-source-webpack-plugin')
... ...
... ...
plugins: [
new hardSourceWebpackPlugin({
cachePrune: {
maxAge: 7 * 24 * 60 * 60 * 1000, // 默認2天,現(xiàn)改7天刪除
sizeThreshold: 500 * 1024 * 1024 // 默認50迷捧,現(xiàn)修改為500织咧,目前項目啟動后占用400MB的空間
}
}), //
... ...
]
同樣,這些額外的配置漠秋,也可以跟我上面劫持修改 webpack 配置一樣笙蒙,寫在一起,方便維護:
/**
*
* @param {*} plugins
* @returns plugins
* @description 按需push插件
*/
function plugins (plugins) {
const hardSourceWebpackPlugin = require('hard-source-webpack-plugin')
plugins.push(
new hardSourceWebpackPlugin({
cachePrune: {
maxAge: 7 * 24 * 60 * 60 * 1000, // 默認2天庆锦,現(xiàn)改7天刪除
sizeThreshold: 500 * 1024 * 1024 // 默認50捅位,現(xiàn)修改為500,目前項目啟動后占用400MB的空間
}
}), //
)
return plugins
}
/**
*
* @param {*} rules
* @returns rules
* @description 按需緩存需要緩存的loader
*/
function rules (rules) {
const shouldCache = ['vue-loader', 'eslint-loader', 'babel-loader']
const cacheLoader = {
loader: 'cache-loader'
}
rules = rules.map(rule => {
if (
rule.use &&
rule.use[0] &&
shouldCache.includes(rule.use[0].loader)
) {
rule.use.unshift(
cacheLoader
)
}
return rule
})
return rules
}
/**
*
* @param {*} devWebpackConfig
* @returns devWebpackConfig
* @description 完整的webpack配置
*/
function dynamicWebpackConfig (devWebpackConfig) {
devWebpackConfig.plugins = plugins(devWebpackConfig.plugins)
devWebpackConfig.module.rules = rules(devWebpackConfig.module.rules)
return devWebpackConfig
}
module.exports = dynamicWebpackConfig
由于該優(yōu)化方案還是緩存搂抒,所以還是需要正常啟動一次項目后艇搀,建立緩存。緩存內(nèi)容在可以在 node_modules/.cache 下看到求晶。再次啟動焰雕,查看啟動時間:第一套健身操昨完矩屁,項目的啟動速度已經(jīng)從 180s 提速至 30s辟宗。
累了的同學(xué)可以先休息一會兒
3. 項目打包優(yōu)化
休息結(jié)束泊脐,跟上第二套健身操 ——— 打包體積優(yōu)化操
經(jīng)過第一套的健身操之后容客,打包速度上约郁,也會沾了緩存的光,打包速度也會有提升调煎。但是士袄,我們打包的體積還是那么大,怎么辦娄柳?
開始前赤拒,還是需要看一看诱鞠,我們打完包后的產(chǎn)物體積:還是那句話航夺,“所有的優(yōu)化,都是需要針對問題進行優(yōu)化始衅,少數(shù)的優(yōu)化是通用優(yōu)化汛闸∫章睿”
那么,如何找到問題呢别伏?
3.1 webpack-bundle-analyzer
這時候就需要用到一個很常見的工具,webpack 打包分析插件 webpack-bundle-analyzer,簡單配置完后轴脐,重新運行打包命令抡砂,可以在本地的8888端口看到如下效果:
每個顏色的快,就是打包產(chǎn)物內(nèi)的代碼塊注益,圖中占面積越大的文件,其文件的大小越大厦瓢,部署到服務(wù)器之后啤月,在瀏覽器中加載的時間越長。我們可以根據(jù)這個圖浙垫,去優(yōu)化
通過這個分析圖夹姥,我們可以知道:
- 了解 bundle 包中的真正內(nèi)容
- 找出哪些模塊尺寸最大
- 查找誤引入的模塊
- 優(yōu)化項目
具體優(yōu)化就看各位同學(xué)的眼力和優(yōu)化方向了辙售。這邊我舉一個例子:
譬如倘要,我發(fā)現(xiàn)在 app、outer-form 兩個個模塊內(nèi)志鹃,有一塊公共的代碼曹铃,分別打入這兩個個模塊
此時可以在 webpack 配置優(yōu)化打包如下:
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
chunks: ['app', 'outer-form'] // 抽取commons chunk
}),
打包后體積略有減小陕见,因為這個地方屬于略有優(yōu)化。
動動眼睛動動手灰粮,其實還可以發(fā)現(xiàn)更多的優(yōu)化點忍坷,再比如:
OK,點到為止柑肴!
4. 最后
希望大家身上的肥油也咔咔掉