12k
All articles

当你不需要组件库的时候

为何在2026年,实用类CSS和headless primitives常比完整组件库更合适,并附何时使用的判断清单。

OpenReplay Team
OpenReplay Team
当你不需要组件库的时候

在2026年,对于大多数小型项目、高度品牌化项目或对性能敏感的项目而言,你并不需要一个组件库——你需要的是用于布局的 utility CSS,以及针对三四种真正复杂的交互行为所使用的 headless 原语。像 MUI、Ant Design 或 Chakra 这样的完整样式库,只有在特定条件下才物有所值:跨多个团队保持一致性、内部工具场景下交付速度优先于品牌表现,或者团队缺乏专职设计资源。除此之外,引入完整组件库所带来的包体积负担、定制摩擦以及视觉同质化问题,通常会超过其带来的收益。本文将为你提供一套决策框架——包括默认使用组件库的真实代价、真正不需要组件库的场景、确实需要的场景,以及一个从”零依赖”到”完整组件库”的具体选择阶梯,帮助你选择能解决实际问题的最低层级。

有一个关键的认知前提需要先说清楚:“不使用组件库”从来不意味着”自己手写下拉菜单”。它的意思是:用 utility CSS 处理样式,用经过实战验证的 headless 原语处理那些难以正确实现的交互行为。

核心要点

  • 对于大多数项目,现代默认方案是 utility CSS 用于样式 + headless 原语——而不是完整的样式组件库,也不是手写交互组件。
  • 只有当你需要跨多个团队保持一致性、交付内部工具时速度优先于品牌,或者没有专职设计资源时,才考虑引入完整的样式库。
  • Reach UI 目前已停止维护,因此任何在2026年仍建议使用它的文章都是错误的——可访问性原语的角色现在由 Radix Primitives 和 Adobe 的 React Aria 承担。
  • 手写下拉菜单最昂贵的部分不是标记结构,而是键盘导航、焦点捕获、点击外部关闭以及屏幕阅读器通知——而这些正是 headless 原语默认提供的能力。
  • Tailwind CSS v4.0 是该 utility-first CSS 框架的重大版本,于2025年1月22日发布,使 utility-first CSS 成为样式层的现实默认选择。

默认使用组件库的真实代价

完整的组件库会带来三类代价,并在项目生命周期内持续叠加:包体积、定制摩擦和视觉同质化。单独来看,每一项都不是决定性因素,但合在一起,就能解释为什么在营销网站或五个页面的小应用中引入 MUI 通常是一笔亏本的买卖。

包体积。 单体样式库会附带一个基础的 CSS 和 JavaScript 负载——主题运行时、组件注册表、设计 token——无论你渲染三个组件还是三十个,这些都会随之下载。Tree-shaking 有所帮助,但前提是库本身真正实现了模块化。按组件拆包的库 tree-shaking 效果良好;radix-ui 包支持 tree-shaking,因此你只会打包实际使用的组件。而单体主题和样式负载则无法以同样的方式减重,因为运行时是每个组件都依赖的共享依赖项。关于”tree-shaking 能解决问题”这一说法,更诚实的表述是:它对模块化原语有效,对那些样式引擎是单一运行时的库则不然。

定制摩擦。 如果项目的设计风格通用且生命周期短,现成的库完全胜任。但如果设计风格独特且需要长期维护,那么你引入的每一个样式组件都会成为一场持续整个项目生命周期的优先级战争——覆盖嵌套选择器、对抗主题默认值、包装组件以适配品牌风格。

视觉同质化。 库的默认样式在设计上是中性的。要实现独特的品牌风格,就意味着大量覆盖,这又回到了定制摩擦的问题。你的设计与库的默认风格差距越大,你就越是在与库对抗,而不是在使用它。

什么时候不需要组件库

当 UI 以静态内容为主、设计风格独特,或性能是硬性约束时,你不需要组件库。这类项目引入组件库只会带来纯粹的开销。

  • 落地页、博客和作品集网站。 主要是排版、布局和少量交互效果。Utility CSS 足以覆盖样式需求,通常不需要超过几个交互组件。
  • 高度品牌化的应用。 当设计本身就是产品的核心标识时,库的默认风格会成为阻力。基于 utility 类和少量自定义组件进行构建,能在不与他人的设计理念对抗的前提下实现完全掌控。
  • 对性能敏感的应用。 当每一千字节和每一毫秒的交互延迟都至关重要时,为了几个按钮而引入样式库运行时,是错误的默认选择。
  • Tailwind 技术栈团队。 如果团队已经在使用 utility 类进行样式开发,引入样式库会造成样式层的重复,并产生两套相互竞争的视觉规范。

这里有一个值得区分的概念:组件库是一套现成的 UI 元素集合,而设计系统是围绕这些元素的更宏观的原则、token 和使用规范体系。你可以需要后者而不购买前者——用 CSS 自定义属性定义一套设计 token,加上 utility 类,就能在不引入任何第三方组件的前提下实现一致性。

