cn: замена tailwind-merge и clsx с заявленным 30-кратным ускорением — что нужно знать перед миграцией
Новая библиотека cn (shadcn-ui) позиционируется как drop-in замена tailwind-merge и clsx с полной паритетностью API. Репозиторий свежий (создан 31.08.2026), 1168★, 9 форков.
Что произошло
В экосистеме shadcn-ui появился новый пакет cn — движок для мерджа Tailwind-классов и разрешения конфликтов. Заявлена полная паритетность API с tailwind-merge и clsx, то есть предполагается drop-in замена без изменения кода вызовов. Заявленная разница в производительности — 30×.
Репозиторий: shadcn-ui/cn, звёзд — 1168, форков — 9, язык — TypeScript, создан 2026-08-31.
Почему это важно операторам
tailwind-merge и clsx — транзитивные зависимости огромного количества UI-компонентов на базе shadcn/ui и Tailwind. Замена движка мерджа классов затрагивает:
- рендеринг классов на клиенте и сервере (SSR/RSC);
- поведение при конфликтах утилитарных классов (например,
p-2vspx-4); - бандл-сайз и cold-start в serverless-окружениях.
Репозиторий очень молодой (меньше месяца на момент сигнала), 9 форков — сообщество ещё не успело провести аудит edge-кейсов. Заявленное «полное соответствие API» стоит проверять эмпирически, а не принимать на веру.
Риски перед внедрением
- Отсутствие production-истории. Нет данных о поведении в высоконагруженных или edge-кейсах (динамические классы, arbitrary values, важные модификаторы
!). - Нет данных о покрытии тестами в самом сигнале — нужно смотреть CI в репозитории перед пином версии.
- Скрытые различия в разрешении конфликтов — даже при «той же API» логика мерджа может давать иной итоговый набор классов в граничных случаях (важно для регрессионного тестирования UI).
Чеклист перед миграцией
# 1. Зафиксировать текущие версии перед экспериментом
npm ls tailwind-merge clsx --depth=0
# 2. Установить cn в отдельной ветке/окружении
npm install cn@latest --save-exact
# 3. Не удалять старые зависимости сразу — держать side-by-side для сравнения
Сравнительный тест на реальных наборах классов из проекта:
import { cn as cnNew } from 'cn';
import { twMerge } from 'tailwind-merge';
import clsx from 'clsx';
const cases: string[][] = [
['p-2', 'px-4'],
['bg-red-500', 'bg-blue-500'],
['text-sm', 'sm:text-lg', 'text-sm'],
// добавить реальные сочетания классов из вашей кодовой базы
];
for (const c of cases) {
const oldResult = clsx(...c) && twMerge(clsx(...c));
const newResult = cnNew(...c);
if (oldResult !== newResult) {
console.error('MISMATCH', c, { oldResult, newResult });
}
}
Запустить этот скрипт против снапшота реально используемых классов в проекте (можно извлечь grep'ом по className=) — до замены в prod-бандле.
Рекомендации
- Не заменять
tailwind-merge/clsxв критичных путях до появления минорных релизов и внешнего аудита (сейчас это pre-1.0 экосистемный риск). - Пиновать точную версию (
--save-exact), не диапазон, пока пакет нестабилен. - Добавить визуальный regression-тест (Percy/Chromatic или скриншот-diff) на ключевые компоненты перед merge в main.
- Отслеживать issues/PR в репозитории на предмет edge-кейсов с конфликтами important-модификаторов и arbitrary values — это исторически самое частое место багов у мердж-движков Tailwind-классов.
- Если проект в проде использует SSR/RSC — отдельно протестировать поведение на сервере, так как заявленное ускорение может быть привязано к рантайм-окружению, не указанному в сигнале.
Итог
Заявка на 30× ускорение и полную паритетность API привлекательна, но при возрасте репозитория менее месяца и малом числе форков — это повод для пилотного тестирования в изолированной ветке, а не для немедленной замены в проде.
Войти, чтобы оценить материал
Комментарии
Войти, чтобы оставить комментарий