Gratulujeme! Úspěšně jste se přihlásili k odběru novinek Frontend Garden.
Ajaj. Při pokusu o přihlášení k odběru novinek došlo k chybě. Zkuste to prosím znovu.
Frontend Garden
  • Články
  • Slovník nové
  • Instagram
  • GitHub
17. listopad 2020 —
  • Sass,
  • Kvalita kódu
— čtení na 9 min.

Co jsou Sass moduly a jak @use a @forward zlepší váš kód

Sass moduly mění způsob práce se soubory. Nejsou novinkou, představeny byly před více než rokem. Nově je však Dart Sass jedinou oficiální implementací Sassu. Nucená migrace je příležitostí s moduly začít. Přinášíme podrobného průvodce migrací, zapojením Sass modulů a řešením nejčastějších chytáků.

Adam Kudrna

Adam Kudrna

Adam je UI developer/designer s více než 20letou zkušeností. Firmám pomáhá stavět design systémy a komponentové UI knihovny a lidem radí, jak je kódovat. O webovém frontendu píše, školí a přednáší. Více o autorovi

Co jsou Sass moduly a jak @use a @forward zlepší váš kód

Sass moduly nejsou úplná novinka, přesto dosud stály trochu stranou pozornosti. Představeny byly před více než rokem, přesně 2. října 2019, spolu s implementací v oficiální, ale nepříliš rozšířené knihovně Dart Sass. Jiné knihovny pro kompilaci Sassu podporu modulů nikdy nepřinesly, včetně dodnes nejpopulárnější knihovny LibSass. Uplynul rok a vše je jinak: 26. října letošního roku vyšlo oznámení, že Dart Sass zůstává jedinou oficiálně podporovanou knihovnou pro kompilaci Sass do CSS. Bootstrap 5 na Dart Sass přešel již 3 dny po tomto oznámení – a ani my bychom neměli otálet.

Dart Sass je od 26. října 2020 jedinou oficiálně podporovanou knihovnou pro kompilaci Sass do CSS.

Původní implementace Sassu byla napsána v Ruby. Později byla tato knihovna přeportována do C/C++ a vznikla kolem ní řada wrapperů, které umožnily kompilovat Sass do CSS v nejrůznějších programovacích jazycích: mj. Go, Java, Lua, Perl nebo PHP. Ve světě Node.js se oním wrapperem stal projekt node-sass. V době vydání článku má node-sass podle npmjs.com stále přes 5 milionů stažení týdně.

sass pomalu, ale jistě dohání node-sass (screenshot z webu npm trends)
sass pomalu, ale jistě dohání node-sass – pokud zrovna nejsou Vánoce (npm trends)

Od loňského roku ji Dart Sass, respektive sass (sass je distribuce Dart Sass zkompilovaného do čistého JavaScriptu), pomalu, ale jistě dotahuje: z milionu stažení týdně v loňském listopadu vyrostla popularita na více než 2,6 milionu stažení. Jak víme, předvídání epidemiologických a podobných křivek je ošemetné. Lze se nicméně domnívat, že po nedávném oznámení se křivky počtu stažení během pár měsíců protnou a Dart Sass se stane nejrozšířenější implementací Sassu.

Problémy s @import

Vedle proměnných, které jsme v CSS dlouhé roky postrádali, je jedním z největších přínosů preprocesorů oproti čistému CSS možnost přehledně rozdělit zdrojový kód do množství menších souborů. Ty pak s pomocí @import a knihovny kompilujeme do finálního CSS souboru, který servírujeme prohlížečům. Díky tomu je náš kód řádově přehlednější. @import má však své nevýhody:

  • @import je zároveň funkcionalita nativního CSS, což může být matoucí.
  • Vícenásobné importování stejného souboru může vést ke zpomalení kompilace, konfliktům a nežádoucím duplicitám.
  • Vše je importováno do globálního namespace, což z něj dělá doutnající sklad střelného prachu.
  • Problém implicitního importu: při volání mixinu nebo proměnné nemusí být vůbec jasné, kde se vzaly. Soubor volaný s @import může být k dispozici i v souborech stylopisu, které ho přímo nevolají, což je matoucí a může vést k chybám.

