探秘前端开源技术:最新趋势与热门框架

发表时间: 2024-08-09 17:40

shadcn/ui 是 2023 年在 GitHub 上星星数量增长最多的项目,总共获得了 39.5k 的 star,而且在 2023 年 1 月的时候才在 GitHub 发布,接着 2024 年 3 月已经增长到 50K star,这个增长速度非常可怕,究竟它是靠什么让大家都愿意贡献给它一颗 star 呢?


目前一些热门的 UI 库,包括 MUIAnt DesignChakra 等等,然后就找到了这个 2023 年最热门的项目。刚开始看 Shadcn UI 组件的样式时并没有觉得令人惊艳,组件也跟其他 UI 库没什么不同,那为什么它会是 2023 年 star 增长数量最多的项目呢?

在这篇文章中会详细介绍 Shadcn UI,并且会整理一些在选择 Shadcn UI 大家会遇到的问题,提供给大家做技术选型的参考。

shadcn ui 简介

首先明确:Shadcn UI 不是 组件库

Shadcn UI 与常见的 MUI、Ant Design 和 Chakra 等等的组件库不一样,它并不是一个组件库,那它是什么呢?

实际上它是汇集了各种组件的一个项目,你可以选择需要的组件,然后复制粘贴到你的项目中。而且它没有 npm 包,这意味着你不会在 package.json 中看到 Shadcn UI。

看到它的使用方式,你可能会疑惑,这个和其他的组件库没有什么不同啊?

Shadcn UI 的底层是 Radix UI

Radix UI 是一个 headless 组件库,这表示它的组件没有任何的样式,它提供了可以定制化样式的方式,让我们自定义组件的样式。

此外,Radix UI 的所有组件都符合 WAI-ARIA 的要求,如果你需要建立具有可访问性的项目,Radix UI 无疑是一个好的选择。 另外一点,是 Radix UI 的所有组件都可以单独下载,你不用在一开始就安装整包的组件库,而是安装需要的组件到你的项目中即可:

npm install @radix-ui/react-dialognpm install @radix-ui/react-dropdown-menunpm install @radix-ui/react-tooltip

如果你不需要 Shadcn UI 提供的样式,也可以自己使用 Radix UI 封装成所需的组件库。

Shadcn UI 使用 Tailwind CSS 封装 Radix UI

Tailwind CSS 无疑是近年来大家最常听到实现了原子化 CSS 的 CSS 框架,而 Shadcn UI 则是用了 Tailwind CSS 封装了 Radix UI 的组件,你从 Shadcn UI 上复制的组件都有 Tailwind CSS 的踪迹。

除了 Tailwind CSS 之外,另一个值得一提的是 class-variance-authority(cva)这个库,这个库也会在 Shadcn UI 中经常看到,它让组件有了 variant 的功能。

使用 Shadcn CLI 下载组件到你的项目

Shadcn UI 的主要功能就是让你复制组件的源代码,它提供了 CLI 跟手动复制两种方式,使用 CLI 便可以很快速地将组件新增到你的项目中:

npx shadcn-ui@latest add button

技术选型的问题

问题1:将 Shadcn UI 的组件源码下载下来,那不得需要自己维护吗?

在看到这个项目的时候,很多人都会有这个问题,如果遇到 bug 的时候怎么办?这的问题不太准确,有两点是大家需要思考的。

首先,不论是 Shadcn UI、MUI 或 Ant Design,只要修改了其组件的样式都需要我们自己维护,所以维护这个问题是必然的,除非你不需要定制样式。

其二,Shadcn UI 的底层是 Radix UI,组件的功能是实现在 Radix 上面,跟 Shadcn UI 没有关系,所以当发生了 bug 或是需要新功能时,则是要去看 Radix UI 是否有更新,而不是 Shadcn UI。

所以这个问题的答案是“对的,你要自己维护,但是只需要维护样式的部分”。

问题2:Shadcn UI 的项目 issue 很多怎么办?

Shadcn 作者在加入 Vercel 之后更新频率变低了,所以 issue 现在蛮多的,而且更新速度并不一定会如大家预期。

但如上个问题所述,Shadcn UI 里面只有样式,组件的功能是 Radix UI 提供的,所以当发生问题时要看的是 Radix UI 的状况,而并非 Shadcn UI。除非你需要的是 Shadcn UI 的 issue 提到的某个新的功能或是样式,但届时也许也是用复制粘贴的方式去更新 codebase 中的组件。

什么时候不要使用 Shadcn UI?

我想这个是大家都想问的一个问题,可以快速总结为几点:

  • 你不想要自己维护所有的样式:

因为 Radix UI 的组件都没有样式,这意味着所有的组件样式都得自己建构跟维护,这是个双刃剑,你拥有组件样式完整的控制权,但就得花费更多心力去维护。如果你依赖了 Ant Design,而按钮只改了 border-radius,其他样式则是由 Antd 提供,不用花费很多心力去维护样式,只需要担心升级的时候会不会跑版,或是圣诞节会不会突然跑出圣诞彩蛋。

  • Radix UI 无法满足你的需求:

