先日、KOJIKA17さんの「Sassを@importから@useに置き換えるための手引き 」という記事を見て、2022年10月ころにはSassで@import
が使えなくなる可能性があることを知りました。まだ2年ありますが、新しく取り組むプロジェクトでは@use
を使ったモジュールシステムにしたいので、自分が使っている構成の置き換えについて考えてみました。
まずはアイディアをシェアをして叩き台にしてもらうのが目的ですが、他に良い書き方があったらぜひアドバイスいただきたいというのもあります。
試しながら、考えながら書いているので内容は変更される可能性が高いかもしれません。
Sassの新モジュールシステムについて
Sassの新しいモジュールシステムについては、上述の記事や SHIFTBRAINさんのブログ がわかりやすかったです。ありがとうございます。
公式の発表と@use
と@forward
のドキュメントは以下で読めます。
Dart Sassじゃないと使えません(2020年6月現在)
ちなみに、2019年10月にリリースされたDart Sass 1.23.0以降じゃないと@use
と@forward
は使えないので、古いバージョンや他のバリエーションをお使いの方はお気をつけください!
LibSassでは5.0に実装予定のよう ですが、2020年6月1日時点でのバージョンは3.6.4で、4.0のリリース目標が2021年だそうなので、ちょっと先の話になりそうです。ほんとに2022年10月に@import
を廃止できるのかな?
なにはともあれ、@import
な書き方から@use
な書き方への移行の方法を考えてみます。
いままでの@importを使った書き方
最近はFLOCCS をベースにしたCSSの書き方をしていて、メインとなるstyle.scss
で以下のように@import
を使ってすべてのモジュール(scssファイル)を読み込んでいます。
// styles.scss
// Foundation
@import "foundation/variables";
@import "foundation/mixins";
@import "foundation/sanitize";
@import "foundation/base";
// Layout
@import "layout/header";
// Component
@import "component/button";
// Project
@import "project/campaign";
// Utility
@import "utilties";
@import
でごっそり全部読み込んで、一番上でvariables
に設定した変数やmixins
に書き込んだmixinを他のどのモジュールからでも使えるようにしています。
foundation/variables
はサイト全体で使う色やサイズ関連の変数をまとめたファイルfoundation/mixins
は共通で使う@mixinをまとめたファイルfoundation/sanitize
はsanitaize.css というCSSリセットの一種foundation/base
は共通で使うスタイル要素をまとめたファイル
他のモジュールは種類別にLayout、Component、Project、Utilityのフォルダに入れています。ここでは例として1つしか@import
していませんが、実際は各種類ごとに複数のモジュールがあります(projectとcomponentがほとんどですが…)。
@importを@useに変えるだけでは動かない
上記の@import
を@use
に変えると、たとえば、component/button
からはfoundation/variables
に設定されている変数を参照できなくなります。@use
の場合は、呼び出したファイル内でしか読み込んだファイルの内容(変数、関数、mixin)を参照できないんですね。
なので、単に@import
を@use
に変えただけではダメなんですね。モジュールごとにfoundation/variables
を読み込む必要があります。
たとえば、component/button
でfoundation/variables
にある$color-btn-normal
という変数を使いたい場合、以下のようにcomponent/_button.scss
で@use
を使ってfoundation/variables
を読み込む必要があります。
// component/_button.scss
@use "../foundation/variables";
.c-button {
background: variables.$color-btn-normal;
}
あと@use
を使うと名前空間が発生するので、@import
で読み込んだ時みたいに$color-btn-normal
だけでは参照できなくて、variables.$color-btn-normal
のように記述する必要があります。
モジュール(ファイル)名が名前空間になるんですが、@use "../foundation/variables" as var
のように自分で設定することも可能です。
これ、一見すると面倒だなぁと思ったんですが、設計面とかメンテのことを考えたら構造が明確になっていいのかもしれませんね。
@useと@forwardを使った書き方を試してみる
ということで、@use
と@forward
を使った構成を考えてみました。いろいろ試しながら改良を加えていきたいですが、いまのところ以下のような書き方を試してみようと思っています。
ディレクトリとファイル構成
まずはディレクトリとファイル構成から。グローバル変数と@mixin
をまとめるglobal
ディレクトリを追加しました。他の構成は変わっていません。
├── foundation
│ ├── _base.scss
│ ├── _index.scss
│ └── _sanitize.scss
│
├── global
│ ├── _index.scss
│ ├── _mixins.scss
│ └── _variables.scss
│
├── layout
│ └── _header.scss
│
├── component
│ └── _button.scss
│
├── project
│ └── _campaign.scss
│
└── utility
└── _index.scss
※FLOCCS本家のファイルディレクトリ構成 では、component
、project
、utility
の3つをobject
ディレクトリに入れてますが、個人的に入れ子にするメリットを感じなかったのでフラットにしています。
変更点
foundation
に入れていた変数(_variables.scss
)と@mixin(_mixin.scss
)はグローバルで読み込めるようにしたいので、global
フォルダに移動。global
は、設定ファイルという意味を込めてconfig
という名前でも良いかと思いましたが、変数を指定する際にglobal.$hoge
と書く方がわかりやすいのでglobal
にしました。
他の構成は以前と変わりません。
foundationとglobalは_index.scssでまとめる
FoundationとGlobalに入っているモジュールをまとめるために_index.scss
を追加して、それぞれ以下のように@forward
を設定しました。
foundation/_index.scss
// foundation/_index.scss
@forward "sanitaize";
@forward "base";
これで@use "foundation"
と記述すればsanitize
とbase
が読み込めます。foundation
に入れるファイルはそこまで増えないと思うので、いらないかなぁと思いつつ、すっきりするしわかりやすいと思ったので_index.scss
にまとめてみました。
global/_index.scss
// global/_index.scss
@forward "variables";
@forward "mixins";
これで、@use "global";
でglobal
内のすべてのモジュール(変数と@mixin)をglobal
という名前空間で参照できます。
ただ、このやり方だとglobal/_mixins.scss
でglobal/_variables.scss
の変数を使いたい場合、以下のように@use
を使って読み込む必要があって、なんか気持ち悪いんですが仕方ないですかね?(自分だけ?)
// global/_mixins.scss
@use "variables" as var;
style.scssの記述
@import
を使った書き方と違い、style.scss
には変数や@mixinを読み込みません(style.scss内で参照する場合は必要)。なので、Foundationにはシンプルにsanitaize
とbase
を@forward
したfoundation
のみ読み込みます。他のモジュールは@import
を@use
に変えただけです。
// styles.scss
// Foundation
@use "foundation";
// Layout
@use "layout/header";
// Component
@use "component/button";
// Project
@use "project/campaign";
// Utility
@use "utilties";
各モジュールでグローバル変数とmixinを読み込む
各モジュールでグローバルの変数やmixinを読み込みたい場合、以下のようにglobal
を読み込みます。
// component/_button.scss
@use "../global";
.c-button {
background: global.$color-btn-normal;
font-size: 1rem;
@include global.mq(global.$body-width-medium){
font-size: 0.875rem;
}
}
モジュールごとに@use
でグローバルを呼び出さないといけないのは若干面倒ですが、明示的にすることでモジュールで使われている変数や@mixinが確認できるので、メンテナンス性があがって良さそうですね。
あと、モジュールごとに使いたい変数や@mixinは、直接モジュールのファイルに書けばいいと思っています。
効率的な名前空間の命名のしかた
上のセクションでGlobalモジュールは名前空間をglobal
として読み込ようにすると書きましたが、実際のプロジェクトでやってみて、やっぱり名前空間の命名は短くしたほうが良いと思いました。というのも、グローバルな変数やMixinを読み込むたびに毎回global.$color-hoge-hoge
と書くのが面倒なんですよね。一度や二度ならいいですか、下手したら数百回参照する可能性もありますからね。
ということで、いまのところGlobalの名前空間は以下のようにg
にするのがいいんじゃないかと考えているところです。
// component/_button.scss
@use "../global" as g;
.c-button {
background: g.$color-btn-normal;
font-size: 1rem;
@include g.mq(global.$body-width-medium){
font-size: 0.875rem;
}
}
さいごにひとこと
ということで、まずはこんなやり方でSassの@import
から@use
への移行を試してみようと思っています。この構成でサイト/ページを作ってみて、問題や課題がみつかったらこの記事の内容も更新したいと思います。
では、Enjoy writing styles using Sass!
更新情報
- 「効率的な名前空間の命名のしかた」について内容を追加しました(2020/7/15)
2020年6月1日に公開され、2020年7月15日に更新された記事です。
About the author
「明日のウェブ制作に役立つアイディア」をテーマにこのブログを書いています。アメリカの大学を卒業後、ボストン近郊のウェブ制作会社に勤務。帰国後、東京のウェブ制作会社に勤務した後、ウェブ担当者として日英バイリンガルのサイト運営に携わる。詳しくはこちら。
ウェブ制作・ディレクション、ビデオを含むコンテンツ制作のお手伝い、執筆・翻訳のご依頼など、お気軽にご相談ください。いずれも日本語と英語で対応可能です。まずは、Mastodon @rriver@vivaldi.net 、Twitter @rriver 、またはFacebook までご連絡ください。
[…] Sassのモジュールシステムを@importから@useに移行する方法を考えてみた | Rriver […]