2026 年 9 月 1 日,shadcn(shadcn/ui 作者)与 aidenybai(cnfast 作者)联合发布新包 cn(GitHub 仓库 shadcn-ui/cn),定位是 Tailwind 类名合并与冲突消解引擎,用来取代前端项目里最常见的 clsx + tailwind-merge 组合。官方基准给出三个关键数字:组件最典型调用从 320 纳秒降到 10 纳秒(快 30 倍);在 58 个真实开源仓库的 144,265 次调用回放中,几何均值快 37 倍;重复字符串场景快 172 倍。迁移不需要重写代码,npx shadcn@latest migrate cn 一条命令即可完成替换。

它解决什么问题

任何 Tailwind 项目都会写 cn() 这类工具函数:条件类名拼接(clsx 的活)加冲突消解(px-2 与 px-4 同时出现时保留后者,tailwind-merge 的活)。这个函数每个组件每次渲染都在跑,是前端工程中调用频率最高的代码之一,但标准实现一直由两个独立库拼凑而成。

cn 把两件事合并进一个包、统一到一个 cn() 入口:拼接沿用 clsx 的参数语义,冲突消解沿用 tailwind-merge 的规则语义。它不依赖 shadcn/ui,任何 Tailwind v4 项目都能直接使用。

快 30 倍是怎么做到的

性能来自两个机制:

  • 参数身份缓存:cn 会记住重复出现的调用序列,同一组件在渲染循环中反复调用时按参数身份直接命中缓存,跳过合并计算。这是重复字符串场景 172 倍提升的主要来源。
  • 编译期表:默认冲突规则在构建时编译成查找表,运行时只查表,不解析规则。

官方基准(pnpm bench,每个库独立进程、独立预热、取 5 次最优)分场景对比:

场景clsx + tailwind-mergecn提升
组件最典型调用(稳定类名)320 ns10 ns30×
与上次渲染相同的类名(缓存命中)14 ns7 ns1.9×
上千个重复字符串(真实仓库工作集)2.4 µs14 ns172×
冷渲染、大量任意值3.4 µs1.1 µs3.0×
SSR 风格唯一字符串2.3 µs360 ns6.4×
页面首次调用3.2 ms0.4 ms7×

除合成基准外,项目还回放了 58 个开源代码库的 144,265 次真实调用(pnpm bench:corpus),几何均值比 clsx + tailwind-merge 快 37 倍。

输出与 tailwind-merge 完全一致

官方用 356,000 组差分测试验证:对每个输入,cn 产生与 tailwind-merge 相同的输出。所有导出按原名或熟悉的名字保留:twMerge、twJoin、clsx 从 cn 导出且行为不变;extendTailwindMerge、createTwMerge、defaultConfig、fromTheme、validators、mergeConfigs 从 cn/config 导出。唯一不支持的是 experimentalParseClassName。

如何迁移

  • 新项目:npm i cn,import 后直接用,无需配置。
  • 现有 shadcn/ui 项目:运行 npx shadcn@latest migrate cn 一键迁移;或手动把 lib/utils.ts 里的 twMerge(clsx(inputs)) 换成从 cn 导入的函数,再移除 clsx 与 tailwind-merge 依赖。其他包仍在 import 这两个库时,可以把它们 alias 到 cn,让打包只带一份实现。
  • 主题定制:cn/config 的 createCn({ extend, override, prefix }) 接受与 tailwind-merge 相同结构的配置,自定义校验器(fromTheme、validators)直接可用;Tailwind v4 前缀配置(prefix 选项)同样受支持。

适用边界

  • 只支持 Tailwind v4:cn 与 tailwind-merge v3 同级,Tailwind v3 项目应留在 tailwind-merge v2,暂不迁移。
  • 动态拼接类名检测不到:用 p- 前缀加变量拼出的类名,cn 与 Tailwind 本身一样无法静态识别,需要 cn build 编译期方案或 --safelist。
  • 包体积:cn minified 后 26 KB,是同类方案中解析成本最低的;追求更小可走 cn build 编译期生成表。
  • 运行环境:零依赖、框架无关,浏览器、Node、Bun、Deno、edge 运行时都能跑,React、Vue、Svelte、Solid、Astro 与服务端模板通用;CLI 需要 Node 20 以上。

结论

cn 用参数身份缓存和编译期表把高频的类名合并压到 10 纳秒级,同时用 356,000 组差分测试保证输出与 tailwind-merge 一致——性能提升与行为兼容可以兼得。正在用 clsx + tailwind-merge 的 Tailwind v4 项目,可以把它当作零成本替换:同 API、官方迁移命令、真实仓库基准背书。Tailwind v3 用户则暂时不用动。