目录
- 方案概述
- 核心原理:@vue/compat 兼容构建
- 详细操作步骤
- 步骤一:环境与依赖准备
- 步骤二:入口文件改造
- 步骤三:路由迁移 vue-router-3x–4x
- 步骤四:状态管理迁移 vuex-3x–4x
- 步骤五:组件逐文件迁移(核心阶段)
- 步骤六:第三方 UI 库迁移
- 步骤七:构建工具优化(可选)
- 步骤八:移除兼容层
- 破坏性变更详解
- 迁移策略与优先级
- 常见问题 FAQ
- 迁移检查清单
1. 方案概述
1.1 什么是方案一
方案一是指在不拆分微前端的前提下,将现有的 Vue2 单体应用渐进式升级到 Vue3。
核心思路:利用 Vue3 官方提供的@vue/compat(兼容构建),让 Vue3 内核运行 Vue2 风格的代码,然后逐个文件、逐个组件地迁移到 Vue3 原生写法,最后移除兼容层。
1.2 与方案二(qiankun 微前端)的区别
| 维度 | 方案一(纯升级) | 方案二(qiankun 微前端) |
|---|---|---|
| 应用形态 | 保持单体应用 | 拆分为多个独立子应用 |
| 项目结构 | 不变 | 需要新建主应用 + 拆分 |
| 构建方式 | 一次构建 | 各子应用独立构建 |
| 部署方式 | 整体部署 | 独立部署 |
| 学习成本 | 低 | 中高 |
| 适合场景 | 中小型项目、团队规模小 | 大型项目、多团队协作 |
| Vue2/Vue3 共存 | 过渡期共存(compat 模式) | 长期共存(不同子应用) |
1.3 渐进式迁移路线图
整个应用(单体,不拆分) ┌──────────────────────────────────────────────────────────┐ │ │ │ 阶段1: Vue2 代码 + @vue/compat (Vue3内核) │ │ ├─ 99% 代码不变,项目直接跑起来 │ │ ├─ 控制台会有弃用警告(DEPRECATION) │ │ └─ 时间:1-2 天 │ │ │ │ 阶段2: 逐步改造组件为 Vue3 原生写法 │ │ ├─ 逐个文件迁移,可与业务开发并行 │ │ ├─ 控制台警告逐渐减少 │ │ └─ 时间:2-6 周(取决于项目规模) │ │ │ │ 阶段3: 移除 @vue/compat,纯 Vue3 运行 │ │ ├─ 全量回归测试 │ │ ├─ 享受 Vue3 全部特性 │ │ └─ 时间:1 周 │ │ │ └──────────────────────────────────────────────────────────┘2. 核心原理:@vue/compat 兼容构建
2.1 什么是 @vue/compat
@vue/compat是 Vue3 官方提供的兼容构建版本。它在 Vue3 内核之上增加了一个兼容层,使得大部分 Vue2 的 API 和语法能够在 Vue3 环境中运行。
2.2 兼容层做了什么
┌─────────────────────────────────────┐ │ 你的 Vue2 代码 │ │ (Options API, $set, filters, ...) │ ├─────────────────────────────────────┤ │ @vue/compat 兼容层 │ │ ├─ 将 Vue2 API 翻译为 Vue3 API │ │ ├─ 发出弃用警告(DEPRECATION) │ │ └─ 标记哪些代码需要迁移 │ ├─────────────────────────────────────┤ │ Vue3 内核 │ │ (Proxy 响应式, Composition API) │ └─────────────────────────────────────┘2.3 兼容模式的行为
| 行为 | 说明 |
|---|---|
| 完全兼容 | Options API(data、methods、computed、watch 等)无需任何修改 |
| 兼容但警告 | this.$set、filters、$listeners、$children等仍可运行,但控制台会输出[Vue compat]警告 |
| 不兼容 | 极少数 API 在 compat 模式下也无法使用(如Vue.extend的部分用法) |
2.4 兼容模式的三种配置
在vue.config.js中可以配置兼容模式的行为:
// vue.config.jsmodule.exports={chainWebpack:(config)=>{config.resolve.alias.set('vue','@vue/compat');// 通过 DefinePlugin 控制兼容行为config.plugin('define').tap((args)=>{args[0]['__VUE_OPTIONS_API__']=JSON.stringify(true);// 启用 Options APIargs[0]['__VUE_PROD_DEVTOOLS__']=JSON.stringify(false);// 生产环境关闭 devtoolsreturnargs;});},};| 编译标志 | 默认值 | 说明 |
|---|---|---|
__VUE_OPTIONS_API__ | true | 启用 Options API 支持 |
__VUE_PROD_DEVTOOLS__ | false | 生产环境 devtools |
__COMPAT__ | true(compat 构建) | 启用兼容模式 |
3. 详细操作步骤
步骤一:环境与依赖准备
预计时间:1-2 天
1.1 升级 Node.js
# Vue3 要求 Node.js >= 16.x,推荐 18.x LTS 或 20.x LTSnode-v# 如果使用 nvmnvminstall18nvm use18# 如果使用 fnmfnminstall18fnm use181.2 安装 Vue3 及兼容构建
# 核心依赖:Vue3 + 兼容层npminstallvue@3.4 @vue/compat# 配套升级npminstallvue-router@4 vuex@4# 如果之前使用了 @vue/composition-api 插件,可以移除npmuninstall @vue/composition-api1.3 配置 Webpack 别名
在vue.config.js中将vue指向兼容构建:
// vue.config.jsmodule.exports={chainWebpack:(config)=>{// ⚠️ 关键配置:让所有 import Vue from 'vue' 实际加载 @vue/compatconfig.resolve.alias.set('vue','@vue/compat');},};1.4 验证项目能否启动
npmrun serve# 或npmrun dev预期结果:项目应该能正常启动。控制台会出现大量
[Vue compat]开头的黄色警告,这是正常的,说明兼容层正在工作。
步骤二:入口文件改造
预计时间:半天
这是必须修改的地方,因为 Vue3 不再使用new Vue()构造函数。
2.1 完整对比
// ═══════════════════════════════════════════// 改造前:Vue2 入口文件 (src/main.js)// ═══════════════════════════════════════════importVuefrom'vue';importAppfrom'./App.vue';importrouterfrom'./router';importstorefrom'./store';importElementUIfrom'element-ui';import'element-ui/lib/theme-chalk/index.css';importaxiosfrom'axios';import*asfiltersfrom'./utils/filters';// 全局注册Vue.use(ElementUI);Vue.prototype.$http=axios;// 全局过滤器Object.keys(filters).forEach(key=>{Vue.filter(key,filters[key]);});// 全局混入Vue.mixin({methods:{formatDate(date){returnnewDate(date).toLocaleDateString();}}});// 启动应用newVue({router,store,render:(h)=>h(App),}).$mount('#app');// ═══════════════════════════════════════════// 改造后:Vue3 兼容模式入口文件 (src/main.js)// ═══════════════════════════════════════════import{createApp}from'vue';// ← 变化1:从 vue 导入 createAppimportAppfrom'./App.vue';importrouterfrom'./router';importstorefrom'./store';importElementUIfrom'element-ui';import'element-ui/lib/theme-chalk/index.css';importaxiosfrom'axios';import*asfiltersfrom'./utils/filters';// 创建应用实例constapp=createApp(App);// ← 变化2:createApp 替代 new Vue// 全局注册插件app.use(ElementUI);// ← 变化3:app.use 替代 Vue.use// 全局属性app.config.globalProperties.$http=axios;// ← 变化4:globalProperties 替代 Vue.prototype// 全局过滤器(Vue3 已移除 filters,改用全局属性)Object.keys(filters).forEach(key=>{app.config.globalProperties[`$${key}`]=filters[key];});// 全局混入app.mixin({// ← 变化5:app.mixin 替代 Vue.mixinmethods:{formatDate(date){returnnewDate(date).toLocaleDateString();}}});// 挂载应用app.use(router);app.use(store);app.mount('#app');