跟随通义灵码一步步升级vue2(ts)项目到vue3版本

简介: 本文介绍了如何将基于 TypeScript 的 Vue 2 项目升级到 Vue 3。主要内容包括:依赖升级、配置文件调整、组件代码迁移、状态管理迁移以及优化策略迁移。文章提供了详细的步骤和示例代码,帮助开发者顺利完成升级。特别推荐使用通义灵码工具来加速组件和状态的转写过程。


由于typescript飞速发展,某些vue2项目也在vue3出现之前集成了typescript开发,例如我的个人网站,当时花费了不少时间。而vue3我使用一段时间后,在2022年左右开始投入生产,但是这个个站就没怎么维护了。若是想继续,升级是无法避开,毕竟vue2也不怎么熟悉了

如果vue2项目是js编写的,升级参考:跟随通义灵码一步步升级vue2(js)项目到vue3版本,本文主要讲如何将vue2的typescript项目升级成vue3,并提供一个prompt提示词,教你如何利用通义灵码快速完成组件转写

1 依赖升级

1.1 老项目依赖 - vuex-module-decorators+vue-property-decorator

老项目使用装饰器包vue-property-decorator实现vue组件的ts支持,使用vuex-module-decorators实现vuex状态管理的支持。

"scripts": {
    "dev": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "lz-string": "~1.4.4",
    "tslib": "~2.1.0",
    "vue": "2.6.10",
    "vue-router": "~3.5.1",
    "vuex": "~3.6.2"
  },
  "devDependencies": {
    "@types/js-cookie": "3.0.6",
    "@types/lz-string": "^1.3.33",
    "@vue/cli-plugin-typescript": "~3.11.0",
    "@vue/cli-service": "~3.11.0",
    "babylonjs": "~4.1.0",
    "js-cookie": "~2.2.1",
    "sass": "~1.18.0",
    "sass-loader": "~7.1.0",
    "ts-loader": "~6.2.1",
    "typescript": "~3.7.2",
    "vue-meta": "~2.3.3",
    "vue-property-decorator": "8.5.1",
    "vue-template-compiler": "2.6.10",
    "vuex-module-decorators": "^0.11.0",
    "webpack": "4.47.0"
  },

image.gif

1.2 新项目ts依赖

"scripts": {
    "dev": "vite --port 5174",
    "build": "vue-tsc && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "babylonjs": "~4.1.0",
    "dayjs": "^1.11.11",
    "lz-string": "^1.5.0",
    "vue": "^3.3.4",
    "vue-router": "^4.2.5"
  },
  "devDependencies": {
    "@types/node": "^20.14.9",
    "@vitejs/plugin-vue": "^4.2.3",
    "@vitest/ui": "^1.6.0",
    "@vue/test-utils": "^2.4.6",
    "autoprefixer": "^10.4.19",
    "jsdom": "^24.1.0",
    "postcss": "^8.4.39",
    "sass": "^1.69.5",
    "sass-loader": "^14.2.1",
    "tailwindcss": "^3.4.4",
    "typescript": "^5.0.2",
    "vite": "^4.4.5",
    "vitest": "^1.6.0",
    "vue-tsc": "^1.8.5"
  }

image.gif

1.3 升级思路

1.3.1 vue3直接支持typescript,所以去掉了装饰器式的组件定义

1.3.2 去掉vuex依赖

实际上,因为状态比较简单,直接使用vue3的reactive定义响应式状态属性state,其它的方法从actions里面提取出来,这样改动很小,每个compute属性返回一个vue3 computed的计算属性

如果是比较复杂的项目,可以考虑前期这样,后面替换成pinia,实际上我个人是不推荐使用pinia的,除非有kpi需求等

1.3.3 修改配置

这个是必须的,主要是webpack和vite配置的升级

1.3.4 修改组件代码

这个是工作量最大的,下面会讲一些注意点

1.3.5 创建vue3项目将老代码和依赖移过去(推荐)

这是我实践且推荐的方法,注意目录结构不要变,一点点的移过去会更稳

2 webpack升级到vite的配置

比较详细的官方会有,这里只是讲一些关键点

2.1 新增vite配置文件

