你是否曾在 React 或 Vue 组件中反复调用 clsx 拼接条件类名,再套一层 tailwind-merge 解决 px-4 和 px-8 的冲突?这种“双层封装”虽已成标配,却悄悄拖慢了渲染性能——尤其在高频更新组件(如表格行、导航菜单、表单控件)时,类名计算竟成瓶颈。而 cn 正是为此而生:它不是又一个语法糖工具,而是一个从零重写的高性能 Tailwind 类名引擎,完全兼容现有 API,却将关键路径性能拉升至原方案的 30 倍,且无需任何配置、不绑定框架、不依赖构建步骤。
核心功能
- 一键替代 clsx + tailwind-merge 双组合:解决开发者长期忍受的“写两行代码干一件事”的冗余问题——现在只需
import { cn } from "cn",即可同时完成条件拼接(如isActive && "bg-blue-500")和冲突消解(如自动丢弃前序text-gray-500、保留后置text-white),API 零迁移成本。 - 毫秒级首屏冷启动优化:针对 SSR 或边缘函数等对初始化延迟敏感的场景,
cn首次调用仅需 0.4ms(对比clsx+twMerge的 3.2ms),大幅降低页面可交互时间(TTI),对 Next.js App Router、Astro SSR 等架构尤为关键。 - 智能缓存命中率高达 99%:通过识别重复调用模式(如
cn("base", variant, condition && "active")这一最常见组件签名),自动跳过解析与合并逻辑;实测缓存命中场景下耗时仅 7ns,比原方案快近 2 倍,让高频重渲染组件(如虚拟滚动列表)真正“无感”。 - 跨运行时全栈支持:不仅能在浏览器中运行,更原生支持 Node.js、Bun、Deno 及 Vercel/Cloudflare 等边缘环境,让你在服务端生成 HTML、SSG 静态站点或 Edge Function 中无缝使用,彻底摆脱“只在客户端可用”的限制。
- 零依赖极简包体:整个库仅 26KB minified(gzip 后约 8KB),比
clsx+tailwind-merge组合包小 40%,且无任何外部依赖,杜绝因间接依赖引发的 tree-shaking 失败或版本冲突。 - 主题感知的类名扩展能力:通过
cn/config支持自定义 Tailwind 扩展类(如bg-brand-500)、覆盖规则(如强制sr-only优先级)及前缀隔离(适配多主题微前端),无需修改业务代码即可适配企业级设计系统。 - 全自动迁移工具链支持:官方提供
npx shadcn@latest migrate cn命令,可一键扫描项目中所有lib/utils.ts文件,自动替换旧版cn封装函数,并提示如何通过打包器 alias 彻底移除clsx和tailwind-merge的残留引用。
技术亮点
- 全新编译时解析引擎:不同于
tailwind-merge的运行时正则匹配与 AST 构建,cn采用预编译的确定性状态机(DFA)处理类名字符串,在构建阶段即固化匹配逻辑,规避了动态正则的回溯开销与对象创建成本。 - 不可变输入哈希加速:对稳定参数序列(如
cn("flex", "gap-2", isActive && "items-center"))进行结构化哈希,实现跨组件实例的共享缓存,使千级列表项的类名计算复用率趋近 100%。 - 无框架抽象层设计:源码中完全不出现
React、Vue等关键词,仅依赖标准 Web API 与 TypeScript 类型系统,因此天然兼容 Svelte 的class:指令、Solid 的响应式属性、甚至纯 ESM 模板引擎(如 Marko、Nunjucks)。 - 真实世界基准验证:项目团队采集了 58 个主流开源项目(含 shadcn/ui、Radix UI、Vaul 等)中 **144,265 次真实
cn()调用**,通过隔离进程重放测试,最终得出几何平均提升 **37×**,远超实验室合成数据的 30×,证明其性能增益在生产环境真实有效。
适合哪些人用
如果你是以下任一角色,cn 将立即为你带来可量化的收益:
- Tailwind 深度使用者:正在维护大型管理后台、低代码平台或设计系统,组件库中大量使用条件类名与主题变量,亟需降低 bundle 体积与运行时开销;
- 全栈/边缘开发者:使用 Next.js App Router、Remix、Astro 或 Cloudflare Workers 构建 SSR/SSG/Edge 应用,对首屏性能与服务端 CPU 占用高度敏感;
- shadcn/ui 用户:当前项目已基于 shadcn/ui 构建,但受限于旧版
lib/utils.ts封装的性能天花板,现可通过一条命令完成平滑升级。
真实场景案例:某跨境电商后台的订单状态卡片组件每页渲染 50+ 个,原方案下 React Profiler 显示 cn 调用占总渲染耗时 12%;接入 cn 后该占比降至 0.3%,页面滚动帧率从 42fps 提升至稳定 60fps;另一家 SaaS 厂商将 Next.js 边缘函数中的类名处理迁移到 cn,Cold Start 延迟从 180ms 降至 45ms,API P95 延迟下降 31%。
快速上手
安装与集成极其简单:
npm i cn
新建项目直接导入使用:
import { cn } from "cn"
export function Badge({ variant = "default", className, ...props }) {
return (
)
}
已有 shadcn/ui 项目?运行迁移命令即可:
npx shadcn@latest migrate cn
若需手动调整,仅需两步:
① 替换 lib/utils.ts 中的封装函数为 export { cn } from "cn";
② 运行 npm rm clsx tailwind-merge 并在 vite.config.ts/next.config.js 中添加 alias(详见官方文档)。
同类对比 / 注意事项
- vs clsx:
clsx仅做字符串拼接,无冲突解决能力,必须搭配tailwind-merge使用;cn单库实现二者全部功能,且性能碾压组合方案。 - vs tailwind-merge:后者专注冲突解决但依赖
clsx输入,且运行时解析开销大;cn将二者内聚为原子操作,并通过 DFA 引擎消除重复解析。 - 注意事项:目前暂不支持动态 class 名的深度嵌套解析(如
cn(`${prefix}-btn`, { [`${prefix}-btn-primary`]: active })),建议将动态前缀提取为常量;若项目中存在大量自定义插件类(非标准 Tailwind 类),需通过cn/config显式注册以确保正确合并。
项目信息
cn is a new engine for Tailwind class merging and conflict resolution. It replaces tailwind-merge and clsx. Same APIs. Full parity. And it is 30× fast
1.0k
Stars
7
Forks
TypeScript
MIT
TypeScript|1036 Stars|MIT 开源协议|GitHub 项目地址
无论你是追求极致性能的架构师,还是希望减少一行代码的务实开发者,cn 都值得你今天就替换掉那两个早已习以为常的依赖——因为它不是“另一个选择”,而是 Tailwind 生态演进至今,最合理、最轻量、也最迅猛的必然答案。


