ブログ
Sassの新しいモジュールシステム
Sassに新しいモジュールシステムが導入されます。具体的には@use
と@forward
という2つのルールが登場し、@import
ルールは将来的に廃止される予定です。現在、Sassのおもな実装としてDart SassとLibSassがありますが、まずDart Sassへの実装が進んでいて、今年10月に安定版がリリースされる予定です。この新しいモジュールシステムを簡単に紹介したいと思います。
なお、ここで言うSassの「モジュール」とは、メンバー(変数、関数、ミックスイン)のコレクションを指し、具体的にはSassのソースファイルのことです。
背景
新しいモジュールシステムが開発された背景として、@import
ルールがかかえる多くの問題があります。ファイルスコープがないため依存モジュールの把握が困難になったり、名前空間を持たないためにライブラリの作者と利用者が命名を工夫しないといけなかったり、といった具合です。
Sassの新しいモジュールシステムはこれらの問題に取り組むとともに、Sassをほかのモダンな言語に近づけることを目指しています。
@use
@use
は@import
を置き換えるルールで、Sassファイル読み込むための新しい方法です。その最大の特徴はファイルスコープを持つ点です。
たとえば、プロジェクト全体で利用する変数をまとめた_theme.scss
というファイルがあったとします。このファイルをブロックの外側で@import
すると、変数はグローバルになり、どのファイルからもアクセスできます。
main.scss
:
@import "theme";
@import "base";
_theme.scss
:
$font-stack-sans: "Helvetica Neue", sans-serif;
$font-stack-serif: "Georgia", serif;
_base.scss
:
body {
font-family: $font-stack-serif;
}
一方@use
を使って読み込むとこれらの変数はグローバルにはならず、読み込んだファイル内でしかアクセスできません。またデフォルトでファイル名に応じた名前空間を持ち、以下のようにnamespace.$variable
という形式で参照することになります。これは関数とミックスインも同様です。
main.scss
:
@use "base";
_base.scss
:
@use "theme";
body {
font-family: theme.$font-stack-serif;
}
@import
による読み込みでは、あるSassファイルで使われているメンバーがどこに宣言されているかを把握するのがかなり大変でした。新しいモジュールシステムではファイルごとに参照するモジュールを宣言するため、そのSassファイルがどのモジュールに依存しているのか簡単に把握できるようになります。
名前空間のコントロール
@use
を宣言するときにas
節を使うと独自の名前空間を持たせることもできます。
@use "theme" as t;
body {
font-family: t.$font-stack-serif;
}
このときas *
とすると、そのモジュールはトップレベルの名前空間に展開されます。ただしモジュールを読み込むファイル内でメンバーの名前が重複するとエラーになるので注意が必要です。
@use "theme" as *;
body {
font-family: $font-stack-serif;
}
ライブラリの設定
!default
フラグを持った変数を上書きするとき、従来の@import
ルールでは変数をグローバルに定義する必要がありました。@use
ではファイルの読み込みと同時にwith
節を用いることで変数を上書きでき、グローバルな名前空間を汚染しません。
_typography.scss
:
$base-font-size: 1rem !default;
$base-line-height: 1.5 !default;
@mixin large-text () {
font-size: $base-font-size * 2;
line-height: $base-line-height * 0.75;
}
_base.scss
:
@use "typography" with (
$base-font-size: 1.125rem,
$base-line-height: 1.6,
);
h1 {
@include typography.large-text();
}
プライベートメンバー
名前が-
または_
ではじまるメンバーはプライベートになります。これらのメンバーは宣言されたファイル内でしかアクセスできません。
_theme.scss
:
$-count: 0;
_base.scss
:
@use "theme";
.layer {
z-index: theme.$-count; // Error!
}
@forward
@forward
ルールはほかのモジュールのメンバーを読み込みつつ、それらを現在のモジュールのAPIとしてエクスポートします。@use
とは違って、@forward
を宣言しているファイル内ではそのモジュールのメンバーを参照できません。たとえば大きなライブラリを作るときなどに便利そうです。
bootstrap/_index.scss
:
@forward "functions";
@forward "variables";
@forward "mixins";
_base.scss
:
@use "bootstrap";
p {
margin-top: 0;
margin-bottom: bootstrap.$paragraph-margin-bottom;
}
show
節でどのメンバーをエクスポートするかを選べます。それ以外のメンバーはエクスポートされません。
@forward "functions" show color-yiq;
逆にプライベートにしたいメンバーをhide
節で除外することもできます。
@forward "functions" hide assert-ascending;
実際に試してみる
新しいモジュールシステムの実装されたSass 1.23.0は、すでにベータ版が提供されていて、パッケージマネージャーやSassのリポジトリからインストールできます。また実際に試せるリポジトリも用意してみました。ぜひ触ってみてください。
タイムライン
今年10月にはDart Sassで安定版がリリースされる予定です。LibSassへの実装はまだこれからで、スケジュールも未定だそうです。
@import
ルールは、モジュールシステムがDart SassとLibSassの両方でリリースされてから1年後、またはDart Sassのリリースから2年後(遅くとも2021年10月)には非推奨になります。そしてそのさらに1年後(つまり遅くとも2022年10月)にサポートが終了する予定です。
おわりに
実際のプロジェクトで使ってみないことには見えてこないこともあるでしょうし、普及するまでにはそれなりの混乱もあるものと思われます。とは言えSassがより使いやすい言語になるのは間違いないのではないしょうか。楽しみですね。