likes
comments
collection
share

如何才能让一套组件库兼容vue2和vue3?(基本思路)

作者站长头像
站长
· 阅读数 35

前言

距离Vue3在2020年9月18日第一次发布到现在,已经过去了将近三年时间,虽然目前许许多多的新项目都开始使用vue3作为主要开发语言,但是因为旧项目比较庞大臃肿,很多的业务中项目、模块等都非常多,贸然升级的成本和风险都较高,所以公司中的许多老项目依旧是vue2的,那么如何去用同一套标准UI的组件库来兼容vue2和vue3就成了一个需要解决的问题。因为细节和代码会比较多,这里给大家提供一下最佳学习的大致的解决思路。

当然,最简单的方案实际上还是开发两套组件库,就像是Vue组件的标杆,Element ui ⇒ Element Plus。

解读2. x 和 3.x的版本

首先其实从版本特性上来说,一共我们可以分为三种情况

  1. @vue/composition-api + Vue 2 ≈ Vue 3
  2. Vue 2.7 (因为组合式API在2.7就被支持了)
  3. Vue 3.x

兼容方案

因为再去兼容传统的vue2(非2.7版)的成本和付出和收入并不成正比,所以我们指的兼容实际上是只vue2.7与vue3兼容,而且我们的兼容方案实际上是去向着vue3靠近,利用我们自己写的兼容代码去抹平vue2.7到vue3的差异。想知道具体差异可以在迁移文档中查看。

总体方案其实差不多,基本就是安装判断所在环境具体版本,使用该版本的产物。

在开发环境的组件脚手架中(编译兼容方案)

其实总体的思路都是一样的,判断所在环境具体版本,然后使用该版本的代码。

所以,首先我们要做的是需要安装两个版本的Vue以及会用到的相关插件

npm i vue2@npm:vue@^2.7.14 vue3@npm:vue@^3.2.45

npm i @vitejs/plugin-vue@2.0.0
npm i @vitejs/plugin-vue2@2.2.0

npm i @vue/compiler-sfc-vue2@npm:@vue/compiler-sfc@^2.7.14
npm i @vue/compiler-sfc-vue3@npm:@vue/compiler-sfc@^3.2.45

npm i @vitejs/plugin-vue-jsx @vitejs/plugin-vue2-jsx

然后在vite的配置中对应需要转换和判断的部分都要进行一次vue版本判断并且去使用对应的版本,如下面的例子。

resolve: {
      extensions: ['.ts', '.tsx', '.js', '.vue', '.less', '.css'],
      alias: {
        vue: isVue3()
    ? path.resolve(
        path.dirname(require.resolve('vue3')),
        'dist/vue.runtime.esm-bundler.js'
      )
    : path.resolve(path.dirname(require.resolve('vue2')), 'vue.runtime.esm.js');,
      }
    },

在组件库代码中

运行中兼容,抹平差异

在Vue2.7和Vue3.x中的API是有一定差异的,我们之前在兼容方案中提到,所谓的兼容实际上就是去抹平 2.7 → 3.x 的差异,实际上我们抹平差异的方式是把 2.7 ⇒ 3.x 。那我们就需要去写一个适配代码去重新实现一些方法来兼容,大致方法如下。

export {
  Teleport,
  Transition,
  cloneVNode,
  Fragment,
  TransitionGroup,
  render,
  createVNode,
  createComponent,
  injectService,
	.......
};

然后根据当前环境来导出对应版本的方法即可。(vue2.7 导出适配重写后的,v3.x 可直接导出)

postinstall 来实现构建产物的切换

什么是postinstall,这玩意有什么用

postinstall 是一个 Node.js 脚本钩子,它会在使用 npm install 命令安装完依赖包之后自动执行。在一个项目的根目录下,你可以在 package.json 文件中定义 postinstall 钩子,用于执行一些在依赖包安装完成后需要执行的操作。

通常情况下,开发者会在 postinstall 钩子中执行一些构建、编译、配置等操作,以确保在安装依赖包后项目可以正确运行。

示例,在 package.json 文件中定义 postinstall 钩子:

{
  "name": "my-app",
  "version": "1.0.0",
  "scripts": {
    "start": "node index.js",
    "postinstall": "node ../script/postinstall.js"
  },
  "dependencies": {
    "express": "^4.17.1"
  }
}

在上述示例中,当你运行 npm install 安装依赖包时,postinstall 钩子会自动执行 npm run build,从而触发构建操作。

需要注意的是,由于 postinstall 钩子是在依赖包安装后执行的,因此它适用于执行与依赖包相关的构建、编译、配置等任务。如果需要在开发过程中进行调试或运行其他命令,最好使用其他钩子,如 prestartprebuild 等。

在兼容v2和v3中,postinstall的作用是什么

根据它的自动执行的特性,在我们install之后要去根据组件库被安装的所在vue环境修改所使用到的产物路径

const Vue = loadModule('vue');
const version = process.env.npm_config_vueVersion || (Vue ? Vue.version : '2.7.');

这样利用version.startsWith()函数就可以确定当前安装环境的版本号,利用版本号来切换所使用的产物的路径即可。(我们的安装包中应该是有两套产物,用于对应切换)

💡 这里就有一个优化点:我们是否可以使用两个产物包,在先判断用户的vue版本后再去拉下对应的版本包,以此来减少包体积呢?

参考文献

转载自:https://juejin.cn/post/7269792100702634025
评论
请登录