Sassでファイルを呼び出す際に使っていた@importは廃止される予定でして、代わりに「@use」「@forward」を使うように推奨されています。自分も重い腰を上げて@useを使ってみました。
(※ Google日本語翻訳)
Dart SassとLibSassの両方がモジュールシステムのサポートを開始してから1年後、またはDart Sassがモジュールシステムのサポートを開始してから2年後のいずれか早い方(遅くとも2021年10月1日)に、@importグローバルコアライブラリ関数呼び出しと同様に非推奨になります。それはモジュールを通して作ることができます。
この非推奨が発効してから1年後( 遅くとも2022年10月1日)、@importほとんどのグローバル機能のサポートを完全に終了します。これには、すべての実装のメジャーバージョンリリースが含まれます。
https://sass-lang.com/blog/the-module-system-is-launched#future-plans
なぜ腰が重くなるかと言うと、@importを@useに書き換えるだけでは使えないからですね。@importでは定義した変数をそのまま使うことができたが、@useでは呼び出しもとのファイルを特定して変数を使用しなければならない、といった縛りが出てきます。
例えば以下のようなイメージです。
@import "variable";
.hoge {
color: $color-main;
}
↓ 呼び出し元のファイル名(もしくは名前空間)を利用する必要が出てくる
@use "variable" as var;
.hoge {
color: var.$color-main;
}
この記事では、Dart Sassでの基本的な書き方と、@importからの移行方法について紹介していきます。実際に手を動かさないと理解しづらい部分もあると思いますが、Sassを使っている方ならいつか対応する必要があることなので、時間を作って重い腰を上げましょう!
@useの使い方
@forwardは基本的に呼び出すだけで使っているので説明は割愛します。@useについては、@importになかった特殊な使い方があるので実例を交えながら紹介していけたらと思います。
呼び出し先で変数を使う
冒頭でも紹介しましたが、一番の大きな変化は、呼び出し元ファイルを起点として変数やmixin、関数の使い方が変わるといった点ですね。
重複しますが、以前は呼び出し元ファイルの中で定義していた変数名を呼び出し先のファイルでもそのまま使えましたが、Dart Sassでは、呼び出し元を明示して使用する必要が出てきます。
@import "variable";
.hoge {
color: $color-main;
}
↓ @useの場合
@use "variable" as var;
.hoge {
color: var.$color-main;
}
上記Afterの「var.」に当たる部分は「名前空間」と呼ばれたりします。どこのファイルから呼ばれたものか定義するものと捉えていただて大丈夫です。
この名前空間にもルールがあって、以下の2点です。
- asで繋ぐことで「名前空間」の名前を定義できる
- asで繋いでいない場合は「名前空間」はファイル名となる
先ほどの例だと、as var
としているので、名前空間は「var」となり、呼び出す際も「var.$color-main;」としているわけです。
as var
を削除し、@use "variable";
だけにした場合の変数の呼び出し方は、ファイル名が名前空間となるので、「variable.$color-main;」となります。
@useでのファイル名
@useの右側に定義しているファイル名ですが、省略可能となるルールがあります。
これは@importでも馴染みがあるはずなので理解しやすいと思いますが、以下の3点ですね。
- ファイル名の先頭の「_(アンダーバー)」は省略できる
- 「.scss」の拡張子は省略できる
- 「_index.scss」は省略できる
_heading.scssというファイルを@useする際は、以下のようになるわけです。
@use "heading";
component/_index.scssというcomponentフォルダ内にある_index.scssファイルを読み込みたい場合は、以下のようになります。
@use "component";
@importを@useに書き換える手順
これまでは、FLOCSSで以下のようなフォルダ構成で@importして使っていました。(ファイルは割愛します)
- setting
- function
- foundation
- layout
- component
- project
- utility
- style.scss
「gulp-sass-glob」でまとめていたので以下のような書き方となっています。なお、@useではglobでまとめるこができないので、その恩恵が受けられくなりました。。
@import "setting/**";
@import "function/**";
@import "foundation/**";
@import "layout/**";
@import "component/**";
@import "project/**";
@import "utility/**";
globでまとめることができない
もしgulpで「gulp-sass-glob」などを使って、まとめて出力している方がいたら、ちょっとだけ悲報かもしれません。
Dart Sassの@use、@forwardの書き方では以下のような「gulp-sass-glob」を使ってまとめることはできなさそうです。
ファイルが増えるたびに一つひとつを@useもしくは@forwardして手動で管理していく必要がありそうです。
変数や関数の定義は一つにまとめる
@useでは呼び出し先で呼び出し元のファイルを定義する必要が出てきます。都度、settingとfunctionを呼び出すのが面倒なので、ここを1つにまとめます。(2つが1つになるだけですが…)
変数のまとめ方は主に以下の記事を参考にさせていただきました。
「global」というフォルダを用意し、ここに「setting」フォルダと「function」フォルダの中身を統合するような形で格納します。わたしはボリュームが少ないので、ファイル化しましたが、フォルダのまま入れてもいいと思います。
- global
- _index.scss
- _variables.scss
- _function.scss
- foundation
- layout
- component
- project
- utility
- style.scss
こうすることで、呼び出し先で以下のように定義することで、定義したすべての変数や関数を使うことができるようになります。
例えば、「component/_button.scss」で使う場合は、以下のようにglobalの変数郡を読み込んで変数を使うようなイメージです。
global/_index.scssにglobal内のファイルをまとめてあげて、
@forward "variables";
@forward "function";
// その他global内のファイルすべて
各コンポーネント用のファイル内で呼び出して変数や関数を使うようなイメージです!
// component/_button.scssで使っている例
@use "../global" as global;
.c-button {
background-color: global.$color-main;
}
globalファイルはすべてのファイルで読み込む
@import的にsettingやfunctionで定義した変数を使いたい場合は、「foundation」「layout」「component」「project」「utility」フォルダ内のすべてのファイルの先頭で「global」の定義を読み込んでおく必要があります。
@use "../global" as global;
// 読み込んだ後にCSSの記述
変数を書き換える
一番面倒なのは変数の書き換えですね。@useによって名前空間を先頭につけるというルールが新たにできました。
各ファイルで膨大に使われている変数を、(今回の名前空間の例だと)global.$var-name
といった形に書き換えていく必要があるわけですね。
@use "../global" as global;
.c-button {
background-color: global.$color-main; // 変数が使われているところは全部書き換える
@include global.mq('sp') { // mixinや関数が使われているところも全部書き換える
width: 100%;
}
}
各フォルダ内のファイルを_index.scssでまとめる
一般的には当たり前にやっていることかもしれませんが、「gulp-sass-glob」で自動でまとめていた自分は、この作業をする必要がありました。
(しなくてもいいですが、呼び出しの大本となるstyle.scssの記述量が膨大になる恐れ…)
- global
- _index.scss
- _variables.scss
- _function.scss
- …
- …
- foundation
- _index.scss
- …
- …
- …
- layout
- _index.scss
- …
- …
- …
- component
- _index.scss
- …
- …
- …
- project
- _index.scss
- …
- …
- …
- utility
- _index.scss
- …
- …
- …
- style.scss
globalの例でいうと以下のようなまとめ方ですね。1つフォルダの対して1つの_index.scssを用意してフォルダ内で並列するファイルはすべてまとめるようなイメージです。
// globalフォルダの_index.scssの例
@forward "variables";
@forward "function";
// その他global内のファイルすべて
globalで@forwardを使ったのは、その先にあるファイルの変数や関数を使いたいからで、変数を祖先のファイルまで使わせる予定がないであろうcomponentとかprojectとかは、@useでまとめていいと思います。
// componentフォルダの_index.scss例
@use "button";
@use "heading";
// その他component内のファイルすべて
こうして作り直されたSassファイルを読み込むstyle.scssは以下のような記述になります。
@use "foundation";
@use "layout";
@use "component";
@use "project";
@use "utility";
@import時代と大きな違いとしては、「setting」や「function」といった変数の定義に関するファイルもstyle.scssの先頭に書き込んで作っていたと思いますが、@useでは利用先となる各ファイルで呼び出さないと使えなくなったため、style.scssから変数を読み込むことはなくなりました。
割り算は関数を使おう
Sassでは簡単に割り算が行えるようになっています。例えば、以下のような感じですね(特にdisplay: grid
の登場によりややこしくなった印象です)。
/* grid-rowのCSS */
.hoge {
grid-row: 3 / 7;
}
割り算の記号としては、「/
」です。ただ、この「/
」の記号ですが、通常のCSSでも使われていたりする記号です。
割り算かCSSの値かを明確に区別するためにSass側で割り算用の関数を新たに用意しています。今後は割り算をする場合は、以下のように関数を使って指定するようにしましょう!
@use "sass:math";
.hoge {
padding-top: math.div(420px, 1200px) * 100%;
}
@useと@forwardの違い
ファイルの呼び出し方として、@useと@forwardの2つがあります。この2つは、ちょっとややこしいですが、以下の違いがあります。
- ファイル1では、ファイル1で@useしたファイル2で@useしているファイル3の変数は使うことができない。
- ファイル1では、ファイル1で@useしたファイル2で@forwardしているファイル3の変数は使うことができる。
今回のようにglobalで一括管理するような作り方の場合は、問題に遭遇することもないかもしれません。深い位置にある変数までアプローチしたい場合に@forwardを検討すると覚えておくといいかもしれません。
Gulpファイルの書き換え
Dart Sassを使うにあたって、必要となるパッケージやgulpfile.jsの書き方が変わってきます。追加で必要となるパッケージは以下の2つですね。
npm install --save-dev sass fibers
gulpfile.jsの書き方は、以下のように変わります。(最小限だけで簡単に書いています)
/* package */
const gulp = require("gulp");
const sass = require("gulp-sass");
const fiber = require('fibers');
/* select use compiler */
sass.compiler = require("sass"); // Dart Sass = "sass"
/* compile sass */
gulp.task("sass", function() {
return gulp
.src("./sass/**/*.scss")
.pipe(sass({ // sass option
fiber: fiber,
outputStyle: "expanded"
}))
.pipe(gulp.dest("./css"));
});
sass.compiler = require("sass");
によってDart Sassを使うことを明示しています。ちなみにnode-sass
が従来のSassのようです。node-sass
はgulp-sass
に内包されています。
Scss のコンパイラとして
https://labor.ewigleere.net/2020/11/09/scss_transfer_libsass_dartsass/gulp-sass
を利用していますが、現時点(2020/11/9)ではgulp-sass
はデフォルトだとnode-sass
を使用しています。
fiber
は処理の高速化に必要なパッケージのようです(あまり理解はしていない…)
コンポーネント毎の書き方が求められる?
@useの書き方から考えると、より限定的な書き方が求められているのかなと感じました。
- どのファイルからの変数参照かの特定
- 変数の利用範囲の限定
などの縛りが強くなり、どこに影響しているか分かりやすくなります。
今回は取り急ぎの@importからの移行ということで、変数や関数をglobalとしてまとめましたが、本来的には特定のコンポーネントに対する変数といった感じで分けるとよりよくなるかもしれません。
おわり
Dart Sassの基本的な使い方の紹介と、@importからの移行方法でした。
- @importを@useにしただけでは使えないこと
- @useで変数の利用範囲の制限がでてくること
- @useでファイルの利用が限定的になること
- gulp-sass-globが使えなくなること
- Sass構造の見直しが必要になること
など、制限が加わることで書き方の見直し(設計方法も含めて)が必要になってくるかと思います。
いい機会なので、今のSassの構成がベストの方法かを見直す機会としてもいいかもしれませんね。いずれにしても従来の書き方から変えなければならない日はくるので、早いうちに慣れておきましょう!