一种vue2/3代码复用解决思路

前言

因为团队里同时存在vue2和vue3的项目,日常开发中经常需要在vue2下开发好,然后复制到vue3的项目里再改成对应的语法,非常麻烦且无趣。在这个背景下,我们探索了一种基于构建的代码复用方案,即:在开发时只用一种语法(最好是vue3),通过打包成两种产物提供给不同的项目消费。

解决思路

要实现上面所说的效果,我们需要解决两个问题

  1. 只用一种语法开发:我们希望可以用vue3的setup script + composition api的方式来开发。

vue2并不支持setup script,在vue2下使用这个特性,我们可以借助unplugin-vue2-script-setup来实现。

refcomputed这些API,在vue2下是从@vue/composition-api中引入,在vue3下则是直接从vue里引入。这种写法上的差异,借助vue-demi可以抹平。

  1. 搭建两条构建流水线:我们要同时在项目里安装两个版本的vue-loadervue以及对应的compiler。

安装同一个包的不同版本,我们可以使用npm/yarn alias

在打包的时候,手动注入对应的环境变量。例如在打包vue2产物时,VUE_VERSION = 2,通过process.env.VUE_VERSION来获取,这样就可以知道当前是打包哪个版本的产物从而选择对应的loader,plugin。如果不想写过多的判断逻辑也可以直接写两个配置文件,在build的时候分别指定对应文件即可

在构建工具的选择上,因为是基于vue技术栈,我们选择vite

最终实现

先新建一个空白目录

bash 复制代码
mkdir demo
cd demo
yarn init -y

安装依赖

bash 复制代码
# 安装vue的不同版本
yarn add vue2@npm:vue@2.6.14 vue3@npm:vue@3 -D

# 安装vue-demi
yarn add vue-demi -D

# 安装vite以及打包vue3/vue2需要的插件
yarn add vite @vitejs/plugin-vue@4.3.4 vite-plugin-vue2 -D

# 安装支持vue2使用setup script的插件
yarn add unplugin-vue2-script-setup -D

# 安装编译vue2需要的compiler,版本和vue版本保持一致
yarn add vue-template-compiler@2.6.14 -D

# 安装ts以及node的类型文件包
yarn add typescript @types/node@14 -D

编写vite配置,在根目录下新建vite.config.ts文件

typescript 复制代码
import { defineConfig } from 'vite'
// 编译vue2需要的插件
import { createVuePlugin as Vue2 } from 'vite-plugin-vue2'
// 支持vue2 setup script语法需要的插件
import Vue2ScriptSetup from 'unplugin-vue2-script-setup/vite'
// 编译vue3需要的插件
import Vue3 from '@vitejs/plugin-vue'

const isVue2 = process.env.VUE_VERSION === '2'
const isVue3 = process.env.VUE_VERSION === '3'

console.log(`compiler target is ${isVue2 ? 'vue2' : 'vue3'}`)

// https://vitejs.dev/config/
export default defineConfig({
  resolve: {
    alias: {
      vue: isVue2 ? 'vue2' : 'vue3',
    }
  },
  build: {
    target: 'es2015',
    outDir: isVue2 ? 'dist/vue2' : 'dist/vue3',
    lib: {
      entry: './src/build.ts',
      formats: ['es', 'cjs'],
      fileName(format, _entryName) {
        return `${format}/index.js`
      },
    },
    rollupOptions: {
      external: ['vue', '@vue/composition-api/dist/vue-composition-api.mjs'],
    }
  },
  plugins: [
    isVue2 && Vue2(),
    isVue2 && Vue2ScriptSetup({}),

    isVue3 && Vue3({
      compiler: require('vue3/compiler-sfc')
    }),
  ],
})

package.json文件里添加上对应的scripts

json 复制代码
"scripts": {
  "dev": "vue-demi-switch 3 && VUE_VERSION=3 vite",
  "build": "yarn build:vue2 && yarn build:vue3",
  "build:vue2": "vue-demi-switch 2 && VUE_VERSION=2 vite build",
  "build:vue3": "vue-demi-switch 3 && VUE_VERSION=3 vite build"
},

在终端里执行yarn build,可以看到dist目录下就生成了对应的产物了

总结

这个方案还有非常多需要完善的地方,例如生成.d.ts的类型定义文件、组件单独打包支持按需加载。而且还有一个非常致命的问题:无法使用已有的UI库,因为这类组件库通常也是针对不同的vue版本有不同的包并且组件的API也有差别,如果要使用需要一个类似vue-demi这样的胶水层来兼容。

如果大家有更好的方案请不吝赐教!

相关推荐
ITmaster07312 小时前
Vibe Coding 时代:Vue 消失了还是 React 太强?
前端·vue.js·react.js
万敏2 小时前
Vue3 全栈实战第七周:错误处理与请求层封装实战记录
vue.js·node.js·全栈
请你吃div3 小时前
Electron 从零开始的新手开发教程
vue.js·windows·electron
咏方舟【长江支流】5 小时前
【前端1】单据编辑 -EasyUI/Vue/React/Bootstrap 主流框架实现订单单据主子表显示和编辑比较,哪个你最易入门?
前端·vue.js·easyui·咏方舟-长江支流·userbaodatagrid
m0_579146655 小时前
Element UI 表格合并单元格完全指南:从原理到实战
前端·vue.js·elementui
雪芽蓝域zzs6 小时前
Prettier (代码格式化)配置详解
前端·vue.js
运维全栈笔记9 小时前
Vue + Spring Boot 前后端分离项目部署笔记(若依 RuoYi-Vue 3.9.2)
运维·服务器·vue.js·spring boot·笔记·开源·开源软件
Simon_He20 小时前
一个渲染内核,五个框架包:我的流式 Markdown 渲染库是怎么长成“全家桶”的
前端·vue.js·markdown
夏雪coding21 小时前
JeecgBoot 动态路由踩坑(Vue2):刷新白屏、permissionList[0] 报 undefined,以及我最后为什么全删了
javascript·vue.js
前进的程序员1 天前
Codex破局:前端组件秒级生成|提速React/Vue开发,可复用提示词+实战调试经验
前端·vue.js·react.js·codex