Radix UI 毕竟还是比较小众的组件库,其星星数只有 3.4K 而已,比起 Shadcn UI 少了 10 几倍,如果遇到 bug 或是需要新功能时,能得到的社区资源相当有限

  • 不想自己维护组件的文档:

如果在会持续迭代的项目中使用 Shadcn UI 还有一个明显的缺点是“文档必须随着组件持续更新”,当我们使用较完整的组件库像是 Ant Design、MUI 等等,其组件的用法更新时会有官方负责维护文档,但我们使用 Shadcn UI 代表着多了一个可能会需要持续更新组件的成本。

Shadcn UI 跟 Ant Design 该怎么选

Ant Design 的优点:

  • 涵盖了非常广泛的使用者行为
  • form 系统很完善
  • 提供的组件非常多样化
  • 阿里旗下的套件,对于维护性毋庸置疑

Ant Design 的缺点:

  • 前几年发生了圣诞彩蛋事件
  • 功能多所以相对来说体积较大
  • 大版本经常会有 breaking change
  • 表格等部分组件性能不太好

Shadcn UI 的优点:

  • theme 的系统很完善,而且简单
  • 拥有高度定制化的弹性,因为你拥有了源代码
  • 较为轻量,你不用把所有的套件都安装到你的项目下
  • 符合 A11y 的规范

Shadcn UI 的缺点:

  • 未来的更新可能会比较辛苦一点,因为你拥有了所有的源代码,更新组件的同时可能需要同时维护文档
  • 组件较为简单,通常都需要自己再定制组件
  • 对于 table 等等有大量数据渲染的组件较弱
  • 对于复杂的表单,form的功能较弱

可以简单总结为,如果 Radix 提供的组件功能可以符合需求,Shadcn UI 也能符合你的需求,不需要安装较重的 Ant Design。但是相对起来 Shadcn UI 需要维护的成本有可能会高一些,因为你需要维护所有的样式及文档。

简单的应用或是不会需要持续迭代的项目也许 Shadcn UI 满足你的需求,而且使用上也很简单;而 Ant Design 的功能很完善,对于如果是需要大型 form 或是 table 的应用,还有许多额外的功能,在复杂的应用中选择 Ant Design 是个不错的选择。

其他在使用 Shadcn UI 遇到的问题

1.form 组件的结构有点怪

这是 Shadcn UI 提供的 form 代码片段,可以看到 form 使用了2次,为什么不是一个 form 呢?

export function ProfileForm() {  // ...   return (    <Form {...form}>      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">        <FormField          control={form.control}          name="username"          render={({ field }) => (            <FormItem>              <FormLabel>Username</FormLabel>              <FormControl>                <Input placeholder="shadcn" {...field} />              </FormControl>              <FormDescription>                This is your public display name.              </FormDescription>              <FormMessage />            </FormItem>          )}        />        <Button type="submit">Submit</Button>      </form>    </Form>  )}

Shadcn UI 的 Form 封装并非基于 Radix UI 的 form,而是采用了 react-hook-form 进行封装。这可能会在名称上给人造成一定的混淆。

2. 在 Shadcn UI 中,DatePicker 并非由 Radix UI 提供

因为Radix UI 并没有 DatePicker组件,所以使用了 React DayPicker 组件。然而,该组件功能相对较少,不具备选择月份或年份的功能。

在 ReactDayPicker 的官方 GitHub 中,MonthPicker 功能已超出其范畴,若有此需求,可能需要自行制作。其想法较为简单,通过年份导航,“面板”将显示月份。另外,React DayPicker 依赖的是 date-fns,如果想要使用 dayjs,则需要考虑其他套件。

Shadcn Vue

社区针对 Vue(3),也退出了对于的 vue 版本的 Shadcn,目前在 vite 下也能很好的使用。

Unocss

如果你想使用 Unocss 代替 Tailwindcss,借助 unocss-preset-shadcn插件,也能很好的使用。

uno.config.ts:

import { presetShadcn } from 'unocss-preset-shadcn'export default defineConfig({  presets: [    presetShadcn({      color: 'neutral',      radius: 0.5    }),  ])}

components.json:

{  "$schema": "https://shadcn-vue.com/schema.json",  "style": "default",  "typescript": true,  "tsConfigPath": ".nuxt/tsconfig.json",  "tailwind": {    "config": "tailwind.config.js",    "css": "assets/styles/index.css",    "baseColor": "neutral",    "cssVariables": true  },  "framework": "vite",  "aliases": {    "components": "~/components",    "utils": "~/lib/utils",    "ui": "~/components/ui"  }}

你也可以在 nuxt 中使用,更多内容请查看: https://nuxt.com/modules/shadcn

总结

看完这篇文章你应该可以了解 Shadcn UI 的有哪些特性,我们知道 Shadcn UI 跟许多的 UI 库不一样,它是通过源码的方式来使用,未来要修改样式都是由你自己决定,也这意味着你需要花更多精力去维护。

我们也知道了一些常见在技术选型中的问题,说到底 Shadcn UI 是 headless UI + Tailwind 的组合,在市面上还是有许多headless UI 的选择的,如果你要打造自己的组件库,可以选择一套headless UI 并且自己定制化。