Jistě, můžeme se pokusit proměnné, funkce a mixiny alespoň prefixovat a udržovat v jejich pojmenování podobný hierarchický systém, jakým je BEM pro CSS třídy. Nástroj je to však umělý a nedokonalý. S nástupem Sass modulů proto @import nahrazují nová zavináčová pravidla (at rules) @use a @forward.

Import souborů pomocí @use

@use je de facto nástupcem Sass příkazu @import. Přináší ovšem podstatné rozdíly:

  • @use importuje Sass modul pouze jednou, a to při prvním volání, bez ohledu na to, kolikrát volaný modul ve svém kódu použijete. Jinými slovy, první volání @use v kódu je vlastním importem modulu a každé další @use je už jen jeho použitím.
  • @use veškerý importovaný kód (proměnné, funkce, mixiny) zpřístupní v namespace odpovídajícím názvu volaného modulu. @use 'settings/grid' tak zpřístupní vše v souboru settings/_grid.scss v namespace grid, takže proměnné modulu budeme volat grid.$gap atd.
  • Kód importovaný pomocí @use zůstává dostupný pouze v aktuálním souboru. Soubory, které aktuální soubor importují nemají tento kód k dispozici.
  • Podobně je omezena působnost @extends – použije se na selektory v importovaných souborech, ale už ne v souborech, které aktuální soubor importují.
  • Proměnné, funkce a mixiny, které začínají podtržítkem _ nebo spojovníkem - (lidově a nesprávně pomlčkou) jsou brány jako privátní a nejsou importovány.

Typické použití Sass modulů může vypadat takto:

// settings/_container.scss

$max-width: 60rem;
$padding: 1.5rem;


// tools/_container.scss

@use '../settings/container';

@mixin create() {
  max-width: container.$max-width;
  padding-right: container.$padding;
  padding-left: container.$padding;
}


// objects/_container.scss

@use '../tools/container';

.container {
  @include container.create();
}

Sass moduly tak přináší do kódu tyto benefity:

  • Původ závislostí je známý, protože v každém souboru musí být explicitně uvedeny.
  • Místo prefixování globálních proměnných, funkcí a mixinů stylem $container-max-width je kód čitelnější díky strukturovanému zápisu container.$max-width.
  • Díky konceptu privátního obsahu (jehož název začíná na _ nebo -) můžeme kód uvnitř modulů dále zpřehlednit rozdělením do menších, skutečně privátních proměnných, funkcí a mixinů, které nejsou exportovány a nelze je použít jinde. Díky tomu nezanáší globální kontext a jejich názvy nemusí být globálně jedinečné.

Přejmenování importů

Pokud jste předchozí ukázku pročetli pozorně, možná vás napadá: ale co mám dělat, když budu v jednom souboru potřebovat jak modul settings/container, tak stejnojmenný tools/container? V takovém případě můžete importované moduly přejmenovat:

@use '../settings/container' as settings;
@use '../tools/container' as tools;

.container {
  @include tools.create();
  padding-top: settings.$padding;
}

V případě, že byste se namespace potřebovali z nějakého důvodu zbavit úplně, je to možné, i když za cenu nižší expresivity kódu:

@use '../tools/container' as *;

.container {
  @include create();
}

Konfigurovatelné importy

Zatímco s @import je třeba knihovnám předávat konfiguraci přes proměnnou v divočině globálního kontextu, kde hrozí konflikt definic nebo nechtěné přepsání hodnoty, s @use je možné tu samou konfiguraci přesně a cíleně nasměrovat přímo do daného modulu:

// _button.scss

$button-color: forestGreen !default;

.button {
  background-color: $button-color;
}


// styles.scss – dříve

$button-color: deepSkyBlue;

@import 'button';


// styles.scss – nově

@use 'button' with (
  $button-color: deepSkyBlue;
);