新增vite.config.ts,配置如下(如果是采用1.3.5的推荐方法可跳过)

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import path from "path";
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  build: {
    rollupOptions: {
      //
    },
  },
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
  server: {
    proxy: {
     
    },
  },
});

image.gif

2.2 更新外部依赖配置externals

很多时候,我们会把比较大的包或常用的包通过url引入,这时候就需要修改配置,例如vue.config.js的配置如下

const path = require('path');
module.exports = {
  chainWebpack: (config) => {
    config.externals({
      vue: 'Vue',
    });
  },
};

image.gif

vue3则需要安装依赖

yarn add vite-plugin-external -D

image.gif

vite.config.ts中需要使用插件:

import { defineConfig } from 'vite';
import createExternal from 'vite-plugin-external';
export default defineConfig({
  plugins: [vue(),
            createExternal({
              externals: {
                 vue: 'Vue'
              }
            })
 ],
});

image.gif

2.3 更新代理服务器配置

vue.config.js的配置如下:

module.exports = {
  
  devServer: {
    port: 8080,
    proxy: {
      '^/api': {
        target: 'https://api.xxx.fun',
        // ws: true,
        changeOrigin: true,
        pathRewrite: {
          '^/api': 'aaa',
        },
        onProxyReq: function (request) {
          request.setHeader('origin', 'https://www.xxx.fun');
        },
      },
    },
  },
};

image.gif

在vite.config.ts中则对应:

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
export default defineConfig({
  server: {
    proxy: {
      "^/api": {
        target: "https://api.xxx.fun",
        // ws: true,
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, "/xxx"),
        headers: {
          Origin: "https://www.xxx.fun",
        },
      },
    },
  },
});

image.gif

可以较大的变化就是头的修改和pathrewrite了,更多详细信息见:开发服务器选项 | Vite 官方中文文档

2.3 入口html文件调整

2.3.1 将index.html从public移出至更目录

2.3.2 在body最下面新增es入口

即   <script type="module" src="/src/main.ts"></script>

2.3.3 去掉以前的baseurl配置

vue2项目支持的html模板语法<%= BASE_URL %>vite下不再默认支持,去掉即可,然后修改index.html文件即可

3 常用优化策略迁移

3.1 摇树优化treeshake默认支持

由于rollup默认支持treeshake,所以可以去掉vue2的相关配置,也就是package.json中的sideEffects字段

3.2 分包优化的调整-指定分包

在vue2中分包方式和vue3没变化,都是使用import函数,但是有一点区别:

  • vue2中未命名分包会进入chunk,vue3会是一个单独的文件
  • vue2命名分包可使用下面的方式,vue3不生效需要删除注释
import(/* webpackChunkName: "aaa" */ './AAA.vue')

image.gif

  • vue3中在vite.config.ts中配置:
export default defineConfig({
  plugins: [vue({})],
  build: {
    rollupOptions: {
      output:{
        manualChunks(id) {
          if (id.includes("AAA.vue")) {
            return 'aaa'
          }
        }
      }
    },
  },
});

image.gif

3.3 小文件引入

vue2支持用require引入文件,vue3也支持使用file-loader,所以变动不大。

4 组件和状态迁移

4.1 组件代码迁移

关键步骤就是:

  • script 新增 setup
  • 去掉class和decorator
  • Prop定义使用defineProps
  • state定义使用reactive
  • compute使用computed
  • slot使用v-slot,子组件使用时用<template></template>包括实现slot的插入使用

例如一个多语言组件

<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator';
import { ClientModule } from '@/store/client';
import { parseLangText } from '@/utils/basic';
@Component({ name: 'lang' })
export default class extends Vue {
  @Prop({
    required: true
  })
  private val: any;
  protected render(h: any) {
    const lang = ClientModule.lang;
    const [txt, fl] = parseLangText(this.val, lang);
    return h(
      'span',
      { class: fl === 'en' ? 'english' : 'chinese', ...this.$props },
      txt
    );
  }
}
</script>

image.gif

可以转化为

