Vue3 组件库设计 | 分享 Varlet UI 开源组件库的架构思路

写在前面

掘金的同学们大家好呀,我是 Vue3 移动端组件库 Varlet UI 的作者,时间过的真的很快,转眼已经来到了 2023 年的 10 月,上一次梳理和分享组件库的架构还是在两年以前 Varlet 刚刚开源的时候,承蒙社区同学们的帮助,两年过去之后 Varlet 已经有了 4000+ 的 star 数量。

在两年前作者曾写过一篇 如何从0到1开发一个开源组件库 希望能够分享和记录组件库从 0 到 1 的心得和思考,同时也希望社区对组件库有兴趣的同学们可以少走一些弯路。然而时至今日前端的生态已经有了翻天覆地的变化,Varlet 也不断的学习并且紧紧追赶,同时也有了长足的进步。本篇文章作者将以一个组件库作者的视角来分享一下目前 Varlet 组件库的架构变化和思路。

Pnpm Monorepo 拆包架构

Monorepo 的好处在于可以将项目中通用的部分单独抽离成一个包进行单独的发布和管理,并且免去了很多依赖关系的维护压力。这有利于组件库的生态建设,我们在项目初期就采用了这种架构,当时采用的是 yarn workspace + lerna 的方式。之后 pnpm 大行其道,我们快速的切换到了 pnpm,pnpm 性能更好并且更加节省磁盘空间,并且对于依赖关系有着更优秀的处理,并且有效的解决了幽灵依赖对于项目整体产生的影响。

目前的拆包结构如下...

lua 复制代码
|-- packages
  |-- varlet-cli 组件库命令行工具,管理整个组件库的生命周期
  |-- varlet-eslint-config 组件库的 eslint 规则
  |-- varlet-icons 组件库图标库打包工具
  |-- varlet-shared 共享的通用工具
  |-- varlet-touch-emulator 桌面端适配器
  |-- varlet-ui 组件库本体
  |-- varlet-ui-playground 组件库的演练场,在线编辑工具
  |-- varlet-use 组件库用到的 composition api
  |-- varlet-vite-plugins 组件库依赖的 vite 插件
  |-- varlet-vscode-extension 为了提高开发体验的 vscode 插件

Design System 设计系统

设计系统和设计资源对于组件库来说十分的重要,也是连接设计师和软件开发工程师的桥梁。没有设计系统,我们的组件将失去标准和原则,将失去一致性 ,最后的视觉效果也会大打折扣。 没有设计资源,设计师就很难配合软件开发工程师行之有效的产出软件设计稿,组件库就很难真正的落地到产品中去。

建议在有条件的情况下先完成设计稿再进行组件实现。我们起初先完成的组件功能后补的设计资源,吃了很大的亏。 在后期又单独花精力对所有组件的视觉重新进行了一次修正,费时费力,并且产生了一些破坏性变更,实在是得不偿失。

而且同学们不需要对做设计图有畏难情绪,像是 sketch figma 之类的工具很符合我们前端开发的惯性思维,非常容易上手。

组件编写风格 SFC OR TSX

我们采取了 SFC 和 TSX 互补使用的组件编写风格,主要使用 SFC,因为 Vue 的 SFC 编译器提供了许多的编译时优化,在运行时性能更好。TSX 用于弥补 SFC 的一些开发短板 (比如对于 VNode 的操作 SFC 没有 TSX 方便),各取所长。

开发环境拥抱 Vite 生态

我们的开发环境由 Webpack5 迁移到了 Vite,并且将项目所需的 Vite 插件独立成了一个包。Vite 很好很强大,既可以用做开发服务器又可以用作库编译器,对于自建组件库文档来说是不二之选。同时也很期待 Vite 之后可能出现的基于 Rust 的构建工具 Rolldown。总的来说,Vite 是一个充满可能性的技术,值得我们拥抱它。

图标库

我们采用的方案是传统的字体图标方案,这种方案使用起来十分方便,我们使用 varlet-icons 把 svg 图片集打包成字体文件和 css 以供组件库使用。

Vitest 单元测试

我们的单元测试工具从 jest 迁移到了 Vitest, jest 一个众所周知的问题就是配置文件比较多,需要单独配置编译相关的东西,这些东西实际上 Vite 早就帮助我们处理好了。Vitest 的最大优势就是和 Vite 共享配置,可以减少很多依赖和配置的维护负担。