To je velice šikovné především pro knihovny. Podmínkou je, že jde o první volání @use daného modulu (další @use lze použít, už ale ne konfigurovat) a že je daná proměnná v modulu definovaná s příznakem !default, čímž říká, že je otevřena přetížení. Je dobré vědět, že tento zápis lze využít i pro závislosti, které funkcionalitu Sass modulů dosud nevyužívají a počítají s konfigurací v globálním kontextu.

Rozšíření předávaného obsahu s @forward

Sass moduly neznamenají pouze výměnu @import za @use. Pravidlo @forward umožňuje modulu navenek zpřístupnit i takové proměnné, funkce a mixiny, které v aktuálním souboru nemají být dostupné. Díky tomu je možné do vnějšího kontextu přeposlat vybrané pomocné funkce, aniž bychom přišli o granularitu zdrojových souborů:

@forward 'functions';
@forward 'variables';
@forward 'mixins';

Klíčová slova show a hide umožňují přesnější kontrolu nad přeposílaným obsahem:

@forward 'functions' hide color-contrast;
@forward 'variables' show $theme, $theme-light, $theme-dark;
@forward 'mixins';

Narozdíl od @use neobaluje @forward přeposílaný obsah do namespace. Můžeme jej však před přeposláním prefixovat:

// _theme.scss
$primary: blue;

// library.scss
@forward 'theme' as 'theme-*';

// project.scss
@use 'library' with ($theme-primary: green);

Vestavěné moduly

Velmi zajímavá je nabídka vestavěných Sass modulů: sass:math, sass:string, sass:list, sass:map, sass:selector a sass:meta. A to hned ze dvou důvodů. Zaprvé, vestavěné moduly zásadně rozšiřují možnosti práce s proměnnými, funkcemi a mixiny, ale nejen s nimi. Zadruhé, vyčleněním Sass funkcí do namespaců nedochází ke konfliktům s nativními funkcemi CSS, což je dobré teď a pro obě strany i do budoucna.

Řada funkcí v Sass modulech má z důvodu kompatibility své aliasy v podobě názvů původních vestavěných Sass funkcí, např. color.adjust() má alias adjust-color(). Zásadním rozdílem mezi starými a novými Sass funkcemi ale je, že ty nové jsou k dispozici pouze v rámci svých modulů, můžeme je tedy použít až po jejich importování:

// Dříve
$new-color: adjust-color($color, $amount);

// Nově
@use 'sass:color';

$new-color: color.adjust($color, $hue: $amount);

Pozor na to, že některé dosavadní Sass funkce nemají z koncepčních důvodů ve vestavěných modulech úplně přesné ekvivalenty. Příkladem budiž třeba hojně využívaná funkce transparentize() / fade-out() se svým protějškem opacify() / fade-in(), ale i lighten(), darken() a další. Přesné rozdíly v chování najdete v dokumentaci.

Migrace z node-sass na sass

Migrace je ve většině případů bezbolestná, Sass moduly jsou plně zpětně kompatibilní. Stačí odinstalovat původní knihovnu, nainstalovat sass a zapojit do automatizace – nic víc by nemělo být třeba.

$ npm uninstall node-sass && npm install --save-dev sass

Je dobré zmínit, že sass přináší oproti node-sass nemalou úsporu v závislostech. Ve spojení s dalšími aktualizacemi nemusí být patrná:

Poměr změn při migraci z node-sass na sass spojené s aktualizací závislostí

Zatímco u čistých migrací je vidět dobře:

Poměr změn při čisté migraci z node-sass na sass (za screenshot díky Honzovi Kryšpínovi!)

Stylelint

Pokud používáte Stylelint (což byste měli), je možné, že budete potřebovat rozšířit povolená zavináčová pravidla v jeho konfiguraci o @use a @forward. K zádrhelu nemusí dojít, využíváte-li některou z komunitních konfigurací jako třeba stylelint-config-recommended-scss, která povoluje jakákoli zavináčová pravidla bez omezení. Jenže pozor, to v důsledku činí jejich kontrolu bezzubou. Spolu s novými @use a @forward vám totiž projde úplně @cokoli – a to nechcete.