什么时候确实需要组件库

当规模化的交付速度和一致性比品牌独特性或包体积更重要时,才考虑引入完整的样式库。以下四种情况可以合理使用:

  • 内部工具和管理后台。 没有人会以视觉标识来评判一个后台 CRUD 面板。一个开箱即用地提供表格、表单、弹窗和日期选择器的库,是最快的交付路径。
  • MVP 和原型验证。 当目标是在投入设计资源之前验证一个想法时,现成的组件能让你快速推进,且易于抛弃。
  • 多团队企业级一致性。 当多个团队向同一产品交付功能时,共享组件库能强制统一视觉风格和更新路径——修复一个组件,所有使用方都能继承更新。
  • 没有专职设计资源。 如果团队没有设计师,也没有设计系统,库的合理默认值通常优于大多数团队临时拼凑出来的结果。

这些场景的共同点在于:库的强主观性默认值是一种特性,而不是你需要对抗的约束。

决策阶梯:从零到完整组件库

与其在”用库”和”不用库”之间二选一,不如把它想象成一段阶梯。每上一级都会增加能力和成本;只需爬到你实际需求所要求的高度即可。这是对经典”自建 vs. 购买”谱系的现代化诠释。

层级选择方案适用场景
1. 无额外依赖原生 HTML + CSS,少量可复用组件静态或近静态 UI,完全掌控设计
2. Utility CSSTailwind CSS v4 + 设计 token希望在不脱离 CSS 的前提下提升样式开发效率
3. Headless 原语Radix、React Aria、Headless UI、Ark UI需要可访问的下拉菜单、对话框、组合框
4. 单一用途组件react-select、日期选择器、富文本编辑器某一个确实复杂的组件,而非整套 UI 工具包
5. 完整样式库MUI、Ant Design、Chakra UI内部工具、企业级一致性、无设计师

第2级——Utility CSS。 Tailwind 是样式与布局层的现实默认选择。Tailwind CSS v4.0 是该框架的全新版本,专为性能和灵活性而优化,并带来了全新的配置与定制体验。最重要的架构变化是:Tailwind CSS v4 是一个处理 CSS 的一体化工具,Lightning CSS 直接集成到框架内部,无需额外配置 CSS 处理管线。配置从 tailwind.config.js 迁移到了通过 @theme 指令在 CSS 中定义。补丁版本迭代较快,建议在项目中锁定版本而不是依赖记忆;截至2026年6月,v4 是当前版本。

第3级——Headless 原语。 这是旧版”不用组件库”建议中最容易被低估的一级,也是最关键的一级。Headless 原语为你提供交互组件的可访问行为——键盘处理、焦点管理、ARIA 连接——而不附带任何样式,让你自行引入 utility 类。

Radix Primitives 是首选方案:这是一个专注于可访问性、定制化和开发者体验的底层 UI 组件库,是一个用于构建高质量、可访问的设计系统和 Web 应用的开源 UI 组件库,由 WorkOS 维护。它为对话框、下拉菜单、弹出层、工具提示等常见 UI 模式提供原语,全部符合 WAI-ARIA 规范,确保屏幕阅读器支持和键盘导航。对于多框架团队,Ark UI(基于 Zag.js 状态机构建,支持 React/Vue/Solid/Svelte)能在多个框架间覆盖相同的需求。如果你使用 React,Adobe 的 React Aria 和 Tailwind Labs 的 Headless UI(支持 React 和 Vue)是同等级别的选择。

有一点需要明确指出:在2026年,请避免使用 Reach UI。Reach UI 目前已停止维护。其维护者在2022年宣布”OSS 破产”,此后该项目便不再活跃开发。自 Reach UI 推出以来,已有其他团队构建了底层、可组合且可访问的组件库,目前有多个维护良好的替代方案可供选择——其中以 Radix 和 React Aria 为首。任何仍在推荐 Reach UI 处理”复杂交互”的文章,都是在将你引向一个已被废弃的依赖项。

第4级——单一用途组件。 当某个组件确实复杂——可搜索的多选框、日期范围选择器、富文本编辑器——时,应该为这一个组件引入专门的、经过实战验证的包,而不是为了得到它而采购整套 UI 工具包。

同样值得注意的是,平台本身已经吸收了一些过去需要依赖库才能解决的问题。在 React 19 中,在 transition 中使用异步函数的支持,自动处理 pending 状态、错误、表单和乐观更新,新的 form actions 以及 useActionStateuseFormStatususeOptimisticuse() API,减少了一类表单场景中”你需要表单库”的理由。需要向上爬梯的理由越来越少,这本身就是一个好消息。

手写交互组件的隐性代价

“不用组件库”不能演变为”什么都自己写”,原因在于可访问性和边界情况处理。手写下拉菜单最昂贵的部分不是标记结构——而是键盘导航、焦点捕获、点击外部关闭以及屏幕阅读器通知,而这些正是 headless 原语免费提供的能力。

