对之前开发的项目升级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
选项。