Webpack

Pracujete-li na javascriptové aplikaci, pravděpodobně ve vašem stacku nebude chybět Webpack. A pokud píšete styly v SCSS, téměř jistě do něj máte zapojený sass-loader. Ten sám o sobě podporuje jak node-sass, tak Dart Sass, takže možná konfiguraci Webpacku vůbec nebudete muset upravovat.

Jediný chyták nastává s načítáním externích modulů z node_modules. Zatímco s @import jste mohli do node_modules odkázat vlnovkou na začátku importu, tedy např. @import '~normalize.css/normalize.css', s @use to není možné. Stačí ale node_modules doplnit do prohledávaných cest v konfiguraci sass-loaderu, tildu vynechat a máte vyhráno:

// styles.scss
@use 'normalize.css/normalize.css';
// webpack.config.js
{
  loader: 'sass-loader',
  options: {
    sassOptions: {
      includePaths: ['node_modules'],
    },
  },
},

CLI a npm skripty

Pozor na to, že CLI API sass se od node-sass trochu liší. Je však šance, že to, co jste s původní knihovnou nastavovali pomocí CLI argumentů budete moci vynechat, protože se sass půjde o výchozí nastavení.

Příklad npm skriptu v package.json v původní podobě s node-sass:

{
  "scripts": {
    "css:compile": "node-sass --output-style expanded --source-map true src/main.scss built/main.css"
  }
}

Nový npm skript po migraci na sass:

{
  "scripts": {
    "css:compile": "sass src/main.scss built/main.css"
  }
}

Volání knihovny sass je zde podstatně jednodušší, protože expanded styl zápisu a generování source map jsou ve výchozím stavu zapnuté. Dohledání externích závislostí v node_modules lze opět vyřešit buď odmazáním vlnovky:

@use 'normalize.css/normalize.css';

… a doplněním cesty do konfigurační volby --load-path:

{
  "scripts": {
    "css:compile": "sass --load-path=node_modules src/main.scss built/main.css"
  }
}

… anebo explicitním vypsáním úplné relativní cesty:

@use '../../node_modules/normalize.css/normalize.css';

Záleží, co lépe vyhovuje vašemu projektu.

Samozřejmě jsou i další automatizační nástroje jako Parcel, Gulp aj., svět nepoužívá pouze Webpack nebo npm skripty. Princip migrace by se ale ani v jejich případě neměl nijak zásadně lišit.

Automatická migrace na Sass moduly

Pokud vám nestačí jen vyměnit kompilující knihovnu a chcete začít naplno využívat Sass moduly, jejichž podporu sass přináší, můžete vyzkoušet automatický nástroj pro migraci přímo od autorů Sassu. Stačí jej nainstalovat:

$ npm install --global sass-migrator

A spustit (na zkoušku raději s --dry-run):

$ sass-migrator module --dry-run --migrate-deps styles.scss

V případě migrace knihovny se může hodit zachovat dostupnost všech proměnných, funkcí a mixinů, a to přepínačem --forward=all:

$ sass-migrator module --dry-run --migrate-deps --forward=all library.scss

Mějte na paměti, že soubory, které už jsou volané s pomocí @use bude sass-migrator považovat za již zmigrované. Více podrobností a další způsoby instalace najdete v dokumentaci.

Shrnutí

Co bude dál s @import a se starými Sass funkcemi? Zatím zůstávají k dispozici, aby vývojáři měli dostatek času přemigrovat své projekty na nový modulární systém. Obě funkcionality budou časem zapovězeny a nakonec úplně odstraněny ve prospěch Sass modulů. A kdy k tomu dojde? Podle oficiálních plánů budou globální funkce Sassu spolu s @import označeny za deprecated nejpozději 1. října 2021. Rok nato, 1. října 2022, pak bude jejich podpora definitivně odstraněna. Dosavadního plánu se zatím vývojářský tým Sassu držel, víme tedy přesně, kolik času máme na to se připravit.

