Sass: новая модульная система
Команда Sass уже много лет знает, что правило @import
, одно из самых ранних дополнений к Sass, было не таким хорошим, как мы этого хотели. Это вызвало целый ряд проблем для наших пользователей:
- Было почти невозможно выяснить, где была задана исходная переменная, миксин или функция (собирательно называемые «members»), поскольку все, что определено в одной таблице стилей, было доступно для всех таблиц стилей, которые были импортированы после нее.
- Даже если вы решите явно импортировать каждую таблицу стилей, в которой определены элементы, которые вы использовали, вы получите дублирующий CSS и странные побочные эффекты, потому что таблицы стилей перезагружались с нуля при каждом импорте.
- Использовать краткие и простые имена было небезопасно, потому что всегда была возможность, что некоторые другие таблицы стилей в другом месте вашего приложения будут использовать то же имя и испортить вашу логику. Чтобы быть в безопасности, пользователям приходилось вручную добавлять длинные, неуклюжие пространства имен ко всему, что они определяли.
- Авторы библиотек не могли гарантировать, что их приватные хелперы не будут доступны для нижестоящих пользователей, что вызовет путаницу и проблемы с обратной совместимостью.
- Правило
@extend
может повлиять на любой селектор в любом месте таблицы стилей, а не только те, что автор явно решил расширить.
Мы также знали, что любая замена, которую мы хотели внедрить, должна быть спроектирована и разработана с предельной тщательностью, чтобы обеспечить прочную основу для будущего развития Sass. За последние несколько лет мы обсудили, спроектировали и разработали совершенно новую модульную систему, которая решает эти и многие другие проблемы, и сегодня мы рады сообщить, что она доступна в Dart Sass 1.23.0.
Обратите внимание, что система модулей полностью обратно совместима. Существующие функции не были удалены или устарели, и ваши текущие таблицы стилей Sass будут работать так же, как и всегда. Мы разработали модульную систему для обеспечения полной совместимости @import
, чтобы авторам таблиц стилей было легче переходить к ней постепенно. Мы планируем в конечном итоге избавиться от этого @import
, но не раньше, чем у всех будет возможность мигрировать.
@use
, сердце модульной системы
Правило @use
является основным для замены @import
: это делает CSS, переменные Примеси и функции из другой таблицы стилей, доступной в текущей таблице стилей. По умолчанию переменные, миксины и функции доступны в пространстве имен на основе базового имени URL-адреса.
@use "bootstrap"; .element { background-color: bootstrap.$body-bg; @include bootstrap.float-left; }
Кроме пространство имен, есть несколько важных различий между @use
и @import
:
@use
выполняет только таблицу стилей и включает ее CSS один раз, независимо от того, сколько раз эта таблица стилей используется.@use
делает имена доступными только в текущей таблице стилей, а не глобально.- Элементы, имена которых начинаются с
-
или_
являются приватными для текущей таблицы стилей. - Если таблица стилей включает в себя
@extend
, это расширение применяется только к таблицам стилей, которые оно импортирует, а не к таблицам стилей, которые его импортируют.
Управление пространствами имен
Хотя правило пространства имен @use
по умолчанию определяется базовым именем его URL, оно также может быть установлено явно с помощью as
.
@use "bootstrap" as b; .element { @include b.float-left; }
Специальная конструкция as *
также может быть использована для включения всего в пространство имен верхнего уровня. Обратите внимание, что если несколько модулей предоставляют элементы с одинаковыми именами и используются с as *
, Sass выдаст ошибку.
@use "bootstrap" as *; .element { @include float-left; }
Конфигурирование библиотек
При этом библиотеки часто настраиваются @import
путем установки глобальных переменных, которые переопределяют !default
, определенные этими библиотеками. Поскольку переменные больше не являются глобальными с @use
, saas поддерживает более явный способ настройки библиотек c with
:
// bootstrap.scss $paragraph-margin-bottom: 1rem !default; p { margin-top: 0; margin-bottom: $paragraph-margin-bottom; }
@use "bootstrap" with ( $paragraph-margin-bottom: 1.2rem );
Это устанавливает значение переменной $paragraph-margin-bottom
как 1.2rem
до ее оценки. Конструкция with
допускает только переменные, определенные в (или пересылаемые) импортируемым модулем, и только если они определены с помощью !default
, поэтому пользователи защищены от опечаток.
@forward
, для авторов библиотеки
Правило @forward
включает в себя переменные другого модуля, миксины и функции в рамках API выставленного текущего модуля, не делая их видимыми для кода в текущем модуле. Это позволяет авторам библиотеки разделять свою библиотеку по множеству различных исходных файлов, не жертвуя локальностью в этих файлах. В отличие от @use
, forward не добавляет к именам пространства имен.
// bootstrap.scss @forward "functions"; @forward "variables"; @forward "mixins";
Контроль видимости
Правило @forward
может выбрать для отображения только конкретных имен:
@forward "functions" show color-yiq;
Он также может скрывать имена, которые предназначены для приватной библиотеки:
@forward "functions" hide assert-ascending;
Дополнительный префикс
Если вы перенаправляете дочерний модуль через модуль «all-in-one», вы можете добавить к этому модулю некоторое пространство имен вручную. Вы можете сделать это с помощью конструкции as
, которое добавляет префикс к каждому перенаправляемому имени члена:
// material/_index.scss @forward "theme" as theme-*;
Таким образом, пользователи могут использовать модуль «all-in-one» с хорошо определенными именами для переменных темы:
@use "material" with ($theme-primary: blue);
или они могут использовать дочерний модуль с более простыми именами:
@use "material/theme" with ($primary: blue);
Встроенные модули
Новая модульная система также добавляет встроенные модули (sass:math
, sass:color
, sass:string
, sass:list
, sass:map
, sass:selector
, и sass:meta
). Поскольку эти модули (как правило) будут импортироваться с пространством имен, теперь гораздо проще использовать функции Sass, не сталкиваясь с конфликтами с простыми функциями CSS.
Это, в свою очередь, делает Sass более безопасным для добавления новых функций. Мы собираемся добавить ряд удобных функций для этих модулей в будущем.
Переименованные функции
Некоторые функции имеют имена во встроенных модулях по сравнению с глобальными функциями. Встроенные функции, которые уже имели пространства имен, например map-get()
, удаляют эти пространства имен во встроенных модулях, так что вы можете просто писать map.get()
. Точно так же adjust-color()
, scale-color()
и change-color()
в настоящее время color.adjust()
, color.scale()
и color.change()
.
Мы также воспользовались этой возможностью, чтобы изменить несколько запутанных имен старых функций. unitless()
сейчас math.is-unitless()
и comparable()
сейчас math.compatible()
.
Удаленные функции
Функции для работы цветами lighten()
, darken()
, saturate()
, desaturate()
, opacify()
, fade-in()
, transparentize()
, и fade-out()
у всех них было очень неинтуитивное поведение.
Чтобы помочь нам встать на путь исправления, эти функции (вместе с adjust-hue()
) не включены в новые встроенные модули. Вы все еще можете получить тот же эффект, вызвав color.adjust()
- например, lighten($color, $amount)
эквивалентно - color.adjust($color, $lightness: $amount)
но мы рекомендуем вместо этого использовать color.scale()
, если это возможно, потому как он более интуитивно понятен.
В какой-то момент в будущем мы планируем добавить color.lighten()
и аналогичные функции в качестве сокращений color.scale()
.
meta.load-css()
Новая модульная система поставляется с новым встроенным миксином meta.load-css($url, $with: ())
. Этот миксин динамически загружает модуль с заданным URL и включает его CSS (хотя его функции, переменные и миксины не доступны). Это замена для вложенного импорта, и она помогает решить некоторые сценарии использования динамического импорта без многих проблем, которые могут возникнуть, если новые элементы могут быть загружены динамически.
Совместимость @import
Экосистема Sass не переключится в одночасье на @use
, поэтому, в то же время, она должна хорошо взаимодействовать с @import
. Это поддерживается в обоих направлениях:
- Когда файл, содержащий
@import
, использует@use
, все в его глобальном пространстве имен рассматривается как один модуль. Члены этого модуля затем обращаются к использованию его пространства имен как обычно. - Когда файл, содержащий
@use
, использует@import
, все в его общедоступном API добавляется в глобальную область импорта таблицы стилей. Это позволяет библиотеке контролировать, какие конкретные имена она экспортирует, даже для пользователей, которые используют@import
, а не@use
.
Чтобы позволить библиотекам поддерживать существующий @import
-ориентированный API с явным пространством имен, где это необходимо, в этом предложении также добавлена поддержка файлов, которые видны только для @import
, а не для @use
. Они именуются как "file.import.scss"
и импортированы, когда пользователь пишет @import "file"
.
Автоматическая миграция
Одновременно с запуском новой модульной системы мы запускаем новый автоматизированный Sass-мигратор. Этот инструмент позволяет легко перенести большинство таблиц стилей для автоматического использования новой системы модулей. Следуйте инструкциям на сайте Sass, чтобы установить его, а затем запустите его в своем приложении:
$ sass-migrator module --migrate-deps
Флаг --migrate-deps
говорит мигрировать не только файл который вы указали, но все, что он импортирует. Мигратор автоматически подберет файлы, импортированные через синтаксис Webpack node_modules
, но вы также можете передать явные пути загрузки с флагом --load-paths
.
Если вы хотите, чтобы мигратор сообщал вам, какие изменения он будет вносить, не внося их на самом деле, передайте флаги --dry-run
, и --verbose
, чтобы он просто распечатывал изменения, которые будет вносить, не сохраняя их на диск.
Миграция библиотеки
Если вы хотите перенести библиотеку Sass, предназначенную для загрузки и использования нижестоящими пользователями, выполните:
$ sass-migrator module --migrate-deps --forward=all
Флаг --forward
указывает Migrator добавлять правила @forward
, так что пользователи могут загрузить все миксины, переменные и функции из вашей библиотеки используя @use
.
Если вы добавили пространство имен вручную в свою библиотеку, чтобы избежать конфликтов имен, мигратор удалит его для вас, если вы передадите флаг --remove-prefix
. Вы можете даже передать только тех участников, которые изначально имели этот префикс, путем передачи --forward=prefixed
.
Проблемы с регистрацией
Инструмент миграции является совершенно новым, поэтому он может иметь некоторые проблемы. Если у вас возникнут какие-либо проблемы, пожалуйста, не стесняйтесь описать проблему на GitHub!
Попробуй это сейчас!
Система модулей доступна как часть Dart Sass 1.23.0. Вы можете установить его прямо сейчас, используя:
$ npm install -g sass
Перевод статьи: The Module System is Launched
Источник: sass.logdown.com