<script lang="ts" setup>
import { computed } from "vue";
import { langModule } from "../../modules";
const mod = langModule();
const props = defineProps<{
  val: any;
}>();
const text = computed(() => {
  return mod.parseText(props.val);
});
const classList = computed(() => {
  return mod.lang === "en" ? "english" : "chinese";
});
</script>
<template>
  <span :class="classList"> {{ text }} </span>
</template>

image.gif

推荐使用通义灵码来转写,提示词:将次vue2组件,转化成 vue3 SFC + typescript + setup 组件


4.2 vuex store迁移

关键点就是:

  • 用类或者一个js对象代替store,state用reactive定义实现响应式
  • 计算属性使用computed替代
  • action/mutation都定义为一个对象方法

例如 一个简单的store

import {
  VuexModule,
  Module,
  Mutation,
  Action,
  getModule
} from 'vuex-module-decorators';
import store from '../';
import { IMedia } from '@/types/media';
import Vue from 'vue';
export interface IPlayerState {
  audioList: IMedia[];
}
@Module({ dynamic: true, store, namespaced: true, name: 'player' })
class Player extends VuexModule implements IPlayerState {
  public audioList: IMedia[] = [];
  public target: IMedia | null = null;
  public get audioPlay() {
    return this.audioList.find(ele => ele.playing);
  }
  @Mutation
  public play() {
    if (this.target) {
      Vue.set(this.target, 'playing', true);
    }
  }
  @Mutation
  public setTarget(e: IMedia | null) {
    if (this.target && e && this.target.src === e.src) {
      return;
    }
    if (e !== null) {
      e.playing = false;
    }
    this.target = e;
  }
  @Mutation
  public stop() {
    if (this.target) {
      Vue.set(this.target, 'playing', false);
    }
  }
}
export const PlayerModule = getModule(Player);

image.gif

可以转化成

import { IMedia } from "../../types";
import { reactive,computed} from "vue";
type MediaPlayerInfo = {
  audioList: IMedia[];
  target: IMedia | null;
};
export class PlayerManager {
  static initialState() {
    return {
      audioList: [],
      target: null,
    };
  }
  static build(
    stateBuilder: (s: MediaPlayerInfo) => ObjectState<MediaPlayerInfo>
  ) {
    return new PlayerManager(this.initialState());
  }
public readonly state:MediaPlayerInfo
  constructor(state: MediaPlayerInfo) {
this.state=reactive(state)
}
  audioPlaying() {
    return computed(()=>this.state["audioList"].find((ele) => ele.playing));
  }
  target() {
    return computed(()=>this.state.target);
  }
  public play() {
    const target = this.state.target;
    if (target) {
      target.playing = true;
      target.playing = true;
    }
  }
  public setTarget(e: IMedia | null) {
    const target = this.state.target;
    if (target && e && target.src === e.src) {
      return;
    }
    if (e !== null) {
      e.playing = false;
    }
    this.state.target= e;
  }
  public stop() {
    const target = this.state.target;
    if (target) {
      target.playing = false;
    }
  }
}

image.gif

推荐使用通义灵码来辅助完成,提示词:将此vue2-vuex store,转化成typescript服务,状态部分使用vue3的reactive进行管理

4.3 迁移策略

4.3.1 从页面组件或store模块作为一次任务

避免漏掉,一个个的完成

4.3.2 从最细粒度的开始迁移

也就是页面所用到的最小组件开始,这样可以避免过多的报错导致代码工具或者提示不可以

4.3.3 多commit代码

哪怕没完成,也不要在未commit的时候撤销等待,避免浪费工作量

5 版本管理

5.1 可在新分支新目录下存放全部的代码

这样的好处是merge等不会出现冲突

5.2 老版本核心依赖版本,用~而不是^

例如vue2/vue-router/vuex,锁定小版本,写固定版本最好。这样的好处就是不用担心老项目出现大的变化,vue2有些版本还是会出现breaking change的,这也是我对vue比较揪心的。例如vue2.7就让一些slot不可以了。

5.3 用好通义灵码,节省90%转写时间

如果不适应代码辅助,手动一行行的还是很累的事情,尤其是类型定义等。使用工具,绝对提速10倍,除了部分配置需要手动,以及对生成代码的微调。

