vue2升级vue3指南(一)—— 环境准备和构建篇

1、nodejs和npm

注意二者的版本,版本过低需要升级,本人升级后的版本如下:

$ node -v
v16.15.1

$ npm -v
8.11.0

2、package.json 和依赖升级

由于我的项目采用的原架构是vue2+vant2+sass+axios+webpack,且项目是通过vue-cli搭建的,因此升级完nodejs和npm后,便要对vue-cli进行升级。而后除了vue和webpack需要按照官方迁移构建文档进行升级处理,sass和vant也需要进行升级,vant由v2升级至v3,本着反正要升级的原则,axios也顺便做了升级处理(axios升级不是必须的,不想升级也无所谓)。

以下是我升级前后相关依赖的版本号对比:
升级前:

"dependencies": {
    ...
    "axios": "^0.21.1",
    "vant": "^2.12.40",
    "vue": "^2.6.11",
    "vue-router": "^3.2.0",
    "vuex": "^3.4.0"
    ...
},
"devDependencies": {
    ...
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "node-sass": "^4.14.1",
    "sass-loader": "^8.0.2",
    "script-ext-html-webpack-plugin": "^2.1.4",
    "vue-template-compiler": "^2.6.11",
    ...
}

升级后:

"dependencies": {
    ...
    "@vue/compat": "^3.1.0", // 新增
    "axios": "^0.27.2",
    "vant": "^3.5.2",
    "vue": "^3.1.0",
    "vue-router": "^4.1.1",
    "vuex": "^4.0.2"
    ...
},
"devDependencies": {
    ...
    "@vue/babel-plugin-jsx": "^1.1.1", // 新增
    // "@vue/cli-plugin-babel": "~4.5.0", // 删除
    "@vue/cli-plugin-eslint": "^5.0.7",
    "@vue/cli-plugin-router": "^5.0.7",
    "@vue/cli-plugin-vuex": "^5.0.7",
    "@vue/cli-service": "^5.0.7",
    "@vue/compiler-sfc": "^3.1.0",
    "node-sass": "^7.0.1",
    "sass-loader": "^13.0.2",
    // "vue-template-compiler": "^2.6.11", // 删除
    // "script-ext-html-webpack-plugin": "^2.1.4", // 删除
    "unplugin-vue-components": "^0.21.1",  // 新增:vant3需要
    ...
}

3、修改 vue.config.js

module.exports = {
  ...
  devServer: {
    ...
    // 原配置,会报错:options has an unknown property 'overlay'.
    // overlay: {
    //   warnings: false,
    //   errors: true
    // },

    // 新配置:
    // 可以将这部分功能关闭,因为项目虽然可以运行构建,但是文件中还有很多代码警告
    client: {
      overlay: {
        //  当出现编译器错误或警告时,在浏览器中显示全屏覆盖层
        warnings: false,
        errors: true
      },
    },
    ...
  },
  css: {
    ...
    loaderOptions: {
      scss: {
        // 升级后,属性名需要由 prependData 改为 additionalData
        additionalData:`
          @import "assets/css/mixin.scss";
          @import "assets/css/variables.scss";
          $cdn: "${defaultSettings.$cdn}";
          `
      }
    },
    ...
  },
  configureWebpack: {
    ...
    plugins: [
      ComponentsPlugin({ // vant3需要
        resolvers: [VantResolver()],
      }),
    ],
    ...
  },
  chainWebpack: config => {
    ...
    // 添加 vue 别名
    config.resolve.alias
      .set('vue', '@vue/compat')
    ...
    // vue-loader的相关部分也需要进行处理
    // 以下注释部分为原代码
    // config.module
    //   .rule('vue')
    //   .use('vue-loader')
    //   .loader('vue-loader')
    //   .tap(options => {
    //     options.compilerOptions.preserveWhitespace = true
    //     return options
    //   })
    //   .end()
    // 以下为新代码
    config.module
      .rule('vue')
      .use('vue-loader')
      .tap(options => {
        return {
          ...options,
          compilerOptions: {
            compatConfig: {
              MODE: 2 // 设置为2,表示开启兼容 VUe2 模式
            }
          }
        }
      })
    ...
  },
  ...
}

4、修改 babel.config.js

const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
const plugins = [
  [
    'import',
    "@vue/babel-plugin-jsx",
    {
      libraryName: 'vant',
      libraryDirectory: 'es',
      style: true
    },
    'vant'
  ]
]
// 去除 console.log
if (IS_PROD) {
  plugins.push('transform-remove-console')
}

module.exports = {
  // presets: [['@vue/cli-plugin-babel/preset', { useBuiltIns: 'usage', corejs: 3 }]],
  plugins
}

5、vuex 调整

升级前,我们使用时写法一般如下:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
  modules: {
    ...
  },
  ...
})

升级后,修改为如下写法:

import { createStore } from 'vuex'
const store = createStore({
  modules: {
    ...
  },
  ...
})

6、vue-router 调整

升级前,我们使用时写法一般如下:

import Vue from 'vue'
import Router from 'vue-router'

const constantRouterMap = {
  // 路由配置
  ...
}
Vue.use(Router)

const createRouter = () =>
  new Router({
    ...
    routes: constantRouterMap
  })

const router = createRouter()
export default router

升级后,修改为如下写法:

import { createRouter, createWebHashHistory } from 'vue-router'
const constantRouterMap = {
  // 路由配置
  ...
}

/*
官方文档说明:
新的 history 配置取代 mode#
mode: 'history' 配置已经被一个更灵活的 history 配置所取代。根据你使用的模式,你必须用适当的函数替换它:

"history": createWebHistory()
"hash": createWebHashHistory()
"abstract": createMemoryHistory()

更多内容可以参见官方文档:https://router.vuejs.org/zh/guide/migration/index.html#%E6%96%B0%E7%9A%84-history-%E9%85%8D%E7%BD%AE%E5%8F%96%E4%BB%A3-mode
*/

const router = createRouter({
  history: createWebHashHistory(), // hash模式
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRouterMap,
})

export default router

7、main.js 调整

升级前,我们使用时写法一般如下:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
...
import util from './utils/export' // 自己封装的全局通用方法库
// 可以直接这样绑定到Vue的原型链上
Vue.prototype.$util = util
...
new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App)
}).$mount('#app')

升级后,修改为如下写法:

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
...
import util from './utils/export'
...
const app = createApp(App)
app.use(router)
app.use(store)
app.config.globalProperties.$util = util
...
app.mount('#app')

8、npm run

至此,可以执行 npm run servenpm run build 了。

不过,升级并没有就此结束,相反,这只是一个开始,我们现在运行的代码还是兼容vue2模式,此外,在运行构建过程中,你会发现,尽管现在是兼容vue2模式,但是你的项目文件中还会有很多语法warning,这需要我们后续排查修改,直到真正完成Vue3的升级。

当升级完成后,就可以将@vue/compat从项目中移除了。

PS:实际项目构建运行中,发现vant3和兼容vue2模式有些冲突,如果需要vant3组件表现正常,最好将@vue/compat移除。

环境升级完成后,关于项目代码中的语法处理和报错警告处理,可以看我的这一篇文章~
vue2升级vue3指南(二)—— 语法warning&error篇

参考文献
用于迁移的构建版本
VUe-router 从 Vue2 迁移
vuex 从 3.x 迁移到 4.0
Vue CLI 文档

posted @ 2022-07-11 11:29  silencetea  阅读(6976)  评论(0编辑  收藏  举报