2026 年组件库选型复盘:为什么我选择了 Sass + UnoCSS + CSS 变量?

1 阅读4分钟

前言

在 2026 年构建一个现代组件库,样式方案的选型不再仅仅是“好不好用”的偏好选择,而是在构建性能、分发体积、开发体验与动态灵活性之间寻找最优平衡点的工程决策。

在经历了不同样式范式的实践对比后,我确立了这一套技术组合:Sass (Dart Sass)UnoCSS 与 CSS 变量。这篇文章将从工程化的视角,复盘这套方案背后的选型逻辑。


一、 预处理层:Sass (Dart Sass) 的工程化优势

尽管 Less 在很多经典项目中依然存在,但在构建现代组件库模板时,Dart Sass 是更符合当前工程标准的选型。

  • 模块系统与命名空间:  Sass 引入的 @use 和 @forward 系统解决了长期以来的全局命名空间污染问题。在组件库开发中,这种隔离性确保了变量、Mixin 的作用域是严格受控的,极大降低了与宿主项目发生样式冲突的风险。
  • 接近编程语言的逻辑抽象:  Sass 的 @each@if 以及完善的内置函数系统,在处理组件库的色彩阶梯、栅格系统或复杂的样式计算时,提供了强大的逻辑能力。相比之下,Less 在处理同类复杂逻辑(如通过递归模拟循环)时,代码往往显得臃肿且难以维护。

二、 原子化层:为什么是 UnoCSS 而非 Tailwind CSS?

原子化 CSS 的效率已无需赘述,但在“如何落地原子化”的路径选择上,UnoCSS 在组件库这种需要二次分发的场景中,展现出了比 Tailwind CSS 更高的适配度。

  • 引擎 vs 框架:极致按需:  Tailwind CSS 本质上是一个带有厚重预设的框架,而 UnoCSS 是一个原子化 CSS 引擎。组件库开发者通常不希望给用户强加一套沉重的预设规则。UnoCSS 允许通过 Preset 从零构建规范,只有在模板中被识别到的类名才会出现在产物中,实现了真正的“按需生成”。
  • 包体积与 Tree-shaking:  组件库对分发体积极其敏感。UnoCSS 采用高性能的字符串匹配机制,没有核心代码库,生成的样式极其精准,且能与 Vite 等构建工具实现深度的 Tree-shaking,确保了组件库产物的轻量化。
  • 属性化模式(Attributify):  传统的原子化方案会导致 HTML 中充斥着长达数行的 class。UnoCSS 支持属性化写法(如 <div m-2 p-1 />),这种方式将原子类与标准类名解耦,让模板结构更清晰,显著提升了源码的可读性。

三、 动态化层:CSS 变量作为底层“协议”

在 2026 年的浏览器环境下,CSS 变量(Custom Properties) 已成为样式架构中不可或缺的底层协议。

  • 运行时动态性:  不同于预编译变量在构建时固化,CSS 变量允许在不重新编译的前提下,通过 JS 或 CSS 媒体查询动态切换主题(如深色模式)。
  • 跨工具的桥梁:  CSS 变量在 Sass 的编译计算与 UnoCSS 的原子映射之间起到了桥梁作用。将设计规范(Design Tokens)统一定义为 CSS 变量,实现了样式逻辑与具体数值的解耦,方便宿主项目进行深度定制。

四、 关于 CSS-in-JS 的取舍

在调研过程中,CSS-in-JS 方案(特别是运行时方案)被排除在了核心选型之外,主要基于以下考量:

  1. 性能开销:  在浏览器运行时解析逻辑并生成样式的成本,在复杂 UI 场景下依然存在性能瓶颈。
  2. 环境适配:  随着服务端渲染(SSR)和 Server Components 的普及,运行时方案在水合(Hydration)阶段增加了额外的复杂度。
  3. 能力重叠:  当原生 CSS 变量解决了动态性,且原子化方案解决了样式隔离后,引入运行时的 JS 解析逻辑已不再是高性价比的方案。

结语

在 2026 年的样式体系中,单一的技术工具往往难以应对多维度的工程需求。在我的实践中,Sass 负责稳健的样式骨架,UnoCSS 提供高效的微调能力,而 CSS 变量 则作为底座负责运行时的动态分发。

选型只是第一步。在实际的开发中,如何让这些方案与组件模板解耦?如何让 CLI 工具既能支持灵活的插件化定制,又能保持模板的高可读性?

在下一篇文章中,我将分享我是如何借鉴 ESLint 的插件化设计,利用 Markdown 代码块与字符串切片,构建出一套极致轻量且高度解耦的组件生成系统。

下篇预告:  《解耦组件库 CLI 与模板:一种基于 Markdown 的务实插件化实践》