前言
公司的项目是用vue-cli4 构建的,最近要安装一个依赖,然后这个依赖在run serve是正常的,打包之后点击一次正常,再点击就报错。后面经过仔细排查,才发现是webpack的版本问题。
vue-cli4 安装的webpack4 的,vue-cli5 安装的是webpack5的。在vue-cli5安装这个依赖打包就没有这个问题。
所以接下来就要把vue-cli4
升级到vue-cli5
,因为是跨版本升级,很多写法,用法都不一样,太酸爽了,所以总结下这个过程,也算是温故知新。
正文
我们首先升级vue-cli的全局依赖。
我用的是yarn,如下
js
// npm
npm update -g @vue/cli
// yarn
yarn global upgrade --latest @vue/cli
升级成功,打印vue -V
可以查看最新的版本。
然后可以使用vue upgrade
升级项目的cli依赖(@vue/cli-plugin-
开头或者vue-cli-plugin-
开头)。
然后安装对应的依赖,就算升级成功了。
但是你以为就好了吗?
node-polyfill-webpack-plugin
webpack4会自动引入node的核心模块,比如path ,process ,os等等。而webpack5做了升级,不会自动引入,需要手动引入。
所以如果你的依赖有引用的话,打包的时候就会报错。
我们可以安装一个依赖来解决这个问题,node-polyfill-webpack-plugin
。
它可以自动引入node的核心模块,在vue.config.js中配置即可。
js
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')
// ...省略部分配置
configureWebpack: {
plugins: [
new NodePolyfillPlugin()
]
},
webpack自定义plugin
我们之前在项目写了一个webpack自定义插件,然后升级了vue-cli5后,打包报错了。
js
// vue.config.js
chainWebpack: (config) => {
// 自定义插件
config.plugin('customPluginName').use(require('./xx/plugins/xx/xx.js'))
},
configureWebpack: {
}
js
// custom plugin.js
const path = require('path')
class VersionPlugin {
apply (compiler) {
compiler.options.entry = {
...compiler.options.entry,
version: './xxx/version.js'
}
}
}
module.exports = VersionPlugin
查看了webpack5的文档,才发现入口的写法更丰富了。
原来entry可以是字符串,或者是字符串对象,数组。
js
entry: './app.js'
// or
entry: {
app: './app.js',
about: './xxx'
}
现在的webpack5在这个基础上,还支持import
,dependOn
等字段。
js
entry: {
app: {import: './app.js'},
about: {import:'./xxx', dependOn: 'xxx'}
}
看了wepback的部分源码发现,如果你的对象的value是字符串,它会拼接好一个import
字段,并且值是数组。如下:
但是我的自定义插件更改入口的执行时机晚于它这个时机,所以如果没有包裹import,它就会报错。
所以,自定义插件如果要更改入口,都要拼接import字段,防止报错。
js
const path = require('path')
class VersionPlugin {
apply (compiler) {
compiler.options.entry = {
...compiler.options.entry,
version: { import: ['./xxx/version.js'] }
}
}
}
module.exports = VersionPlugin
copy-webpack-plugin
首先我们项目用了copy-webpack-plugin来复制文件,vue-cli内置了它,但是版本不一样。
vue-cli4 安装了5.x.x版本的, vue-cli5 安装了9.x.x版本的。
js
// copy-webpack-plugin v5.x.x
plugins: [
new CopyWebpackPlugin([{
from: path.resolve(__dirname, './xx/xx/*.js'),
to: 'js/[name].[ext]'
}])
]
// copy-webpack-plugin v9.x.x
plugins: [
new CopyWebpackPlugin({
patterns: [{
from: path.resolve(__dirname, './xx/xx/*.js').replace(/\\/g, '/'),
to: 'js/[name][ext]'
}]
})
]
可以看到[name].[ext]
一个中间有点,一个中间没点。
还有带*
的写法,需要调用replace去替换\
,适应glob匹配。(不带*
可以不用调用replace)
eslint
如果你有使用eslint,vue-cli5的eslint 和eslint-plugin-vue的版本也升级了,跨版本升级会导致很多eslint规则都改变了,以前没有报错的,现在会疯狂报错。
比如组件的名称不能使用单个词,nextTick不能同时使用await和callback,不要对props传入的对象的key进行赋值修改。
太酸爽了,改这170个eslint错误。
总结
以上就是vuecli4升级到5遇到的问题总结,我建议不到万不得已不要在老项目上直接升级,不然会有很多bug等着你修复,最好是在新的项目使用vue-cli5。
不说了,我eslint的bug还没改完,还在改。。。