前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >三年项目升级Vue3的踩坑经历

三年项目升级Vue3的踩坑经历

作者头像
乐圣
发布2022-11-19 17:50:07
2.6K0
发布2022-11-19 17:50:07
举报
文章被收录于专栏:随心分享

背景

我们组三年前开发了一套NoCode平台命名为米鹿平台,旨在提升运营生产力,目前这个系统的用户数一直维持在一个相对较高的水准,并且有越来越多的新用户加入,所以对该平台开放的能力要求就变高了许多。经过多次会议后,我们要将这个平台改造一下,可以接受外部组件,任何业务方的开发人员都可以给我们平台提供自定义组件,这样可以进一步提升开发和运营效率,充分发挥这个平台的作用。由于即将接入我们平台的多个业务方已经拥抱Vue3,所以我们决定将米鹿平台升级到Vue3。

项目介绍

米鹿是一个拖拽搭建H5的工具,项目的生产端前端使用的vue-cli搭建而成,拖拽过程中的状态都存储在Vuex中,通过Vuex实现了了一套状态机模型,路由使用的是Vue-router,UI框架使用的element-ui,除此之外,还引入了很多基于vue2开发的的第三方组件。

升级步骤

新建一个仓库

米鹿系统已经维护了三年多,内置组件上百个,直接在原项目升级风险较高,所以一定要新建一个仓库,将原仓库中的功能逐渐迁移过来。

使用最新版本的Vue-cli生成新项目

这里大家可能会有疑问,为什么还是使用Vue-cli而不用Vite。因为我们的项目基于原有的vue-cli做了很多webpack配置,而且在打包时依赖vue-cli打包lib的功能,相对于vue-cli升级,直接替换为vite成本较高。

在这里直接使用vue-cli生成一个vue3项目,然后迁移老项目的一些工程化配置(eslint,gitHooks等)即可。

分析原项目的package.json,逐渐迁移依赖

首先我们要分析一下老项目中的打包依赖,比如babel,webapck相关的loader等,因为vue-cli升级后对应的webpack版本已经升级是5.x,一些想对应的loader也需要升级,不兼容的配置也需要处理一下,保证项目能够跑起来。

升级开发环境依赖(devDependencies)和项目配置

1.迁移并升级开发环境依赖。

2.根据VUE-CLI升级文档修改vue.config.js配置,在这一步,我们主要是移除了一些不兼容webpack5的配置,例如devServer中的watchOptions和disableHostCheck,其中disableHostCheck: true要替换成allowedHosts: 'all',还有其他不兼容的配置这里就不一一列举,大家去官网查看相关文档即可。

注意vue-cli中文文档已经好久不更新,需要查看英文文档进行升级

3.安装@vue/compiler-sfc,替换vue-template-compiler

4.注释掉业务逻辑入口(后续逐渐打开),首先保证项目能跑起来。

修改Vue3不兼容的语法

根据文档非兼容性变更修改即可,这里给大家列举一下此次升级遇到的一些常见的变更。

1.应用入口修改,Vue不能再通过import全局引入,Vue3全局API已经支持Treeshaking,且不再支持全局引入vue的方式,改动如下:

代码语言:javascript
复制
import App from './App';
import router from './router';
import store from './store';
// 不再支持
// import Vue from 'vue';
// Vue3 导入方式
import { createApp } from 'vue';

// 不再支持
// new Vue({
//  路由和vuex的挂载方式也改变了
//  router,
//  store,
//  render: h => h(App),
//}).$mount('#app');

// 全局变量的挂载方式发生变化,不再支持
// Vue.prototype.$axios = httpClient;
// Vue.prototype.$isEditor = true;
// Vue.use(...)
// Vue.directive(...)

// VUE3
const app = createApp();
app.config.globalProperties.$axios = httpClient;
app.config.globalProperties.$isEditor = true;

