CSS-модули: включение и использование

CSS Modules в Parcel представляют собой механизм локальной области видимости классов, при котором каждый CSS-файл становится изолированным модулем, а имена классов автоматически преобразуются в уникальные идентификаторы на этапе сборки. Это устраняет конфликты стилей между компонентами и позволяет строить масштабируемую модульную архитектуру интерфейса без ручного управления неймингом.

Parcel реализует поддержку CSS Modules на уровне трансформации файлов. При обработке стилей происходит анализ имени файла и его содержимого, после чего классы преобразуются в хешированные идентификаторы.

Ключевой принцип включения функциональности:

  • файл считается модулем, если его имя соответствует шаблону *.module.css
  • отдельная конфигурация в большинстве случаев не требуется
  • экспорт классов происходит автоматически в виде JavaScript-объекта

Пример структуры:

Button.module.css
Button.js

Подключение CSS Modules

При импорте CSS-модуля Parcel преобразует стили в объект, где ключи соответствуют исходным именам классов, а значения — сгенерированным уникальным классам.

CSS-файл

.button {
  padding: 12px 16px;
  border-radius: 6px;
  background-color: #2d6cdf;
  color: white;
}

.primary {
  background-color: #1f4db8;
}

JavaScript-файл

import styles from './Button.module.css';

export function Button() {
  return `<button class="${styles.button} ${styles.primary}">OK</button>`;
}

В результате styles.button и styles.primary становятся строками с уникальными именами классов, например:

Button_button__3Xk9a
Button_primary__1QaZp

Локальная область видимости

Основное свойство CSS Modules — автоматическая инкапсуляция стилей. Классы внутри модуля не попадают в глобальное пространство имён.

Поведение по умолчанию:

  • каждый класс считается локальным
  • пересечение имён между файлами не вызывает конфликтов
  • итоговые идентификаторы генерируются на основе имени файла и хеша

Это позволяет использовать одинаковые имена классов в разных компонентах:

Header.module.css
Footer.module.css

оба могут содержать .title, но на выходе будут разные классы.

Использование нескольких классов

CSS Modules позволяют комбинировать классы через обычные операции JavaScript.

import styles from './Card.module.css';

const className = `${styles.card} ${styles.shadow}`;

Также применяется массивная композиция:

const className = [styles.card, styles.active, styles.shadow]
  .filter(Boolean)
  .join(' ');

Глобальные стили внутри модулей

Parcel поддерживает явное отключение локальной области видимости через директиву :global.

:global(.reset) {
  margin: 0;
  padding: 0;
}

.container {
  max-width: 1200px;
}

Особенности:

  • .container остаётся локальным классом
  • .reset становится глобальным CSS-классом
  • глобальные стили применяются вне системы модулей

Также возможна инверсия:

:local(.button) {
  padding: 10px;
}

Хотя чаще используется неявный локальный режим без :local, так как он включён по умолчанию.

Композиция классов (composes)

CSS Modules поддерживают механизм наследования стилей через директиву composes, позволяющий строить композиции без дублирования CSS-кода.

.base {
  padding: 10px;
  border-radius: 4px;
}

.primary {
  composes: base;
  background-color: blue;
}

.danger {
  composes: base;
  background-color: red;
}

Поведение:

  • .primary включает стили .base
  • итоговый класс объединяет оба набора правил
  • исключается необходимость повторного описания общих свойств

В Parcel композиция обрабатывается на этапе сборки, и результатом становится единый набор CSS-правил.

Импорт нескольких классов из одного модуля

CSS Modules экспортируют все классы как свойства объекта:

.wrapper {}
.header {}
.body {}
.footer {}
import styles from './Layout.module.css';

styles.wrapper;
styles.header;
styles.body;
styles.footer;

Каждое свойство соответствует конкретному селектору из CSS-файла.

Поддержка динамических классов

CSS Modules хорошо сочетаются с условной логикой:

import styles from './Alert.module.css';

function Alert({ type }) {
  const className =
    type === 'error'
      ? styles.error
      : styles.success;

  return `<div class="${styles.alert} ${className}"></div>`;
}

Также возможна более сложная комбинация:

const className = [
  styles.alert,
  isVisible && styles.visible,
  isDisabled && styles.disabled
]
  .filter(Boolean)
  .join(' ');

Работа с несколькими CSS-модулями

В Parcel допускается импорт нескольких модулей в одном компоненте:

import layout from './Layout.module.css';
import theme from './Theme.module.css';

const className = `${layout.container} ${theme.dark}`;

Каждый модуль изолирован, но может использоваться совместно в DOM-структуре.

Интеграция с препроцессорами

CSS Modules в Parcel поддерживаются не только для CSS, но и для препроцессоров:

  • *.module.scss
  • *.module.sass
  • *.module.less

Пример:

.button {
  padding: 10px;

  &:hover {
    opacity: 0.8;
  }
}

Импорт остаётся идентичным:

import styles from './Button.module.scss';

Parcel автоматически применяет соответствующий трансформер.

Типизация CSS Modules

При использовании TypeScript возможно подключение типизации классов через декларации модулей.

Пример файла:

Button.module.css.d.ts
declare const styles: {
  button: string;
  primary: string;
};

export default styles;

Это позволяет:

  • получать автодополнение в редакторе
  • предотвращать обращения к несуществующим классам
  • улучшать контроль над стилями на этапе компиляции

Переиспользование и архитектурные паттерны

CSS Modules часто применяются в компонентной архитектуре:

  • каждый UI-компонент имеет собственный .module.css
  • стили локализованы внутри компонента
  • отсутствует зависимость от глобального CSS

Типичная структура:

components/
  Button/
    Button.js
    Button.module.css
  Modal/
    Modal.js
    Modal.module.css

Такой подход обеспечивает предсказуемость каскада и снижает вероятность непреднамеренного переопределения стилей.

Особенности сборки в Parcel

При обработке CSS Modules Parcel выполняет несколько шагов:

  • парсинг CSS-файла
  • анализ классов
  • генерация хешированных имён
  • экспорт JS-объекта
  • связывание с исходным модулем

Результатом становится связка CSS + JavaScript API, обеспечивающая доступ к стилям напрямую из кода приложения.

Взаимодействие с другими инструментами

CSS Modules в Parcel совместимы с:

  • PostCSS-плагинами
  • автопрефиксером
  • минификацией CSS
  • tree-shaking классов
  • HMR (Hot Module Replacement)

При изменении CSS-модуля Parcel обновляет только затронутый модуль без полной перезагрузки страницы, сохраняя состояние приложения.