- PVSM.RU - https://www.pvsm.ru -

Модульная система Sass: руководство по @use

Ситуация

Раньше в Sass был только @import, который просто копировал содержимое одного файла в другой. Это создавало проблемы: глобальное загрязнение, конфликты имён, дубл��рование кода. Начиная с Dart Sass (современная версия), @import объявлен устаревшим и будет полностью удалён в версии 3.0.0. Вместо него введена модульная система с правилами @use.

1. @use — подключение модуля

@use загружает файл (модуль) и делает его содержимое доступным в текущем файле, но в изолированном пространстве имён. Это главное отличие от @import.

@use 'путь/файл';

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

Пример:

Файл helpers/_colors.scss:

$primary: blue;
$secondary: gray;

Подключаем в body/header.scss:

@use '../helpers/colors';

.button {
  color: colors.$primary;   // обращение через пространство имён "colors"
}

Важно: пространство имён по умолчанию берётся из названия файла.

2. Изменение пространства имён (as)

Можно задать своё имя для модуля, чтобы сократить или уточнить контекст:

@use 'helpers/colors' as myColors;

.button {
  color: myColors.$primary;   // обращение через "myColors"
}

Пространства имён в Sass — это идентификаторы, они подчиняются тем же правилам, что и имена переменных:

✅: МОЖНО:

  • буквы a–z, A–Z

  • цифры 0–9 (но не в начале)

  • camelCase (myColors)

  • PascalCase (MyColors)

