項(xiàng)目背景簡(jiǎn)介
- 多頁面應(yīng)用川无,每個(gè)頁面獨(dú)立entry,單個(gè)頁面內(nèi)使用vue-router
- 基于vue诅岩,使用vue-loader加載.vue文件
- 單頁內(nèi)使用懶加載異步chunk
項(xiàng)目二期上線后痘括,相對(duì)不辣么忙,眼看著webpack4也出來快半年了并且日趨穩(wěn)定挥唠,之前雖然寫過demo測(cè)試使用抵恋,但還未在項(xiàng)目中用過,于是擇日不如撞日一鼓作氣開啟了升級(jí)【踩坑】之旅
升級(jí)之旅
首先保證 node>= 6.11.5宝磨,建議使用8以上LTS版本
相關(guān)依賴包安裝或更新
以下是我的項(xiàng)目中使用到的依賴安裝或更新情況弧关,不同項(xiàng)目使用loader盅安、插件不同,這部分得根據(jù)自身情況調(diào)整
主要依賴:
- webpack安裝最新
- webpack-cli安裝(啟動(dòng)webpack)
- webpack-dev-server更新至3以上
- vue-loader更新至15以上
- 安裝mini-css-extract-plugin
其他:
babel相關(guān)依賴世囊、html-webpack-plugin别瞭、file-loader、url-loader株憾、sass-loader等我都升級(jí)了版本蝙寨,或者也可以修改完配置后,運(yùn)行起來看看控制臺(tái)是否有相關(guān)報(bào)警再更新
輔助:
推薦安裝webpack-bundle-analyzer插件嗤瞎,可以分析構(gòu)建結(jié)果依賴關(guān)系
配置變更
接下來來到這次愉快踩坑之旅的重頭戲了墙歪!
mode
mode
是webpack4新增的配置項(xiàng),也是本次更新的亮點(diǎn)之一贝奇,簡(jiǎn)單理解就是告訴webpack本次構(gòu)建模式虹菲,使其可以對(duì)構(gòu)建使用對(duì)應(yīng)的優(yōu)化策略〉敉回想之前寫工程化配置毕源,也會(huì)區(qū)分開發(fā)模式和生產(chǎn)模式的配置入口,webpack4提供了mode
降低了不少配置成本陕习。
mode
可被設(shè)置為development
(默認(rèn))或production
module.exports = {
mode: 'production'
};
development
側(cè)重于優(yōu)化開發(fā)體驗(yàn)霎褐,production
側(cè)重于優(yōu)化模塊體積和線上部署,具體優(yōu)化內(nèi)容這里就不搬運(yùn)官方文檔了该镣,對(duì)于我的項(xiàng)目而言比較在意的有以下幾點(diǎn):
- 將自動(dòng)設(shè)置
process.env.NODE_ENV
為對(duì)應(yīng)值(development
或production
)冻璃,原手工配置process.env.NODE_ENV = 'development' ;
的代碼可以刪除 -
production
模式將自動(dòng)加入代碼壓縮功能,可刪除原new UglifyJsPlugin()
相關(guān)代碼
更多說明參考 https://medium.com/webpack/webpack-4-mode-and-optimization-5423a6bc597a
optimization
webpack4根據(jù)mode
配置對(duì)構(gòu)建進(jìn)行優(yōu)化拌牲,也可以通過覆蓋optimization
配置進(jìn)一步定制兩種構(gòu)建模式下的優(yōu)化策略俱饿,并且官方移除了CommonsChunkPlugin
插件。
其中項(xiàng)目升級(jí)最大的變更就在CommonsChunkPlugin
插件的移除和optimization
下splitChunks
塌忽、runtimeChunk
的配置
另外由于代碼壓縮功能將在production
模式下自動(dòng)開啟拍埠,如果需要對(duì)js壓縮或css壓縮策略定制,則需要覆蓋默認(rèn)optimization.minimizer
配置
splitChunks
關(guān)于splitChunks
可以單獨(dú)用一篇文章進(jìn)行詳細(xì)說明土居,這里我只是按原項(xiàng)目的緩存策略修改(CommonsChunkPlugin
配置): 抽取/node_modules/下第三方依賴作為公共vendor(基于第三方依賴更新頻率低)
默認(rèn)配置下枣购,splitChunks
只對(duì)懶加載的模塊產(chǎn)生影響
注釋部分是splitChunks的默認(rèn)配置,這里僅修改cacheGroups內(nèi)vendor相關(guān)配置擦耀,將chunks改成'initial'避免將部分異步加載的較大的第三方依賴也合并到vendor中
splitChunks: {
//chunks: 'async',
//minSize: 30000,
//minChunks: 1,
//maxAsyncRequests: 5,
//maxInitialRequests: 3,
//automaticNameDelimiter: '~',
//name: true,
cacheGroups: {
vendor: {
name: 'vendor',
//@NOTE 配置成all 會(huì)把a(bǔ)sync的也打進(jìn)來
chunks: 'initial',
priority: -10,
test: /[\\/]node_modules[\\/]/
}
}
}
runtimeChunk
之前的production
模式構(gòu)建會(huì)使用CommonChunkPlugin
抽取runtime code(這部分概念不了解的可以參考https://webpack.js.org/concepts/manifest/#src/components/Sidebar/Sidebar.jsx)作為單獨(dú)的chunk棉圈,升級(jí)后這部分配置需要寫到optimization.runtimeChunk
中:
- 默認(rèn)設(shè)置為
false
,runtime code包含在基于各個(gè)entry抽取的第一個(gè)chunk中(注意:由于本項(xiàng)目抽取了公用vendor眷蜓,針對(duì)本項(xiàng)目會(huì)將所有entry的runtime代碼抽取到公用vendor中分瘾,vendor將失去瀏覽器緩存意義) - 配置為
single string
,所有entry的runtime代碼將會(huì)抽取為一個(gè)chunk - 配置為一個(gè)生成函數(shù)吁系,可以基于每個(gè)entry獨(dú)立抽取runtime代碼(本項(xiàng)目使用德召,多個(gè)獨(dú)立頁面多入口)
配置成生成函數(shù)的代碼:
runtimeChunk: {
name: entrypoint => `manifest~${entrypoint.name}`
},
minimizer
這個(gè)接收單個(gè)對(duì)象或?qū)ο髷?shù)組白魂,指定壓縮插件和配置,相對(duì)比較簡(jiǎn)單上岗,這里就不詳細(xì)描述了
minimizer: [
// 配置UglifyJsPlugin壓縮js文件
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: true
}),
// 配置css文件壓縮
new OptimizeCSSAssetsPlugin({
cssProcessor: require('cssnano'),
cssProcessorOptions: {
discardComments: {removeAll: true},
// 避免 cssnano 重新計(jì)算 z-index
safe: true
},
canPrint: false
})
]
mini-css-extract-plugin
webpack4之后福荸,Extract-text-plugin
不再適用于css文件抽取,如果還要繼續(xù)使用安裝時(shí)只能通過@next版本安裝(yarn add extract-text-plugin@next)肴掷,除此之外contenthash
不支持使用在文件名中敬锐、會(huì)生成一些多余的chunk css文件
mini-css-extract-plugin
專用于抽取css文件支持async-loading,只能配合webpack4使用呆瞻,但目前暫時(shí)還不支持HMR(Hot Module Replace)台夺,本項(xiàng)目只在production
下使用這個(gè)插件
配置相對(duì)Extract-text-plugin
是簡(jiǎn)單一些
// loader部分(項(xiàng)目使用scss)
test: /\.(sa|sc|c)ss$/,
use: [
isProd ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
... ...
}
},
],
},
// plugin部分
plugins.push(
new MiniCssExtractPlugin({
filename: isProd ? "css/[name].[contenthash:8].css" : "css/[name].css";
})
);
vue-loader
vue-loader配合webpack4升級(jí)到了v15版本,升級(jí)之后配置方式發(fā)生了一些改變栋烤,以下是項(xiàng)目中使用到的部分:
- 增加一個(gè)步驟:需要以plugin方式添加到webpack配置中
- v15版本之后谒养,使用了不同的策略推導(dǎo).vue文件中各個(gè)語言塊使用的loader挺狰,將各個(gè)語言塊視為獨(dú)立的文件使用webpack中配置了規(guī)則的loader處理明郭,由此帶來的配置變化就是針對(duì)樣式處理,webpack.rules中必須顯示提供對(duì)應(yīng)loader處理的規(guī)則丰泊,原vue-loader配置中內(nèi)聯(lián)傳入的樣式相關(guān)loader可以去除
- 鑒于推導(dǎo)變化薯定,
<script></script>
標(biāo)簽內(nèi)的js代碼將被視為獨(dú)立的js文件并根據(jù)webpack配置使用babel-loader轉(zhuǎn)譯;項(xiàng)目配置babel-loader時(shí)使用exclude: /node_modules/
排除依賴包中代碼的轉(zhuǎn)譯瞳购,如果導(dǎo)入了/node_modules/
中的.vue文件话侄,<script>
部分將不能被轉(zhuǎn)譯,故需要將.vue文件加入到排除白名單中
// 增加一個(gè)plugin
const VueLoaderPlugin = require('vue-loader/lib/plugin')
plugin.push( new VueLoaderPlugin())
// rules loader配置
// @UPDATED
// vue-loader v15+版本 .vue文件中的樣式將被抽取出來并認(rèn)為和獨(dú)立引入的css文件相同
// 故需要配置單獨(dú)loader處理
... ...
{
test: /\.(sa|sc|c)ss$/,
use: [
isProd ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
includePaths: ['src/static/scss']
}
},
],
},
// .vue文件
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
// @UPDATED @DEPRECATED
// v15+版本不再需要提供內(nèi)聯(lián)的cssloader配置
// 如果不去掉會(huì)報(bào)錯(cuò)
// loaders: util.cssLoaders({
// sourceMap: false,
// extract: build,
// build: build
// })
}
},
// .js文件
{
test: /\.js$/,
loader: 'babel-loader',
exclude: file => (
// @UPDATED
// vue-loader v15+版本
// /node_modules/中的.vue文件需要經(jīng)過babel-loader轉(zhuǎn)譯
/node_modules/.test(file) &&
!/\.vue\.js/.test(file)
)
}
... ...
其他變更可以參考vue-loader官方文檔說明https://vue-loader.vuejs.org/migrating.html#notable-breaking-changes
DEMO
項(xiàng)目webpack4配置demo学赛,可以參考~~
https://github.com/icyfanfan/try-webpack4
參考
webpack官方文檔
https://medium.com/webpack/webpack-4-mode-and-optimization-5423a6bc597a
https://medium.com/webpack/webpack-4-import-and-commonjs-d619d626b655
https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
mini-css-extract-plugin
https://github.com/webpack-contrib/mini-css-extract-plugin
vue-loader
https://vue-loader.vuejs.org/migrating.html#notable-breaking-changes