相关文章
|
7天前
|
编解码 人工智能 API
通义万相2.1视频/图像模型新升级!可在阿里云百炼直接体验
通义万相2.1模型推出新特征,包括复杂人物运动的稳定展现、现实物理规律的逼真还原及中英文视频特效的绚丽呈现。通过自研的高效VAE和DiT架构,增强时空上下文建模能力,支持无限长1080P视频的高效编解码,并首次实现中文文字视频生成功能。升级后的通义万相荣登VBench榜单第一,提供电影级分镜效果、四格漫画故事速览及情侣头像创意定制等多种玩法,满足多样化的视觉创作需求。可直接在阿里云百炼平台调用API体验这些功能。
|
2月前
|
NoSQL 安全 测试技术
Redis游戏积分排行榜项目中通义灵码的应用实战
Redis游戏积分排行榜项目中通义灵码的应用实战
86 4
|
16天前
|
人工智能 自然语言处理 程序员
通义灵码2.0全新升级,AI程序员全面开放使用
通义灵码2.0来了,成为全球首个同时上线JetBrains和VSCode的AI 程序员产品!立即下载更新最新插件使用。
1509 26
|
1月前
|
人工智能 监控 算法
3D-Speaker:阿里通义开源的多模态说话人识别项目,支持说话人识别、语种识别、多模态识别、说话人重叠检测和日志记录
3D-Speaker是阿里巴巴通义实验室推出的多模态说话人识别开源项目,结合声学、语义和视觉信息,提供高精度的说话人识别和语种识别功能。项目包含工业级模型、训练和推理代码,以及大规模多设备、多距离、多方言的数据集,适用于多种应用场景。
298 18
3D-Speaker:阿里通义开源的多模态说话人识别项目,支持说话人识别、语种识别、多模态识别、说话人重叠检测和日志记录
|
12天前
|
人工智能 前端开发 IDE
通义灵码 2.0 全新升级发布会:你的 AI 程序员来了!
「飞天发布时刻」通义灵码 2.0 发布专场来啦。
|
18天前
|
编解码 人工智能 缓存
通义万相重磅升级,成功登顶VBench,百炼邀您第一时间体验
阿里云通义万相推出2.1视频生成模型,大幅提升复杂运动、物理规律遵循及艺术表现,在权威评测VBench中夺冠。新模型采用自研VAE和DiT架构,增强时空上下文建模,实现更稳定的大幅度肢体运动和多对象生成。通义万相支持中英文文字特效生成,满足广告设计、短视频等创作需求,并在阿里云百炼平台开放API调用,提供免费试用资源。
|
14天前
|
人工智能 JavaScript 前端开发
通义灵码 2.0 全新升级,阿里云正式推出繁星计划
在上午的通义灵码 2.0 发布会上,阿里云正式推出通义灵码繁星计划。通义灵码繁星计划希望为每位开发者送一个智能编码助手,为职场、校园开发者提供不同维度的产品免费使用、体系化课程学习、人才认证考试等权益,同时长期建设通义灵码MVP、校园大使体系,激活创新潜力,培养创新明星,点亮追梦之旅。
|
1月前
|
人工智能 搜索推荐 安全
数百名研发人员用通义灵码,33%新增代码由AI生成,信也科技研发模式焕新升级
目前,信也科技数百名研发人员正在使用通义灵码,周活跃用户占比70%,新增代码中有33%由通义灵码编写,整体研发效率提升了11%,真正实现了数百研发人员开发效能的全面提升。
|
1月前
|
运维 Serverless 测试技术
通义灵码 x 函数计算:构建高效开发流程,加速项目交付
本方案基于通义大模型的通义灵码,提供代码生成、补全、优化及单元测试生成等能力,提升编码效率和质量。结合云效和函数计算 FC 进行代码管理、持续集成、部署发布,加速项目交付,为开发者提供智能编码、CI/CD、部署上线体验,加快产品迭代速度。
|
2月前
|
存储 缓存 运维
通义灵码在Mongo多副本集群优化项目中使用分享
通义灵码在Mongo多副本集群优化项目中使用分享
49 3

热门文章

最新文章