前言
現在距離2018年2月15號webpack4.0.0出來已經有一段時間了,現在已經出了 @vue/cli 3.0,但是樓主還沒試過,聽說很強大,想要試水的可以看文件 @vue/cli,官方腳手架都用上webpack4了,你專案還停留在webpack3,甚至webpack2,是不是覺得落伍了。
受號稱0配置的parcel啟發,webpack4 增加了一些預設配置,摒棄掉了一些難懂的配置,對使用者更加友好,下面我來講一講比較大的一些變化
環境
不再支援 Node.js 4。
預設出入口
在 Webpack 4 中,不再強制要求指定 entry 和 output 路徑。webpack 4 會預設 entry 為 ./src,output 為 ./dist,當然了,這只是開胃菜。
mode 構建模式
webpack 提供了兩種構建模式可供選擇 development 和 production
選項 | 描述 |
---|---|
development | 會將 process.env.NODE_ENV 的值設為 development。啟用 NamedChunksPlugin(固化 runtime 內以及在使用動態載入時分離出的 chunk 的 chunk id) 和 NamedModulesPlugin(開啟 HMR[熱過載]的時候使用該外掛會顯示模組的相對路徑)。 |
production | 會將 process.env.NODE_ENV 的值設為 production。啟用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin. |
也就是說如果 mode 為development 時候官方腳手架可以砍掉的程式碼
// webpack.development.config.js
module.exports = {
+ mode: `development`
- plugins: [
- new webpack.NamedModulesPlugin(),
- new webpack.DefinePlugin({
- `process.env`: require(`../config/dev.env`)
- }),
- ]
}
複製程式碼
如果 mode 為production 時候官方腳手架可以砍掉的程式碼
// webpack.production.config.js
module.exports = {
+ mode: `production`,
- plugins: [
- new UglifyJsPlugin(/* ... */),
- new webpack.DefinePlugin({
- `process.env`: require(`../config/dev.env`)
- }),
- new webpack.optimize.ModuleConcatenationPlugin()
- ]
}
複製程式碼
import(): 動態匯入
在 webpack 4 中,import() 會返回一個帶名稱空間(namespace)的物件,這對 ES Module 不會有影響,但對於遵循 commonjs 規範的模組則會加一層包裹:
// webpack 2/3
import("./commonjs").then(exports => {
// ...
})
// webpack 4
import("./commonjs").then({default: exports}=> {
// ...
})
複製程式碼
optimization 配置項
配置項新增了 optimization 選項,智慧的根據所選模式mode為做執行優化。
使用這個配置的時候之前的一些外掛可以使用 optimization 裡的配置代替
- NoEmitOnErrorsPlugin 替換為 optimization.noEmitOnErrors (預設只在 production 模式)
- ModuleConcatenationPlugin 替換為 optimization.concatenateModules(預設只在 production 模式)
- NamedModulesPlugin 替換為 optimization.namedModules(預設只在 develoment 模式)
CommonsChunkPlugin 外掛被棄用,使用 optimization.splitChunks, optimization.runtimeChunk 代替
// webpack.prod.conf.js
const config = {
// ...
plugins: [
- new webpack.NoEmitOnErrorsPlugin(),
- new webpack.optimize.ModuleConcatenationPlugin(), // 預編譯
- new webpack.optimize.CommonsChunkPlugin({
- name: `vendor`,
- minChunks (module) {
- // any required modules inside node_modules are extracted to vendor
- return (
- module.resource &&
- /.js$/.test(module.resource) &&
- module.resource.indexOf(
- path.join(__dirname, `../node_modules`)
- ) === 0
- )
- }
- }),
- new webpack.optimize.CommonsChunkPlugin({
- name: `manifest`,
- minChunks: Infinity
- }),
],
+ optimization: {
+ noEmitOnErrors: true,
+ concatenateModules: true,
+ splitChunks: {
+ chunks: `all`,
+ name: `common`,
+ },
+ runtimeChunk: {
+ name: `runtime`
+ }
+ }
};
複製程式碼
// webpack.dev.conf.js
const config = {
// ...
plugins: [
- new webpack.NamedModulesPlugin()
]
+ optimization: {
+ namedModules: true
+ }
};
複製程式碼
optimization.splitChunks 預設是不用設定的。如果 mode 是 production,那 Webpack 4 就會開啟 Code Splitting。預設 Webpack 4 只會對按需載入的程式碼做分割。如果我們需要配置初始載入的程式碼也加入到程式碼分割中,可以設定 splitChunks.chunks 為 `all`
壓縮
webpack4 的mode 設定成 production 時,預設開啟程式碼壓縮,但是我要敲黑板,劃重點了,uglifyjs-webpack-plugin 終於到 v1.0.0 版本了,支援多程式壓縮,快取以及es6語法,無需單獨安裝轉換器。感動不感動。想看的話可以看這裡順風車。想要覆蓋配置可以這樣
const UglifyJsPlugin = require(`uglifyjs-webpack-plugin`)
module.exports = {
// ...
optimization: {
minimizer: [
new UglifyJsPlugin() // 具體配置可看github
]
}
}
複製程式碼
##移除的功能 ##
移除了 module.loaders
移除了 loaderContext.options
移除了 Compilation.notCacheable
移除了 NoErrorsPlugin
移除了 Dependency.isEqualResource
移除了 NewWatchingPlugin
移除了 CommonsChunkPlugin
周邊
既然講了 webpack 做了比較大的更新,周邊的配套設施也不要不捨得,改換久換,由於我平時專案中使用vue,如果你也使用vue的話,那麼針對vue的有幾個變化你要知道:
vue-loader
什麼?學不動了,只要用官網的腳手架不就好了?前端的知識不斷更新,固步自封,只會不進則退。但是你要相信,webpack也好,vue-loader 也好,api 會越來越好懂,效能也會更加高效,所以,扶我起來,我還能學。。。
Vue Loader v15 使用了一個不一樣的策略來推導語言塊使用的 loader。vue-loader v15
在 v14 或更低版本中,如果你想為一個推匯出來的 loader 定製選項,你不得不在 Vue Loader 自己的 loaders 選項中將它重複一遍。在 v15 中你再也沒有必要這麼做了。
拿官方腳手架來說, 可以看到兩個函式,用來生成 vue-loader 的 options 還有 module.rule, 我把他們摘出來,就可以看出來了。
// util.js
exports.cssLoaders = function (options) {
// ...
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
// ...
}
複製程式碼
// vue-loader-conf.js
module.exports = {
loaders: utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: isProduction
}),
...
}
複製程式碼
// webpack.dev.config
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
...
}
複製程式碼
我剛入腳手架的坑的時候都蒙了,為什麼要這樣寫,為了德瑪西亞麼?當然不是,是因為填 vue-loader v14 的坑
vue-loader v15版本只要寫一遍就好了,但是要注意請確保在你的 webpack 配置中新增 Vue Loader 的外掛
// webpack.config.js
const VueLoaderPlugin = require(`vue-loader/lib/plugin`)
module.exports = {
module: {
rules: [
{
test: /.vue$/,
loader: `vue-loader`
},
// ...
]
},
plugins: [
// 請確保引入這個外掛!
new VueLoaderPlugin()
]
}
複製程式碼
然後由於生產和測試環境對 css 檔案處理不同。在webpack.dev.config.js和webpack.prod.config.js裡分別配置 less/scss css 的loader就好了:
{
module: {
rules: [
// ...
{
test: /.less$/,
use: [
`vue-style-loader`,
`css-loader`,
`less-loader`
]
}
]
}
}
複製程式碼
mini-css-extract-plugin css 抽取
webpack v4 官方不在推薦使用 extract-text-webpack-plugin 了,改換 mini-css-extract-plugin
// webpack4
npm install -D mini-css-extract-plugin
// webpack.config.js
var MiniCssExtractPlugin = require(`mini-css-extract-plugin`)
module.exports = {
// 其它選項...
module: {
rules: [
// ... 忽略其它規則
{
test: /.css$/,
use: [
process.env.NODE_ENV !== `production`
? `vue-style-loader`
: MiniCssExtractPlugin.loader,
`css-loader`
]
}
]
},
plugins: [
// ... 忽略 vue-loader 外掛
new MiniCssExtractPlugin({
filename: style.css
})
]
}
複製程式碼
// webpack3
npm install -D extract-text-webpack-plugin
// webpack.config.js
var ExtractTextPlugin = require("extract-text-webpack-plugin")
module.exports = {
// 其它選項...
module: {
rules: [
// ...其它規則忽略
{
test: /.css$/,
loader: ExtractTextPlugin.extract({
use: `css-loader`,
fallback: `vue-style-loader`
})
}
]
},
plugins: [
// ...vue-loader 外掛忽略
new ExtractTextPlugin("style.css")
]
}
複製程式碼
福利
對webpack3官方腳手架還不是很瞭解的同學可以看我根據自己理解寫的註釋,詳情點這裡
覺得麻煩,不想自己搞?那也沒關係,我自己按照腳手架改了一套,感興趣的可以試試點這裡
覺得不錯請star哦,另外,我準備在下一篇文章中將如何如優化webpack,喜歡的話可關注