// 挂载路由和vuex(vuex和vue-router也需要升级)
app.use(router);
app.use(store);
app.directive(...)

2.全局变量的修改,vue2我们可以通过this.nextTick或者this.createElement等全局api,Vue3需要单独引入使用。

代码语言:javascript
复制
import { nextTick, h } from 'vue';

// nextTick(...)
// h(...)

3.slot插槽变更,3.x版本统一了普通插槽和作用域插槽。 。

  • 在 3.x 中,将所有 this.scopedSlots 替换为 this.slots。
  • 将所有 this.slots.defalut 替换为 this.slots.defalut()。
  • 现在已经无法通过插槽获取到具体的dom对象,如果有此应用场景需要替换成ref获取的方式。

4.模板的v-for需要在模板上指定key,不需要在子元素中指定;模板中的子元素不再要求唯一。

代码语言:javascript
复制
<templete v-for="item in list" :key="item.key">
    <div>1</div>
    <div>2</div>
</templete>

5.v-bind:param.sync替换成v-model:param。Vue3移除了v-bind.sync的语法,由v-model替换

6.组件生命周期变化

代码语言:javascript
复制
// destroyed() {}
unmounted() {}

// beforeDestroy() {}
beforeUnmount() {}

7.移除了部分api。比如set和destroy等方法。vue2中不能监听对象属性的增加和删除,必须使用set或者Vue.set来变更对象或者数组,Vue3中直接用原生语法改变对象数组即可,不需要再使用set。

升级开发依赖(dependencies)

分析开发依赖,前面已经介绍过,此项目使用的是Vue全家桶+element-ui,所以vue全家桶和element-ui都需要升级,除此以外项目中有很多第三方组件都是基于vue2开发的,我们先找出这些组件标记出来,对应的代码入口先注释掉,后续一一替换成vue3版本的组件即可。

此部分是最费时间的一部分,虽然不难但比较繁琐且容易出bug,需要谨慎测试。

1.升级Vue-router。vue-router的升级改动并不大,此次升级只改动了定义和引入路由的方式,参照官方升级文档从 Vue2 迁移 | Vue Router (vuejs.org)升级即可。

2.升级Vuex。Vuex的改动也很小,此次升级只改动了定义store和引入store的方式,其余没有任何变化。参照官方升级文档从 3.x 迁移到 4.0 | Vuex (vuejs.org)升级即可

3.升级element-ui为element-plus。此部分升级工作较为繁琐,可参考文档Element Plus 不兼容变化(中文简体) · Discussion #5657 · element-plus/element-plus · GitHub进行升级。我们项目的具体改动如下:

删除emlemt-ui,引入element-plus,并替换项目中的import语句。

如果项目是全局引入,讲Vue.use(Element)替换为app.use(Element),并且替换全局引入的样式和变量文件。

如果项目是按需引入,请参考安装 | Element Plus (element-plus.org)文档修改。

按需引入有一定的bug,比如项目中如果有v-loading等指令就会报错,this.$message()等方法也会出现问题,修改方法是全局引入ElLoadingElMessageElMessageBox,具体用法如下:

代码语言:javascript
复制
import { ElLoading, ElMessage, ElMessageBox } from 'element-plus';
import 'element-plus/theme-chalk/el-loading.css';
import 'element-plus/es/components/message/style/css';
import 'element-plus/es/components/message-box/style/css';

//...
const app = createApp(App);
app.use(ElMessage);
app.use(ElMessageBox);
app.use(ElLoading);

同时修改vue.config.js

代码语言:javascript
复制
// ...
configureWebpack: {
    plugins: [
      autoImport({
        resolvers: [elementPlusResolver({
          importStyle: 'css',
          exclude: new RegExp(/^(?!.*loading-directive).*$/),
        })],
      }),
      components({
        resolvers: [elementPlusResolver()],
      }),
    ],
},
// ...

