こんにちは、UXエンジニアのヨーナスです。今回のブログリレー投稿では、よく後回しにされがちなSassの@import
アットルールの廃止に伴うリファクタについて書きます。
基本的には人間というのは、変化が苦手なものです。もちろん、僕もそうです。一度いいやり方を見つけるとそれにずっと従いがちな性格です。何かの明らかなメリットが見えないと一回慣れたやり方でずっとやってしまうタイプです。ですが、いざ新しいことに挑戦してみると、結局やってみてよかった〜と毎回終わりに思います。そもそもSass自体もそうでしたし、TypeScriptもそうでした。一度その良さを味わうと元には戻れなくなります。
新しいことに挑戦するのはいいことですが、実は、今回の記事の内容は「挑戦」というまでもなく、まったく複雑ではありません。それでも、記事として少しでも役に立てばなーと思いながら書きます。僕は初めて@import
を@use
と@forward
にリファクタしようとした時に読みたかった記事を書いているつもりで、対応しない言い訳を残さないように説明を頑張ります!
そもそもなんで@importが廃止にされる?
CSSプリプロセッサのSassがリリースされて以来、幅広くウェブ業界に浸透しましたが、特に@importというアットルールについて様々な問題点が浮かんできました。主な問題を3つ紹介します。
まずは、1つ目の問題はCSSにも@import
という、他のファイルの内容を読み込むアットルールがあるという点です。Sassの@import
はそれを拡張したもので、シンタックスと使い方も若干本来のものと変わっていますので、開発者にとって紛らわしい存在です。本稿で使う@import
はSassのものを示します。
2つ目の問題は、無駄な処理が行われることと、無駄なコードがコンパイルされることです。Sassは、@import
でインポートされたファイルがすでにどこかでインポートされているかどうかは分かりません。これによって、複数のSassファイルの中でインポートされたファイルが、読み込みごとに、毎回コンパイルされて、重複してCSSとして書き出す場合もあります。このような無駄処理はCI/CDの実行時間を長くするし、CSSファイルの肥大化でページロードのスピードにも影響を及ぼします。
3つ目の問題点は、名前衝突の可能性です。@import
を使うと、インポートされたSass変数やmixinや関数がグローバルな名前空間に入ってしまって、名前がかぶるリスクが発生します。
要は、あまりに問題点が多くあって、Sassの開発チームは@importを廃止することを決めました。次にその代わりになった@use
と@forward
アットルールを紹介します。
@useと@forwardはどうやってこの問題を解決するのか?
前に書いた問題をどうやって解決できるかを見てみましょう。
最初の問題の解決方法は簡単です。2つの@import
が存在する問題は、Sassのものの廃止でなくなります。これから使われる@import
はCSSのもののみになります。
2つ目の問題についても、Sassの@import
の代わりになる@use
を使うと、Sassがすでにインポート済みのファイルを把握できるので、重複処理やCSSの肥大化を防ぎます。3つ目の名前衝突の問題が、開発者にとって一番ややこしい問題です。この問題を解決するために、Sassに名前空間が導入されました。それでSassのインポートに対する考え方が大幅に変わります。@import
と違って、@useでインポートされたパーシャル(Sassの読み込み対象ファイル)は、ただCSS内容を読み込むだけではなく、固有の名前空間を持っているモジュールとして扱われるようになります。再利用性や名前空間が重視されてきて、ある意味でJavaScriptでの開発に少し似てきたとも言えるでしょう。
従来の@import
おさらいになりますが、まず、従来のSass @import
が使った場合の図を見ましょう。
お馴染みのパターンですね!パーシャルをテーマ別で分けて、集約ファイルにまとめて、それをまたページ用Sassファイルで@import
します。インポートされたSass変数やMixinや関数はすべて同じファイルで使えるようになるのが便利ですが、プロジェクトの規模が大きくなればなるほど名前衝突のリスクも高まります。それを避けるために、開発者が変数に接頭辞を付けたりドキュメンテーションを残したりして工夫しないといけません。
@use登場
これからデフォルトになるSassのインポート方法に入ります!@use
は、他のファイルのCSSを読み込むSassのアットルールです。使い方は@import
に似ていますが、さきほど説明したとおり、違いがいくつかあります。
@use
は次のように使います:
// _colors.scss $niceBlue: #5eabed;
// index.scss @use "colors"; .button { background-color: colors.$niceBlue; }
@importと同様に、@useでファイルを読み込む場合、_
と拡張子を入れる必要がありません。モジュールを@useでインポートすると、名前空間が生成されるので、Sass変数の最初にモジュールの名前を指定する必要があります。名前空間はデフォルトで、_
と拡張子を省いたファイル名になります。上記の例では、名前空間はcolorsになっています。複数のモジュールをインポートする例を見てみましょう。
// style.scss @use "mixins"; @use "colors"; @use "fonts"; .title { color: colors.primary; font-family: fonts.title; @include mixins.paddingSmall; }
画像で表すと次のようになります。
基本使用は構造的には@import
と変わりません。次は、集約ファイルの新しい作り方を紹介します。
@forwardは?
@forward
は、パーシャルを集約して他のファイルで使えるようにまとめるSassのアットルールです。基本的には、@forward
が入っているファイルに他のコードを書きませんので、非常に分かりやすいです。
一般的な@forward
ファイルの例:
@forward 'components/buttons'; @forward 'components/carousel'; @forward 'components/modal'; @forward 'components/breadcrumb'; @forward 'components/animation';
要するに、@forward
を使うことで、インポートしたい複数のパーシャルをひとつにまとめてモジュール化することができます。
「全部まとめてくれるなら@forward
だけでいいのでは?」と思ってしまうかもしれませんが、モジュールを実際にスタイルの中で利用するには@use
が必要なので、@forward
だけでは動きません。
では、どうすればいいでしょうか?
@use と @forward を一緒に使うには?
パーシャルをまとめたモジュールファイルを@use
で読み込みます。
// styles.scss @forward “mixins”; @forward “colors”; @forward “fonts”;
// top.scss // main.scss // loggedIn.scss @use “styles”;
図で表すと以下のようになります。
画像を見たら分かりやすいでしょうか。エントリーポイントになっているSassファイルと、そうでないSassファイルがはっきりと分けられてきました。
@forward
が使った集約ファイルの便利な点は、インポートするモジュールをカスタマイズできることです。必要に応じて、複数の集約を作成することができますので、例えば、不要なスタイルを省いて、トップページのパフォーマンスを高めることができます。
補足しますが、メインのSassファイルが一つしかない規模の小さいサイトの場合は、@forward
を使う必要が特にありませんので、@use
だけでも全く問題ありません。
「@forwardなどはどうでもいい。とりあえず@importをなくしたいだけ」と思っている方へ
@import
が廃止になったあと、パッケージ更新などでCI/CDの周りはがどうなるかなどの心配になる方がいると思います。@use
に移行したいけど時間の余裕がない方には、他の対応方法もあります。こういった、とりあえず@import
をなくしたい場合は、モジュールを*
として@use
すると名前空間を指定されなくてもSassの変数やMixinや関数が使えます。
// _fonts.scss $baseFontSize: 1.4rem;
// style.scss @use "fonts" as *; .text { font-size: $baseFontSize; }
インポートの仕方が変わりますが、セレクターの中身を触る必要がありません。しかし、こうすると、名前衝突から守る名前空間がなくなるので、あまり推奨はできません。
終わりに
いかがでしたか?
@use
と@forward
のおかげでスタイル管理がだいぶ楽になります。むしろ、もし@import
サポートが続いても、積極的に移行したいくらいです。コードが読みやすくなることからCI/CDの運用費用の減少までメリットが多すぎますから。
もう一回まとめると、
@use
か@forward
でインポートされたパーシャルはモジュールと呼ぶ。- パーシャルを
@forward
で一つのファイルに集約して、それをページ用CSSファイルの中で@use
で読み込む。 - 名前空間のおかげでSassの管理がしやすくなった。
になります。冒頭にも言いましたが、恥ずかしいほど簡単でした。
この記事を読んで、少しでも分かりやすくなったと思ったら大変嬉しいです。ちなみに、本稿の図はすべてNulabが提供しているCacooというツールで作成しました。BacklogとTypetalkとのインテグレーションもバッチリで、リンクを貼るだけでCacooで描いた図を埋め込むこともできます。ぜひ、試してみてください!
では!