Ponechání knihovny Dart Sass jedinou oficiální implementací a ukončení vývoje těch ostatních (oficiálních) je pro vývojáře impulzem ke změně. Je jen na nás, zda situaci pojmeme čistě jako výměnu jednoho kolečka ve frontendovém soukolí, anebo využijeme příležitost k tomu stroj rozebrat, promazat a znovu sestavit. Výhody konceptu Sass modulů, včetně těch vestavěných, jsou zásadní, a já věřím, že není nač čekat.

Související odkazy

  • The Module System is Launched (Natalie Weizenbaum, Sass, 2019)
  • Introducing Sass Modules (Miriam Suzanne, CSS Tricks, 2019)
  • Understanding Dart Sass modules and namespaced variables (Kevin Hougasian, RIMdev, 2019)

Úvodní ilustraci způsobil autor článku. Nepoužívejte ji prosím bez jeho souhlasu nebo citace.


Adam Kudrna

Adam Kudrna

Adam je UI developer/designer s více než 20letou zkušeností. Firmám pomáhá stavět design systémy a komponentové UI knihovny a lidem radí, jak je kódovat. O webovém frontendu píše, školí a přednáší. Více o autorovi

Další články od autora:

  • Pozvánka na WebExpo 2025
  • WebExpo 2024 obrazem
  • WebExpo 2023 obrazem
Více k tématu:
  • Sass
  • Kvalita kódu

Sdílejte

Líbí se vám článek? Podpořte jej sdílením!

X (Twitter) Facebook LinkedIn

Komentujte

Chcete k článku něco doplnit? Našli jste chybu? Napište e-mail.

Adam Kudrna

Nejnovější články

WebExpo — čtení na 3 min.

Pozvánka na WebExpo 2025

Rok se s rokem sešel, přichází měsíc květen a s ním WebExpo 2025, které se po nejistých letech usadilo v tomto jarním termínu. Jaké bude?

  • Adam Kudrna
    Adam Kudrna
Pozvánka na WebExpo 2025
JavaScript — čtení na 10 min.

Jak předcházet chaotické organizaci npm skriptů

Řešíte, jak organizovat skripty napříč projekty přehledně a konzistentně? Inspirujte se systémem, který zjednoduší práci vám i kolegům.

  • Tomáš Litera
    Tomáš Litera
Jak předcházet chaotické organizaci npm skriptů
Reportáž — čtení na 2 min.

FrontKon 2024 obrazem

Frontendisti letos připravili třetí ročník konference FrontKon. Ta se letos historicky poprvé odehrála naživo v Praze, a to v prostorách O2 Universum.

  • Kateřina Klouček Dlouhá
    Kateřina Klouček Dlouhá
FrontKon 2024 obrazem

Odběr novinek

Zadejte svůj e-mail a nenechte si ujít další nové články!

Odesláním formuláře souhlasíte se .
Zpracování osobních údajů probíhá za účelem zasílání newsletteru. Můžete se spolehnout, že vaše osobní údaje nebudeme s nikým sdílet. Z newsletteru se můžete kdykoli odhlásit. Stejně tak můžete kdykoli požádat o úplné smazání svých osobních údajů z naší databáze.
Zkontrolujte svoji e-mailovou schránku a potvrďte své přihlášení kliknutím na odkaz.

Všechna témata

  • Bootstrap
  • CSS
  • Design
  • Dokumentace
  • HTML
  • ITCSS
  • JavaScript
  • Kariéra
  • Kvalita kódu
  • Nástroje
  • No-code
  • Přístupnost
  • PWA
  • Reportáž
  • Rozhovor
  • Rychlost
  • Sass
  • Spolupráce
  • Typografie
  • Variable fonts
  • WebExpo
  • ✏️ Napište článek
  • Autoři
  • Cookies
  • Instagram
  • GitHub

Obsah na tomto webu je publikován pod licencí Creative Commons CC BY-NC 4.0.
Frontend Garden vysázel, zastřihuje a okopává (s ♥️) Adam Kudrna.
Založeno v květnu 2019.