并且 Vitest 对测试文件的执行速度也有了极大提升,在 Mac M1 上尤为明显。不过 Vitest 显然在单核 cpu 上速度就没有那么快了,CI 上的速度和 jest 可以勉强五五开。迁移到 Vitest 还是很值得的。

基于原生语言的 JS/TS 编译器

随着基于原生语言的 JS/TS 编译器大热,社区中涌现出许多的基于原生语言的编译器的上游工具可供我们替换一些旧的工具。浏览器场景的 TS 库的编译器我们选择使用 tsup 替换 Typescript 的官方编译器 tsctsup 是基于 esbuild 的,它的编译速度是 tsc 的很多倍,并且足够的开箱即用。

Node 场景 的 TS 库,我们推荐使用 unbuild,它在开发模式下提供了一个 typescript 的运行时,可以免去 watch 文件进行重复编译的性能开销,同时也支持生产环境的构建。我们最后没有采用它的原因是因为不太希望项目中的编译器太过冗杂,并且对于我们来说 Node 场景 的 TS 库也是不多的。最终选用 tsup 对除组件编译之外的所有场景的库进行编译。

我们对组件的编译是通过自研的编译器进行的,自研编译器的好处在于编译流程足够可控和直接,并且足够的轻量,编译核心也从 babel 过度到了 babel + esbuild 的混合编译方式,使用 babel 去处理 vue jsx语法, 再用 esbuild 进行编译和语法降级,极大的加快了编译速度。

编译产物

为了满足不同场景的使用需要,一般情况下我们需要以下几种产物,esmcjsumdesm 一般用于构建工具的场景,cjs 一般用于较老旧 node 版本的服务端渲染和单元测试场景、umd 一般用于浏览器 cdn 方式引入的场景。我们通过自研的组件编译器按照目录结构输出 esm 模块,按照目录结构输出对组件按需引入更加友好,再通过 Vite 的库编译模式输出 cjsumd 的捆绑文件。

文档的部署

本着能不花钱就不花钱的原则,国内首选 Gitee Pages 服务,国外首选 Vercel。部署两个站点有利于国内外用户的访问体验。Vercel 还有一个优势在于可以直接通过 github app 集成到 CI,每个 pr 或者 commit 都可以自动的部署并得到一个可访问的地址,有助于你对每个提交对应的组件效果有一个清晰的预览和了解,毕竟我们做的是组件库,视觉效果的审查是极其重要的。

演练场

每个组件库都需要一个在线的编辑工具,以便用户反馈、复现 bug 或是提出问题,我们魔改了 Vue 官方的 playground 代码,构建了一个 Varlet Playground,具体实现细节可以查看这篇文章 Vue3组件在线交互解释器,或者查看源码。 也可以使用一些成熟的服务,如 codesandbox,但是相对 playground 就没有那么轻量,在线构建也比较耗时,国内网络不好的同学访问起来也比较困难。

VSCode 插件

组件库不光需要满足用户体验,还要尽可能的满足开发者的使用体验,VSCode 插件是一个很好的入手点。 我们尝试开发了一个 VSCode 插件。功能如下

  • 🛠️ 支持全组件的语法提示、快速补全。
  • 🛠️ 支持全组件的文档地址预览、快速跳转。
  • 🛠️ 支持框选代码片段,快速打开 Playground
  • 🛠️ 支持图标组件的全图标预览。
  • 🌍 支持中英文切换。

顺道一提我们还做了一个 varlet 的 vscode 主题

插件可在 VSCode 的插件市场搜索到

感谢大家看到这里

不知道自己写的怎么样,也许能帮助到大家的地方不多,但也希望能给大家一些启发。 再次感谢社区同学们对 Varlet 组件库的支持,欢迎 issue pr star

仓库地址: github.com/varletjs/va...

相关推荐
清灵xmf几秒前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
小白学大数据7 分钟前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
qq_3901617716 分钟前
防抖函数--应用场景及示例
前端·javascript
3345543244 分钟前
element动态表头合并表格
开发语言·javascript·ecmascript
John.liu_Test1 小时前
js下载excel示例demo
前端·javascript·excel
Yaml41 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事1 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶1 小时前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json
getaxiosluo1 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
理想不理想v1 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript