webpack4 也发布3个月了,一直想体验一下。最近项目不忙,也感受项目编译和打包的速度略慢,索性就把一个由 vue-cli 生成的项目从 webpack3 升级到 webpack4,期间遇到的问题也记录一下。javascript
npm i webpack@latest webpack-cli --save-dev
css
出现报错信息:html
根据报错信息,逐个升级它们:vue
npm install extract-text-webpack-plugin@latest html-webpack-plugin@latest inject-loader@latest webpack-dev-middleware@latest webpack-dev-server@latest
java
顺便把其它 loaders
及 plugins
都升级到最新版本node
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
webpack
npm install css-loader@latest file-loader@latest url-loader@latest less-loader@latest postcss-loader@latest vue-loader@latest vue-style-loader@latest
ios
升级的版本信息以下:git
webpack@4.8.3github
webpack-cli@2.1.4
html-webpack-plugin@3.2.0
extract-text-webpack-plugin@4.0.0-beta.0
webpack-dev-server@3.1.4
webpack-dev-middleware@3.1.3
friendly-errors-webpack-plugin@1.7.0
webpack-bundle-analyzer@2.13.1
webpack-merge@4.1.2
optimize-css-assets-webpack-plugin@4.0.1
copy-webpack-plugin@4.5.1
vue-template-compiler@2.5.16
postcss-loader@2.1.5
inject-loader@4.0.1
less-loader@4.1.0
css-loader@0.28.11
vue-style-loader@4.1.0
file-loader@1.1.11
vue-loader@15.2.0
url-loader@1.0.1
运行 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
相比于 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
拦截器,出现 40一、404 或 500 时,跳转相应页面。 注释掉 api.js
中对 router
的引用,确实能够成功运行了,可是 40一、40四、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 的,有个 extract-text-webpack-plugin@4.0.0-beta.0
版本能够适配 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 边进行优化)可是打包的时间减小了一半,也不枉费我这么辛苦的升级。