webpack4 也发布3个月了,一直想体验一下。最近项目不忙,也感觉项目编译和打包的速度略慢,索性就把一个由 vue-cli 生成的项目从 webpack3 升级到 webpack4,期间遇到的问题也记录一下。
安装依赖
npm i webpack@latest webpack-cli --save-dev
出现报错信息:
根据报错信息,逐个升级它们:
npm install extract-text-webpack-plugin@latest html-webpack-plugin@latest inject-loader@latest webpack-dev-middleware@latest webpack-dev-server@latest
顺便把其它 loaders
及 plugins
都升级到最新版本
npm install webpack-bundle-analyzer@latest vue-template-compiler@latest webpack-merge@latest friendly-errors-webpack-plugin@latest copy-webpack-plugin@latest optimize-css-assets-webpack-plugin@latest
npm install css-loader@latest file-loader@latest url-loader@latest less-loader@latest postcss-loader@latest vue-loader@latest vue-style-loader@latest
升级的版本信息如下:
运行 npm run dev
,又出现 eslint
的报错信息
npm i eslint@latest eslint-config-standard@latest eslint-friendly-formatter@latest eslint-loader@latest eslint-plugin-import@latest eslint-plugin-node@latest eslint-plugin-promise@latest eslint-plugin-standard@latest eslint-plugin-vue@latest
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
配置
相比于 webpack 3,webpack 4 的配置部分改变,具体如下:
在 dev 环境中,添加 mode: 'development'
,去掉 webpack.NamedModulesPlugin 及 webpack.NoEmitOnErrorsPlugin 插件,因为 webpack4 开发模式已经内置。
// webpack.dev.conf.js
module.exports = {
// ...
mode: 'development',
// ...
plugins: {
// new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
// new webpack.NoEmitOnErrorsPlugin(),
}
}
复制代码
在 prod 环境中添加 mode 配置,用 optimization 代替以前的 webpack.optimize.CommonsChunkPlugin 、 uglifyjs-webpack-plugin 、 webpack.optimize.ModuleConcatenationPlugin 相关配置及引用
// webpack.production.prod.js
// const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const webpackConfig = merge(baseWebpackConfig, {
// ...
mode: 'production',
// webpack4 内置
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
chunks: 'initial',
name: 'vendors',
},
'async-vendors': {
test: /[\\/]node_modules[\\/]/,
minChunks: 2,
chunks: 'async',
name: 'async-vendors'
}
}
},
runtimeChunk: { name: 'runtime' }
},
// ...
pluins: {
// new UglifyJsPlugin({
// uglifyOptions: {
// beautify: false,
// comments: false,
// compress: {
// warnings: false,
// drop_console: true
// }
// },
// sourceMap: config.build.productionSourceMap,
// parallel: true
// }),
// ...
// enable scope hoisting
// new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
// 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
// )
// }
// }),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
// new webpack.optimize.CommonsChunkPlugin({
// name: 'manifest',
// minChunks: Infinity
// }),
// // This instance extracts shared chunks from code splitted chunks and bundles them
// // in a separate chunk, similar to the vendor chunk
// // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
// new webpack.optimize.CommonsChunkPlugin({
// name: 'app',
// async: 'vendor-async',
// children: true,
// minChunks: 3
// }),
}
}
复制代码
运行 npm run dev
,又出现 vue-loader
的报错信息:
vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.
为了解决上面的 vue-loader
的报错,在 webpack.base.conf.js 中添加配置
// webpack.base.conf.js
const { VueLoaderPlugin } = require('vue-loader')
//...
plugins: [
new VueLoaderPlugin()
]
复制代码
运行 npm run dev
,报错:
虽然有报错信息,但是没有显示错误的具体位置。在网上查找了很久,发现有人说他在template file
和 routing file
出现了循环引用。 根据这个,我突然发现在 main.js
和 向后台请求的api文件中都引用了路由文件,api.js
中引用是为了写 axios
拦截器,出现 401、404 或 500 时,跳转相应页面。 注释掉 api.js
中对 router
的引用,确实可以成功运行了,但是 401、404、500 跳页的问题就没法解决了。 但是后来我又找到了另一种方法,在 HtmlWebpackPlugin
插件中添加或者修改 chunksSortMode: none
。(不过不确定这方式会不会对性能优化等等有影响)
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true,
chunksSortMode: 'none'
}),
复制代码
运行 npm run dev
,没问题了。
接下来试试生产环境,运行 npm run build
。1分钟过去了……5分钟过去了……中午吃饭1个小时都过去了……居然没反应,也没有报错。又尝试了好几次,依旧如此。在网上也没有找到相关问题。
于是我只好在 build.js
中逐步打断点,最后发现是 extract-text-webpack-plugin
插件的问题。 查找资料了解到 extract-text-webpack-plugin
其实是适配 webpack3 的,有个 [email protected]
版本可以适配 webpack4,但是我用的就是这个版本。
有人推荐用 mini-css-extract-plugin
来替代它,我就根据 文档尝试配置一下。
需要在 webpack.prod.conf.js
和 utils.js
两个文件中配置。
// webpack.prod.conf.js
// const ExtractTextPlugin = require('extract-text-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// ...
// extract css into its own file
// new ExtractTextPlugin({
// ...
// })
// 升级 webpack4, 由 ExtractTextPlugin 改用 MiniCssExtractPlugin
new MiniCssExtractPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
allChunks: true,
}),
复制代码
// utils.js
// const ExtractTextPlugin = require('extract-text-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// ...
// generate loader string to be used with extract text 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
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
// if (options.extract) {
// return ExtractTextPlugin.extract({
// use: loaders,
// fallback: 'vue-style-loader'
// })
// } else {
// return ['vue-style-loader'].concat(loaders)
// }
// 升级 webpack4, 由 ExtractTextPlugin 改用 MiniCssExtractPlugin
return [
options.extract ? MiniCssExtractPlugin.loader : 'vue-style-loader',
].concat(loaders)
}
复制代码
运行 npm run build
,终于成功了。
附上 webpack3 和 webpack4 的打包对比图,可以看到,体积少了一点(后期我会在边学习 webpack 边进行优化)但是打包的时间减少了一半,也不枉费我这么辛苦的升级。
参考
- vue-cli#webpack3.0 升级到webpack4.6
- Webpack4 新特性 及 Vue-cli项目升级
- https://github.com/jantimon/html-webpack-plugin/issues/870
- https://webpack.js.org/plugins/mini-css-extract-plugin/
- https://vue-loader.vuejs.org/guide/extract-css.html#webpack-4