對之前開發的項目升級webpack4.0的一個總結。
- 先升級webpack的版本
npm install webpack@latest webpack-cli -D
升級成功後,我們會發現,package.json
文件中的webpack
版本以及變成4.0
以上。接下來將我們使用的插件和·loader·全部升級到最新的版本。
執行的命令是:
npm install loadername@latest -D
請根據自己使用的插件和loader進行升級操作。
升級完成之後,接下來我們來修改配置文件:
webpack.dev.conf.js文件
由於webpack4採用了mode
選項來區分開發環境和生產環境,因此,我們需要在webpack.dev.conf.js
文件中設置mode
屬性。並且將NamedModulesPlugin
和NoEmitOnErrorsPlugin
兩個插件註釋掉。因爲webpack4開啓development
模式已經默認使用它們了。
const devWebpackConfig = merge(baseWebpackConfig, {
mode: 'development',
// ....
plugins: [
//...
// 更新到webpack4 需要註釋掉這兩個插件
// new webpack.NamedModulesPlugin(),
// new webpack.NoEmitOnErrorsPlugin(),
]
})
webpack.prod.conf.js
webpack.prod.conf.js
文件中需要設置mode
選項,將mode
的選項值設置成'production'
,
- new NoEmitOnErrorsPlugin(),
- new ModuleConcatenationPlugin(),
- new DefinePlugin({ “process.env.NODE_ENV”: JSON.stringify(“production”) })
- new UglifyJsPlugin()
以上的這些插件全部註釋掉,因爲webpack4
的 production
模式下已經默認引用了這些插件。
而webpack4最大的變化就是棄用了CommonsChunkPlugin
,而採用了 optimization.splitChunks
選項。因此,我們需要移除掉與CommonsChunkPlugin
有關的所有配置。最終,webpack.prod.conf.js
文件變成這樣:
const webpackConfig = merge(baseWebpackConfig, {
mode: 'production',
// ....
// 此配置用來替代plugin裏面的配置
optimization: {
minimizer: [
// 壓縮代碼
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: config.build.productionSourceMap,
}),
// 可自己配置,建議第一次升級先不配置
new OptimizeCSSPlugin({
}),
],
// 可自己配置,建議第一次升級先不配置
splitChunks: {
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
chunks: 'initial',
name: 'vendors',
},
'async-vendors': {
test: /[\\/]node_modules[\\/]/,
minChunks: 2,
chunks: 'async',
name: 'async-vendors'
}
}
}
},
plugins: [
// new webpack.DefinePlugin({
// 'process.env': env
// }),
// new UglifyJsPlugin({
// uglifyOptions: {
// beautify: false,
// comments: false,
// compress: {
// warnings: false,
// drop_console: true
// }
// },
// sourceMap: config.build.productionSourceMap,
// parallel: true
// }),
// 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
// }),
// new webpack.optimize.CommonsChunkPlugin({
// name: 'app',
// async: 'vendor-async',
// children: true,
// minChunks: 3
// }),
]
});
這個時候運行npm run dev
,此時報錯:
vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.
在升級到webpack4
的時候,我們需要手動引入vue-loader
的插件,接下來,修改vue-loader.conf.js
文件.
vue-loader.conf.js
module.exports = {
// loaders: utils.cssLoaders({
// sourceMap: sourceMapEnabled,
// extract: isProduction,
// usePostCSS: true
// }),
// cssSourceMap: sourceMapEnabled,
// cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
}
接下來在webapck.base.conf.js
文件中引入vue-loader
的插件
const { VueLoaderPlugin } = require('vue-loader')
//...
plugins: [
new VueLoaderPlugin()
]
此時再次運行npm run dev
,如果報下面的這種錯誤:
vue-template-compiler must be installed as a peer dependency, or a compatible compiler implementation must be passed via options.
解決方法:
- 將你的
vue-loader
升級到最新的版本 - 如果已經處於最新的版本,檢測
vue-loader
是否已經安裝成功 - 如果在
package.json
文件中已經存在vue-loader
,此時仍然報這個錯誤,就將node_modules文件夾刪掉,再執行npm install
進行重新安裝。
此時再次運行npm run dev
,就可以看到編譯成功。
接下來讓我們打包一下試試看,運行 npm run build
。如果此時報錯,且錯誤與extract-text-webpack-plugin
有關的話,在這裏建議將extract-text-webpack-plugin
替換成mini-css-extract-plugin
插件。
安裝mini-css-extract-plugin
npm install mini-css-extract-plugin@latest -D
在webpack.prod.conf.js文件中將extract-text-webpack-plugin
的配置註釋掉,添加mini-css-extract-plugin的配置。
// webpack.prod.conf.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const webpackConfig = merge(baseWebpackConfig, {
// ...
plugins: [
// ...
// 升級 webpack4, 由 ExtractTextPlugin 改用 MiniCssExtractPlugin
new MiniCssExtractPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
allChunks: true,
}),
]
});
修改utlis.js
文件
// utlis.js
// const ExtractTextPlugin = require('extract-text-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// ....
function generateLoaders (loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// 升級 webpack4, 由 ExtractTextPlugin 改用 MiniCssExtractPlugin
return [
options.extract ? MiniCssExtractPlugin.loader : 'vue-style-loader',
].concat(loaders);
}
此時再次運行npm run build
便可以看到成功打包。升級了webpack4之後打包的時間縮短了很多。
在成功升級到webpack4.0之後,又遇到了問題,便是每次更新的時候都會把所有頁面編譯一遍,此時的解決辦法:
-
檢測
vue-loader
的版本,webpack4
所配置的vue-loader
的版本,必須是v15
以上的。 -
如果vue-loader的版本是最新的,請檢測
webpack.dev.conf.js
文件中,是否有配置mode
選項。