这正是 Radix 作者所描述的痛点:Web 平台为这些交互模式提供的原生实现是不够的——要么根本不存在,要么功能欠缺,要么无法充分定制——因此开发者被迫构建自定义组件,这是一项极其困难的任务,结果就是 Web 上大多数组件都存在可访问性缺陷、性能问题,并且缺少重要功能。

手写交互组件中的可访问性缺陷,正是那类会在生产环境的会话回放中浮现出来的 bug。观看自定义控件的回放,才能真正看清”自己写就好”的真实代价:一个键盘用户的焦点从自定义弹窗中逃逸,落在了背后的页面上;一个移动端用户反复点击一个无法关闭的下拉菜单,因为没有实现点击外部关闭或 Escape 键处理;一个组合框从未向屏幕阅读器播报其选项,用户最终放弃。这些正是 headless 原语默认处理的行为——也是手写组件在有人真正观察用户与之交互之前,会悄无声息地出错的地方。

结论不是”永远使用原语”,而是:自己实现交互组件的代价是延迟支付的,以可访问性 bug 和用户放弃操作的形式出现,而不是在写标记时预先支付。在决定手写之前,请将这笔账算进去。

决策检查清单

在选择层级之前,用以下五个问题对项目进行评估:

  1. 生命周期。 是一次性原型还是多年期产品?短期项目倾向于现成方案;长期项目倾向于自主掌控样式层。
  2. 品牌独特性。 是通用模板风格,还是具有鲜明标识的设计?独特的设计会使样式库成为负担。
  3. 团队规模。 是单一团队,还是多个团队向同一产品交付?多团队一致性是使用共享库最有力的理由。
  4. 性能预算。 包体积或交互延迟是否是硬性约束?如果是,优先选择 utility CSS 加按需引入的原语,而不是单体运行时。
  5. 维护主体。 你有设计师,并且有能力维护自定义层吗?没有设计资源会推动你转向库的合理默认值。

如果大多数答案指向”短期、通用、多团队、无设计师”,就爬到第5级。如果指向”长期、独特、单团队、性能预算紧张”,就停在第2级和第3级。

结语

2026年前端新项目的默认方案是:用 utility CSS 处理样式,用 headless 原语处理少数难以正确实现的交互——只有当规模化一致性、极致交付速度或缺乏设计资源使其强主观性默认值成为优势时,才考虑升级到完整的样式库。在出于习惯执行 npm install 安装 UI 工具包之前,先走一遍五问检查清单,选择能解决当前问题的最低层级。有意识地构建,而不是凭惯性行事——让项目本身,而不是反射性的直觉,决定你究竟需要多少组件库。

常见问题

Headless 组件库和样式组件库有什么区别?

Headless 库(如 Radix Primitives、React Aria 或 Headless UI)提供交互组件的行为和可访问性——键盘导航、焦点管理、ARIA 连接——但不附带任何样式,由你自行提供 CSS 或 utility 类。样式库(如 MUI、Ant Design 或 Chakra UI)则同时提供行为、有主观性的视觉设计以及主题运行时。Headless 库以牺牲便利性换取完全的视觉控制权和更小的样式负载。

可以在同一个项目中同时使用 Tailwind CSS 和组件库吗?

可以,但通常会造成样式层的重复,并产生两套相互竞争的视觉规范。样式库附带自己的主题运行时,与 Tailwind 搭配使用意味着需要同时维护两套体系。更简洁的组合是:用 Tailwind 处理样式,加上 Radix、React Aria 或 Ark UI 等 headless 原语——这些原语不附带任何样式,天然适合与 utility 类搭配使用。

为什么 Reach UI 不再被推荐用于 React 可访问性组件?

根据其官方 GitHub 仓库,Reach UI 目前已停止维护。维护者于2022年宣布 OSS 破产,此后该项目便不再活跃开发。任何在2026年仍推荐使用 Reach UI 处理下拉菜单、工具提示或其他复杂交互模式的指南,都是在将你引向一个已被废弃的依赖项。它曾经承担的可访问性原语角色,现在由 Radix Primitives 和 Adobe 的 React Aria 接替,两者均在积极维护,并提供完整的 WAI-ARIA 键盘和焦点支持。

哪个 headless 组件库同时支持 React、Vue、Solid 和 Svelte?

Ark UI 是跨框架的选择,基于 Zag.js 状态机构建,在 React、Solid、Vue 和 Svelte 之间保持功能一致性。大多数 headless 原语是框架特定的:Radix Primitives 和 Adobe 的 React Aria 面向 React,而 Tailwind Labs 的 Headless UI 支持 React 和 Vue。如果你需要在同一组织内跨多个框架共享组件逻辑,Ark UI 正是为此场景设计的——因为底层行为逻辑存在于 Zag.js 中,而不是绑定在某个单一框架上。

Digital experience platform

Truly understand users experience

See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.