背景
近期我在做什么?
远程组件如何引入在项目中
这个话题也就是我最近在研究的东西;
为什么?
最近有一个想法,就是在工作中有那么一个功能就是商品属性
, 类似于淘宝京东的选择商品规格的功能, 有尺寸大小,有眼色,有材质等等;
该功能涉及到多个平台,每个属性有对应的规则,但是有一个比较麻烦的点就是功能是一致的,规则是一样的,就是完全的功能要在不同的项目中复制粘贴修改;导致现在就是不同的项目中都有一样的组件一样的代码
这样就暴露出了弊端:
- 维护多个平台,比如修改了规则,那么就要修改多个项目;pc 端, h5, 小程序等等;
- 代码的重复性比较高,对于高复杂的组件没有对应的文档以及说明;
- 底层的变动以及参数不统一,A 同学加个一个参数 a, B 加了一个 b,最后都不知道该字段的具体作用
在这样的业务场景下,于是我消费一些时间去研究一下远程组件如何做?
当然远程组件的好处就是:后期维护这个组件即可;
于是,就考虑到了俩种不同的处理方式
- 包依赖模式,有一个缺点就是如果远程组件更新了,那么本地以及生产的
package.json
也要对应进行升级;不过稳定性比较高 - cdn 模式,那就是项目使用 cdn 的模式引入
import {RTx} from 'https://xxx.com/xx.js'
, 不过这样在vite
上是可以正常运行的,在webpack
上就无法使用了
思路
首先,选用构建工具:
- vite
- webpack
- rollup
在三者的比较下,我选择了vite
- vite 与 webpack 相比,不论是启动,打包还是热更新,vite 还是比较优秀的,再者,vite 还支持对 rollup 的配置
- rollup 与 webpack 相比,rollup 更加轻量,配置简单,但是不支持热更新
为什么要用到热更新,因为你在开发组件或者测试一些 api 的时候总不能每次都重启修改吧,那么热更新是不错的选择;
于是我还是采用vite
的打包方式,原因就是很简单,速度,配置等都算的是比较不错的,当然是还可以配置 rollup 配置; 完全是自定义的;
其次,组件的编写方式:
组件使用 vueComponent
的方式,之前也想过用函数组件,但是有些场景不太合适;就拿vant
来讲,其远嘛就是tsx/jsx
编写,你直接看不到vue
文件,但是对于其维护的便利性来讲我还是看中component
的形式;
接着,就要对其目录进行分级,
- packages
- ele-components => element-plus 组件的目录
- van-components => van-ui 组件的目录
- utils => 工具函数的目录
- hooks => 封装的 hooks
- types => 类型定义
- style => 样式的目录
- index.ts => 入口文件
- package.json => 组件的配置文件
- package.json
- vite.config.ts
- ...其他文件
当然对应的打包文件的格式也和packages
一样,这样就可以了
编写远程组件
其实这里的远程组件和日常编写的组件是一样的,不过是对公司的一些公共的业务组件进行拆分,从而再二次封装,后期只需要引入对应的依赖即可,这样就可以做到仅仅修改一次从而再多个平台进行更新;
具体的编写方式就不细说了;
当你写完之后,那么最后一步就是进行打包了, 这里我采取vite-lib
插件的形式进行打包:
{
build: {
lib: {
entry: '', // 插件的入口文件
name: '', // 名字
formats: ['es'] // 打包的格式
},
// rollup配置
rollupOptions: {
external: {},
output: {
}
},
cssCodeSplit: true
}
}
以依赖包的形式将进行打包,这里我用到了几个插件:
- vite-plugin-dts: 将组件的代码进行类型声明,方便使用
- autoprefixer: 添加浏览器前缀
- rollup-plugin-obfuscator: 代码混淆
打包完成之后,你会发现对应的文件会很大,那么接着对其进行优化, 首先我们下载的一些依赖不需要进行打包,如:vue, vant, element-plus
;
那么vite-rollupOptions
有这样一个配置:
{
rollupOptions: {
external: ["vue", "vant", "element-plus"];
}
}
那么重新打包,观察其文件大小,你会发现比之前的文件小了很多;
到了这一步基本上差不多了,不过要注意的是打包完成之后必须要有package.json
文件,不然后期使用install
的方式会失败的;
这是一个使用案例:
// 类似于这样的格式,具体路径自己进行配置;
// 这样做到了按需加载,用到那个组件加载对应的组件以及样式,避免组件和样式打包一起导致文件加载时间过长的情况
import "remote-components/ele/index.css";
import { ElButton } from "remote-components";
<template>
<ElButton />
</template>;