修改各种情况下Icon的用法。element-plus已经将icon单独抽离出来,需要按需引入,所以Icon的改动量巨大,以前用<i class="el-icon-edit" />这种用法和<el-input :pre-fix="el-icon-search" />已经不起作用,都需要替换成对应的icon组件,示例如下:

代码语言:javascript
复制
<script setup lang="ts">
import { Search } from '@element-plus/icons'
</script>

<template>
  <el-button type="primary" :icon="Search">Search</el-button>
</template>

所有带有slot的组件修改,不再支持slot="header等语法,例如ElCardElDialog

代码语言:javascript
复制
<template>
    <el-card>
        <template #header>
            header
        </template>
    </el-card>
</template>

4.升级其他第三方组件。第三方组件的升级依赖其官方是否支持Vue3,如果不支持,需要寻找替代品或者自己造轮子。这里简单列举一下我们升级遇到到一些第三方组件。

vue-awesome-swiper替换为swiper/vue,新版本的swiper改为插件模式,每个模块都需要按需引入,具体改动可参照Swiper Vue.js Components (swiperjs.com)

vue-cropper升级到1.x版本,参考官网进行修改。

vue-json-editor替换为vue3-json-editor,参考官网进行修改。

vuedraggable升级到4.x版本,参考官网进行修改。

qrcode.vue升级到3.x版本,参考官网进行修改(升级后样式会发生一定变化,需要留意)。

vue-wechat-title不支持vue3,查看其源码很简单,参考源码维护一个Vue3版本的即可。

handsontableVue3版本不支持免费使用,我们替换成了ag-grid-vue3并变更了一下代码逻辑。

5.升级团队自己维护的vue组件。团队内部维护的组件直接去相对应的代码仓库修改即可,要注意的是一定要升级一个大版本,保留vue2的版本,此次升级我们也升级了接近10个内部组件。

踩坑记录

  1. 通过以CDN的方式引入Vue3的umd版本,有些组件的语法在模板中不被编译,查找了各种文档也没有找到原因,所以我们的解决方案是不通过CDN的方式引入Vue3,因为Vue3已经支持treeShranking,打包体积已经缩小很多,没有必要再通过CDN的方式引入。
  2. Mixin混入的data中的变量变为浅拷贝,如果用到mixin,得额外注意这一点。
  3. 自己维护的组件,经过webpack打包后的组件引入项目中不能被正确编译,且样式丢失。和vue-loader和vue升级相关,具体原因还在查找,因为时间较紧,我们将组件改为通过vue-cli打包后可正常编译。

总结

此次升级大概用时14人天,主要耗时的工作还是在解决非兼容性语法和第三方组件升级,此外,测试工作是非常重要的,升级之后要进行一次全量的测试,以下是这次升级的一点总结:

  • 升级时先升级脚手架,注释业务逻辑,之后逐渐放开,有限保证项目可以运行起来。
  • 大部分API在Vue3中仍然可用,只有部分不兼容的变更,参照官方文档即可。
  • 第三方组件的升级最为繁琐,依赖第三方组件是否支持Vue3,不支持就需要自己造轮子。
  • 新语法如setup在接下来写新组件的时候再尝试使用,老组件在功能升级是可顺带修改,以保证项目代码风格统一。
  • 测试工作十分重要,升级过程中可以逐步开始测试。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 项目介绍
  • 升级步骤
    • 新建一个仓库
      • 使用最新版本的Vue-cli生成新项目
        • 分析原项目的package.json,逐渐迁移依赖
          • 升级开发环境依赖(devDependencies)和项目配置
          • 修改Vue3不兼容的语法
          • 升级开发依赖(dependencies)
      • 踩坑记录
      • 总结
      相关产品与服务
      内容分发网络 CDN
      内容分发网络(Content Delivery Network,CDN)通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免因网络拥堵、跨运营商、跨地域、跨境等因素带来的网络不稳定、访问延迟高等问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档