今度こそ@importをやめる!

こんにちは、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が使った場合の図を見ましょう。

@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;
}

画像で表すと次のようになります。

@use

基本使用は構造的には@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”;

図で表すと以下のようになります。

@forwardと@use

画像を見たら分かりやすいでしょうか。エントリーポイントになっている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の運用費用の減少までメリットが多すぎますから。

もう一回まとめると、

  1. @use@forwardでインポートされたパーシャルはモジュールと呼ぶ。
  2. パーシャルを@forwardで一つのファイルに集約して、それをページ用CSSファイルの中で@useで読み込む。
  3. 名前空間のおかげでSassの管理がしやすくなった。

になります。冒頭にも言いましたが、恥ずかしいほど簡単でした。

この記事を読んで、少しでも分かりやすくなったと思ったら大変嬉しいです。ちなみに、本稿の図はすべてNulabが提供しているCacooというツールで作成しました。BacklogTypetalkとのインテグレーションもバッチリで、リンクを貼るだけでCacooで描いた図を埋め込むこともできます。ぜひ、試してみてください!

では!

開発メンバー募集中

より良いチームワークを生み出す

チームの創造力を高めるコラボレーションツール

製品をみる