Sassのモジュールシステムを@importから@useに移行する方法を考えてみた

Advertisement

先日、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/sanitizesanitaize.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/buttonfoundation/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本家のファイルディレクトリ構成 では、componentprojectutilityの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"と記述すればsanitizebaseが読み込めます。foundationに入れるファイルはそこまで増えないと思うので、いらないかなぁと思いつつ、すっきりするしわかりやすいと思ったので_index.scssにまとめてみました。

global/_index.scss

// global/_index.scss
@forward "variables";
@forward "mixins";

これで、@use "global";global内のすべてのモジュール(変数と@mixin)をglobalという名前空間で参照できます。

ただ、このやり方だとglobal/_mixins.scssglobal/_variables.scssの変数を使いたい場合、以下のように@useを使って読み込む必要があって、なんか気持ち悪いんですが仕方ないですかね?(自分だけ?)

// global/_mixins.scss
@use "variables" as var;

style.scssの記述

@importを使った書き方と違い、style.scssには変数や@mixinを読み込みません(style.scss内で参照する場合は必要)。なので、Foundationにはシンプルにsanitaizebase@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)

About the author

Rriverのステッカーが貼られたMacBookの向こうにいる自分のMemojiの似顔絵

「明日のウェブ制作に役立つアイディア」をテーマにこのブログを書いています。アメリカの大学を卒業後、ボストン近郊のウェブ制作会社に勤務。帰国後、東京のウェブ制作会社に勤務した後、ウェブ担当者として日英バイリンガルのサイト運営に携わる。詳しくはこちら

ウェブ制作・ディレクション、ビデオを含むコンテンツ制作のお手伝い、執筆・翻訳のご依頼など、お気軽にご相談ください。いずれも日本語と英語で対応可能です。まずは、Mastodon @rriver@vivaldi.net Twitter @rriver 、またはFacebook までご連絡ください。

“Sassのモジュールシステムを@importから@useに移行する方法を考えてみた” への1件のコメント

  1. […] Sassのモジュールシステムを@importから@useに移行する方法を考えてみた | Rriver […]