CSS в микрофронтендах: почему Layers и Mixins лучше CSS-in-JS
CSS в микрофронтендах: почему Layers и Mixins лучше CSS-in-JS Микрофронтенды в монорепе — штука удобная, пока не касаешься CSS. Каждый микросервис тащит свои стили, потом они накладываются друг на друга, кто-то где-то вставляет !important, начинается хаос. Знакомо. Попробовал связку: CSS Modules + CSS Layers + PostCSS Mixins. Дает типизацию, изоляцию и контроль над каскадом. Не идеально, но жить можно. Проблема 1: порядок подключения ломает стили Решается CSS Layers. Явно задаешь приоритет через @layer. Например, слой base (общие компоненты) всегда ниже слоя components (конкретный микрофронт). Делаешь файл layers.css: @layer reset, base, components, utilities; В каждом микрофронте подключаешь: @import '@company/styles/layers.css' layer(components); @layer components { .button { background: var(--color-primary); } } Порядок гарантирован, даже если импорты разбросаны. Типичная ошибка — мешать @import в разные слои в одном файле. Используй одну точку входа для всех слоев. Проблема 2: опечатки в styles.myButton TypeScript тут не поможет — это же CSS. Выход — typed-css-modules. Генерирует .d.ts для всех .module.css. Добавляешь скрипт: "type-check": "typed-css-modules 'packages/*/src/**/*.module.css' --outDir ." Получаешь: // Button.module.css.d.ts export const button: string; IDE подсказывает имена, ошибки ловятся на CI. Practical совет: генерируй типы на pre-commit хуке, чтобы не забывать. Проблема 3: копипаста flex-center, text-truncate по всем модулям Тут помогает postcss-mixins. Заводишь общий файл: /* @company/styles/mixins.css */ @define-mixin flex-center { display: flex; align-items: center; justify-content: center; } В модуле: @import '@company/styles/mixins.css'; .card-header { @mixin flex-center; gap: 0.5rem; } Кода меньше на 30-40%. И стили синхронизированы по всему монорепу. Важно: в продакшене убедись, что postcss-import обрабатывается до postcss-mixins, иначе миксины не раскроются. Архитектура в Nx/Turborepo: - packages/shared/styles — базовые слои + миксины - packages/shared/ui-kit — компоненты с typed-css-modules - apps/mfe-* — каждый микрофронт подключает общие стили, но со своими слоями Ключевые trade-offs: меньше рантайма, чем CSS-in-JS, безопаснее голого CSS. Надежность растет за счет типизации и изоляции каскада. Поддержка масштабируется на сотни компонентов. Ссылки по теме: CSS Layers спецификация typed-css-modules postcss-mixins Вывод: Явное управление каскадом через CSS Layers, типизация через typed-css-modules и переиспользование через PostCSS Mixins превращают CSS Modules из опасного зверя в предсказуемый инструмент для микрофронтендов в монорепе.