Статьи

Понимание методологии CSS модулей

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

Когда мы смотрим на CSS, я бы сказал, что последний большой сдвиг в том, как мы пишем CSS (на стороне инструментальных средств), должен был появиться CSS-процессоры, в основном Sass , возможно, самый известный. Существует также PostCSS , который имеет немного другой подход, но в основном оказывается в той же корзине — включается неподдерживаемый браузером синтаксис, пропускается поддерживаемый браузером синтаксис.

Теперь новый ребенок присоединился к блоку под названием CSS Modules . В этой статье я хотел бы познакомить вас с этой техникой, рассказать, почему у нее есть некоторые хорошие моменты, и как вы можете начать с ней работать.

Что такое модуль CSS?

Начнем с объяснения из официального репозитория:

Модуль CSS — это файл CSS, в котором все имена классов и имена анимации по умолчанию имеют локальную область видимости.

Теперь это немного сложнее, чем это. Поскольку имена классов по умолчанию имеют локальную область видимости , это включает некоторую настройку, процесс сборки и немного магии, которую иногда трудно понять.

Но, в конце концов, мы можем оценить CSS-модули за то, что они есть: способ использовать CSS для компонента и избежать глобального ада пространства имен. Больше не нужно искать хороший способ назвать ваши компоненты, потому что шаг сборки делает это за вас!

Как это работает?

Модули CSS должны быть переданы на этапе сборки, что означает, что они не работают сами по себе. Смотрите это как плагин для веб-пакета или Browserify . В основном это работает следующим образом: когда вы импортируете файл CSS внутри модуля JavaScript (например, но не обязательно, компонента React ), модули CSS будут определять имена классов объектов, сопоставляемых из файла, с динамическими именами классов в пространстве и пространстве имен, которые могут использоваться как строки в JavaScript. Позвольте мне проиллюстрировать это на примере:

Ниже приведен очень простой файл CSS. Класс .base Это просто своего рода псевдоним внутри таблицы стилей, который будет использоваться в модуле JavaScript.

 .base {
  color: deeppink;
  max-width: 42em;
  margin: 0 auto;
}

А вот как вы могли бы использовать его в фиктивном компоненте JavaScript:

 import styles from './styles.css';

element.innerHTML = `<div class="${styles.base}">
  CSS Modules are fun.
</div>`;

В конце концов, это сгенерирует что-то вроде этого (при использовании через веб-пакет с настройками по умолчанию):

 <div class="_20WEds96_Ee1ra54-24ePy">CSS Modules are fun.</div>
 ._20WEds96_Ee1ra54-24ePy {
  color: deeppink;
  max-width: 42em;
  margin: 0 auto;
}

Способ генерации имен классов может быть настроен так, чтобы они были короче или следовали определенному шаблону. В конце концов это не имеет значения (хотя более короткие имена классов означают более короткие таблицы стилей), поскольку дело в том, что они генерируются динамически, уникально и отображаются в правильных стилях.

Возможно действительные проблемы

Так вот как это работает. И теперь вы должны думать: «Что это за штука? Я даже не… Ну, держись! Я слышу тебя. Давайте решать эти проблемы один за другим, не так ли?

Это выглядит чертовски уродливо!

Это правда. Но имена классов не предназначены быть красивыми; они предназначены для применения стилей к элементам. И это именно то, что они делают, поэтому я бы сказал, что это не обоснованная проблема.

Это боль для отладки!

Как только есть шаг сборки, чтобы выполнить некоторую обработку в вашей таблице стилей, отладка становится трудной. Сасс не легче. Вот почему у нас есть исходные карты , которые вы можете настроить и для CSS-модулей.

На самом деле я бы сказал, что, несмотря на непредсказуемость имен классов, отладку не так сложно, так как стили по определению специфичны для модулей. Если вы знаете, какой модуль вы просматриваете в инструментах разработчика, вы знаете, где искать прикрепленные стили.

Это делает стили одноразовыми!

Да и нет. С одной стороны, да, но это на самом деле главное: он связывает стили с компонентом, чтобы избежать глобальной утечки стилей и конфликтов. Что хорошо, я уверен, что вы уступите.

С другой стороны, все еще возможно определить глобальные классы (с помощью :global() Эти классы могут затем использоваться в ваших компонентах JavaScript.

 :global(.clearfix::after) {
  content: '';
  clear: both;
  display: table;
}

Модули CSS также имеют возможность расширять стили из другого модуля, который в основном работает так же, как @extend Он не копирует стили, но объединяет селекторы для расширения стилей.

 .base {
  composes: appearance from '../AnoherModule/styles.css';
}

Для этого нужен веб-пакет, Browserify или [любой] инструмент!

Это аналогично тому, как Sass нужно компилировать файлы .scss Шаг сборки уже есть в любом случае.

Почему мы даже обсуждаем это?

Ну, я не совсем уверен, что в будущем CSS-модули останутся такими, какими они являются в настоящее время, но я думаю, что это разумный способ написания стилей. Наличие большой глобальной таблицы стилей не подходит для больших сайтов, отделенных от крошечных компонентов.

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

Начиная

Как сказано выше, вам понадобится либо веб-пакет, либо Browserify, чтобы включить CSS-модули.

Webpack

Начнем с версии веб-пакета. В webpack.config.js

 {
  test: /\.css$/,
  loader: 'style-loader!css-loader?modules'
}

Прямо сейчас он будет внедрять стили внутри элемента <style> Вероятно, это не то, что вам нужно, поэтому давайте сделаем из него правильную таблицу стилей благодаря плагину извлечения текста для веб-пакета :

 {
  test: /\.css$/,
  loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules')
}

Это довольно много для веб-пакета.

Browserify

Я только когда-либо использовал Browserify через командную строку, так что это немного сложнее, я думаю. Я добавил сценарий npm в мой файл package.json

 {
  "scripts": {
    "build": "browserify -p [ css-modulesify -o dist/main.css ] -o dist/index.js src/index.js"
  }
}

Это заставляет Browserify запускать src/index.jsdist/index.jsdist/main.csscss-modulesify . Если вы хотите добавить к нему Autoprefixer , вы можете выполнить команду следующим образом:

 {
  "scripts": {
    "build": "browserify -p [ css-modulesify --after autoprefixer -o dist/main.css ] -o dist/index.js src/index.js"
  }
}

Как видите, вы можете использовать опцию --after

Вывод

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

Я думаю, что идея CSS Modules — это путь. Я не говорю, что эта библиотека, в частности, является лучшим доступным решением, но она определенно имеет некоторые особенности в отношении того, как должен быть написан CSS: модульный, объемный, но все же многократно используемый.

В качестве дальнейшего чтения я рекомендую это введение в CSS Modules от Глена Мэддерна, создателя проекта.