❌: НЕЛЬЗЯ:

  • дефис (-)

  • пробелы

  • спецсимволы (!@#$%^&*)

  • начинаться с цифры

3. Встроенные модули (math, list, map, color, string)

Sass предоставляет встроенные модули, которые подключаются через @use с префиксом sass::

@use 'sass:math';
@use 'sass:list';
@use 'sass:map';
@use 'sass:color';
@use 'sass:string';

Примеры:

$width: math.div(100%, 3);          // деление
$len: list.length($my-list);        // длина списка
$color: color.adjust(#336699, $lightness: 20%);
$index: string.index($string, 'sub');

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

4. Использование миксинов и функций из модулей

Миксины и функции, определённые в пользовательских файлах, тоже доступны через пространство имён:

// helpers/_mixins.scss
@mixin flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}
// components/_card.scss
@use '../helpers/mixins';

.card {
  @include mixins.flex-center;
}

Если нужно импортировать несколько модулей в одном файле, делаем это явно:

@use '../helpers/colors';
@use '../helpers/variables' as var;
@use '../helpers/mixins';

5. Организация файлов

Каждый SCSS-файл сам отвечает за свои зависимости. В начале файла перечисляются все необходимые модули с помощью @use. Это обеспечивает полную прозрачность и упрощает рефакторинг.

Рекомендуемая структура папок:

scss/
  helpers/
    _colors.scss
    _variables.scss
    _mixins.scss
  components/
    _button.scss
    _card.scss
  pages/
    _about-page.scss
  template.scss

Пример components/_button.scss:

@use '../helpers/colors' as myColors;
@use '../helpers/variables';
@use '../helpers/mixins';

.button {
  background-color: myColors.$primary;
  padding: variables.$spacing-md;
  @include mixins.border-radius;
}

6. Преимущества подхода с пространством имён

  • Явность — сразу видно, из какого модуля взята переменная/миксин.

  • Отсутствие конфликтов — даже если в разных модулях есть одинаковые имена, они не пересекаются.

  • Лёгкий рефакторинг — можно менять один модуль, не боясь сломать другие.

  • Поддержка IDE — автодополнение работает лучше, так как пространства имён известны.

  • Масштабируемость — код остаётся понятным даже в больших проектах.

7. Важные замечания

  • @use работает только в начале файла (до любых правил).

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

  • Встроенные модули не нужно копировать в проект — они уже есть в Sass. Их нужно явно подключать в необходимом файле:

@use '../helpers/colors' as myColors;
@use '../helpers/variables';
@use '../helpers/mixins';
@use 'sass:list';

.button {
  background-color: myColors.$primary;
  padding: variables.$spacing-md;
  @include mixins.border-radius;
  $len: list.length($my-list);        // длина списка
}

8. @use ... with ()

@use [1] ... with () — это механизм конфигурации модулей в Sass. Он позволяет передавать значения в модуль при его импорте, переопределяя переменные, которые помечены как !default.

8.1 Как это работает:

В модуле объявляются переменные с !default

// helpers/_theme.scss

$bg-color: #ffffff !default;      // значение по умолчанию
$text-color: #333333 !default;    // можно переопределить
$spacing-unit: 8px !default;      // можно переопределить
$border-radius: 4px !default;     // можно переопределить

!default означает: «используй это значение, если никто не передал своё»:

  • Если значение НЕ БЫЛО задано до импорта — используется то, что после !default

  • Если значение УЖЕ БЫЛО задано — используется заданное, а значение после !default игнорируется

Пример, когда значение было задано ДО импорта:

// helpers/_theme.scss

$bg-color: #ffffff !default;  // будет белый, если никто не задал другой
$bg-color: #000000;  // задали чёрный ДО импорта

@use 'helpers/theme';

body {
  background: theme.$bg-color;  // будет #000000
}

8.2 При импорте передаём новые значения через with:

// pages/dark-theme.scss
@use '../helpers/theme' with (
  $bg-color: #1a1a1a,
  $text-color: #f0f0f0,
  $spacing-unit: 12px
);

body {
  background: theme.$bg-color;      // будет #1a1a1a
  color: theme.$text-color;         // будет #f0f0f0
  padding: theme.$spacing-unit;      // будет 12px
  border-radius: theme.$border-radius; // будет 4px (осталось по умолчанию)
}

Выходит, что с помощью @use [1] ... with(), мы также переопределяем переменные, только вместо "ДО импорта", мы прописываем с помощью with в скобках самого импорта.

Таким образом, у нас есть два способа переопределить переменные в конкретном файле

  1. Сделать это до конкретного импорта, а лучше вышел всех импортов в файле .scss

  2. Переопределить переменную из определенного импорта, используя with()

8.3 Примечание

  1. Многие Sass-библиотеки используют !default для настройки своих стилей. Их также можно переопределить двумя способами, указанными выше (если такое требуется).

  2. Для одного и того же модуля директива with() работает только при первом импорте. Все последующие @use [1] ... with() для этого же модуля будут проигнорированы:

// Правильно
@use 'helpers/theme' with (
  $bg-color: #000
);

// Бесполезно (повторный импорт игнорирует with)
@use 'helpers/theme' with (
  $bg-color: #f00  // НЕ СРАБОТАЕТ!
);
  1. Можно применять @use [1]... with() для каждого импорта (если требуется):

// helpers/colors

// Правильно
@use 'helpers/colors' with (
  $primary: red,
  $secondary: lightgray
);

// helpers/spacing

// Правильно
@use 'helpers/spacing' with (
  $padding: 24px,
  $margin: 12px
);

9. @forward — проброс м��дуля

@forward [2] — это директива, которая передаёт содержимое подключённых файлов дальше, но сама не даёт к ним доступ в текущем файле. Она используется для создания единой точки входа (публичного API) из нескольких модулей.

9.1 Что делает @forward?

@forward [2] полезен тем, что его можно использовать в одном scss файле, который можно импортировать в scss файлах и при этом не прописывать несколько штук импортов в каждом файле.

Пример с @forward [2]:

Создаем scss файл, допустим _core.scss, и прописываем в нем ссылки, с помощью @forward [2], на scss файлы, которые являются для нас глобальными (переменные, цвета, миксины, шрифты, базовые стили и прочее)

// core.scss

@forward "helpers/colors";
@forward "helpers/variables";
@forward "base/fonts";
@forward "helpers/fonts-variables";
@forward "helpers/extend";
@forward "base/reset";
@forward "base/reboot";
@forward "base/base";
@forward "base/new-system";

И дальше добавляем только один импорт в scss файлах:

//./pages/about-page.scss

@use "../core.scss"

Плюс в том, что вместо, например, 9 импортов, мы будем использовать только один "core".

НО минус такого подхода состоит в том, что при использовании пространства имен (неймспейс), мы не сможем точно поределить из какого scss файла нужная нам переменная, так как все неймспейсы будут равны имени одного файла (c @forward [2]) или же назначенному нами имени (через as). Итог с @forward [2]:

// ./pages/about-page.scss

@use "../core.scss"; // или @use "../core.scss" as core;

.button {
  color: core.$blue;
  border-radius: core.$border-radius-medium;
  @include core.flex-center;
}

Без @forward [2] удобнее тем, что мы сразу можем определить из какого файла, нужный нам стиль, как было описано выше. Но вот еще пример:

// ./pages/about-page.scss

@use '../helpers/colors';
@use '../helpers/variables';
@use '../helpers/mixins';

.button {
  color: color.$blue;
  border-radius: variables.$border-radius-medium;
  @include mixins.flex-center;
}

9.2 Важный нюанс

Как уже говорилось, @forward [2] только пробрасывает содержимое дальше, но сам файл, в котором написаны @forward [2], не получает доступа к этим переменным и миксинам. Если внутри _core.scss понадобится использовать что-то из проброшенных файлов, нужно добавить отдельный @use [1].

// _core.scss

@forward 'helpers/colors';      // проброс наружу
@use 'helpers/colors' as c;     // для использования внутри

body {
  background: c.$bg-color;      // работает благодаря @use
}

9.3 Пространство имён при использовании @forward

При импорте файла-сборщика через @use [1] пространство имён определяется так же, как и для обычного модуля.

9.4 Выборочный проброс (show / hide)

С помощью show и hide можно ограничить, что именно пробрасывается из модуля:

  • show — пробросить только перечисленные имена

  • hide — пробросить всё, кроме перечисленных

// helpers/_index.scss

@forward 'colors' show $primary, $secondary;  // только эти переменные
@forward 'mixins' hide private-mixin;         // все, кроме private-mixin

9.5 Конфигурация через with() при пробросе

Если пробрасываемый файл содержит переменные с !default, их можно переопределить прямо в @forward [2] с помощью with():

// helpers/_theme.scss

$bg-color: #fff !default;
$text-color: #000 !default;

// helpers/_index.scss

@forward 'theme' with (
  $bg-color: #f0f0f0,
  $text-color: #222
);

10. Как организовывать зависимости между модулями

В модульной системе Sass каждый файл изолирован и должен явно указывать, откуда он берёт переменные, миксины и функции. Это касается и случаев, когда один ваш модуль (например, variables.scss) использует переменные из другого модуля (colors.scss).

Пример: variables.scss зависит от colors.scss

// _core.scss

@forward 'helpers/colors';
@forward 'helpers/variables';
@forward 'helpers/mixins';

Внутри _variables.scss по-прежнему нужно писать:

//variables.scss

@use 'colors;;   // явная зависимость
// ...

Почему это правильно:

  • Явность – сразу видно, от каких модулей зависит файл.

  • Надёжность – при переносе файла в другое место зависимости не теряются.

  • Поддержка IDE – автодополнение работает чётко.

  • Рефакторинг – легко найти все места, использующие конкретный модуль.

11. Краткие итоги

  • Явность важнее краткости – каждый файл сам импортирует нужные модули через @use [1]. Это делает зависимости прозрачными.

  • Пространство имён обязательно – обращайся к переменным/миксинам через имя модуля (или алиас). Никакого глобального доступа.

  • Имена модулей – только буквы, цифры (не в начале) и подчёркивание. Дефисы и спецсимволы запрещены.

  • Встроенные модули (sass:math, sass:list и др.) подключаются там, где используются. Они не наследуются.

  • Конфигурация через !default и with() – позволяет гибко настраивать модули, переопределяя значения по умолчанию. with() работает только при первом импорте.

  • @forward [2] для сборки – удобен для создания единой точки входа, но скрывает источник переменных. Используй осознанно.

  • show / hide в @forward [2] – позволяют точечно контролировать, что попадает в публичное API.

  • Зависимости внутри модулей – даже если файл входит в сборщик, внутри него нужно явно писать @use [1] для других модулей.

  • Повторные импорты – норма. Даже если один модуль нужен в ста файлах, в каждом пишем @use [1]. Это плата за надёжность.

  • Рефакторинг становится безопасным – изменения в одном модуле не ломают другие, если их имена не конфликтуют.

Автор: Kenchobas99

Источник [3]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/sass/447513

Ссылки в тексте:

[1] @use: https://www.pvsm.ru/users/use

[2] @forward: https://www.pvsm.ru/users/forward

[3] Источник: https://habr.com/ru/articles/1013818/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1013818