Sassの複数のimportはglobを使って一つにまとめると幸せ


CSSの拡張言語Sassの強力な機能の一つは、ファイルを複数に分割できる「Partials」です。ファイルを機能ごとに分割することで、見通しのよいコードを記述できます。近年注目を浴びている「OOCSS」をSassで実現する上でもよく使われています。

しかし、分割するファイルが多くなればなるほど、大量の@importを記述したり、ファイル分割の度に@importを書き換える手間がかかります。本エントリーでは、このような大量のimport文を短くまとめる方法について紹介します

Sassのファイルの分割と問題点

例えば、_a.scss_b.scssの2ファイルに分割したスタイル設定を、style.scssにて読み込む設定をしてみます。

_a.scss
.classA {
  background-color: red;
}
_b.scss
.classB {
  background-color: blue;
}
style.scss
@import "a";
@import "b";

style.scssをコンパイルすることで、_a.scss_b.scssが結合されてCSSが出力されます。

結合後のCSS
.classA {
  background-color: red;
}

.classB {
  background-color: blue;
}

ファイルの増加と共に増加する@import

2ファイルくらいの場合は特に問題ありませんが、例えば次のように多階層・多数に分割したSassファイルの読み込みを考えてみましょう。


└── sass
    ├── foundation
    │   ├── _foundation1.scss
    │   └── _foundation2.scss
    ├── layout
    │   ├── _layout1.scss
    │   └── _layout2.scss
    ├── object
    │   ├── component
    │   │   ├── _component1.scss
    │   │   └── _component2.scss
    │   ├── project
    │   │   ├── _project1.scss
    │   │   └── _project2.scss
    │   └── utility
    │       ├── _utility1.scss
    │       └── _utility2.scss
    └── style.scss

これらのSassファイルを読み込む場合、次のように多くの@importを記述しなければなりません。

@import "foundation/foundation1";
@import "foundation/foundation2";

@import "layout/layout1";
@import "layout/layout2";

@import "object/component/component1";
@import "object/component/component2";

@import "object/project/project1";
@import "object/project/project2";

@import "object/utility/utility1";
@import "object/utility/utility2";

また、ファイルを追加・削除する度に@importを追加・削除する必要があります。Node.jsのファイル操作機能のように、@import "hoge/**";という記述(globパターン)ができれば短く済みそうですが、Sassの現在のバージョン(3.4)ではそのような機能はありません。

globパターンが使えるプラグインを使うことでこの問題は解決します。

glob用のプラグインでSassのimport文を減らす

Gulp用のプラグイン「gulp-sass-glob」やNode.jsの「node-sass-globbing」といったプラグインを使うと、Sassにおいても@import "hoge/ **";の記述でSassファイルの読み込みが可能になります。今回は、Gulp(※)での設定事例を紹介します。

※ 参考記事「5分で導入! タスクランナーGulpでWeb制作を効率化しよう - ICS MEDIA

環境のセットアップ

まずは環境設定を行います。Gulpがグローバルにインストールされていない場合は、インストールしておいてください(npm install -g gulp-cli)。

プロジェクトフォルダにて、npmの初期設定を行います

npm init -y

Gulp、Sass、そしてgulp-sass-globのプラグインをローカルにインストールします。

npm i -D gulp gulp-sass gulp-sass-glob

タスクの設定

globを用いて記述されたimport文を解釈しつつ、style.scssファイルをコンパイルするタスクを定義します。

gulpfile.js
// プラグインの読み込み
const gulp = require("gulp");
const sass = require("gulp-sass");
const sassGlob = require("gulp-sass-glob");

// Sassコンパイルタスクの定義
gulp.task("default", function() {
  return gulp.src("sass/style.scss")
    .pipe(sassGlob()) // Sassの@importにおけるglobを有効にする
    .pipe(sass())
    .pipe(gulp.dest("css"));
});

以上で準備は完了です。Sassファイルをコンパイルしてみましょう。

Sassファイルをコンパイルする

任意のSassファイルを準備します。例として、冒頭で示したファイル構成のSassファイルをstyle.scssで読み込むことを考えます。下記のURLの[Clone or download]よりダウンロードできますので、サンプルを試したい場合はご利用ください。

└── sass
    ├── foundation
    │   ├── _foundation1.scss
    │   └── _foundation2.scss
    ├── layout
    │   ├── _layout1.scss
    │   └── _layout2.scss
    ├── object
    │   ├── component
    │   │   ├── _component1.scss
    │   │   └── _component2.scss
    │   ├── project
    │   │   ├── _project1.scss

  (中略)

    └── style.scss

▲ コンパイル対象のSassファイル群

globパターンを使って@importを定義

style.scssでglobパターンによる@importを記述します。全てのSassファイル名を記述する必要はなく、最低限の行数のコードで記述可能です。

globパターンを使った読み込み
@import "foundation/**";
@import "layout/**";
@import "object/**";

Sassのコンパイルタスクを実行します

コマンドラインで実行
gulp

出力されたCSSを確認すると、目的のCSSファイルが全て読み込まれていることがわかります。

コンパイル後のCSS
/* foundation1 */
/* foundation2 */
/* layout1 */
/* layout2 */
/* component1 */
/* component2 */
/* project1 */
/* project2 */
/* utility1 */
/* utility2 */

foundationフォルダやlayoutフォルダでファイルの追加・削除があった場合も、style.scssを書き換える必要はありません。

ファイル順を無視すればさらに短く

通常の@importと同じく、記述順にSassファイルは読み込まれます。前述の例では、foundationlayoutobjectの順番にCSSを読み込むために3つの@importを記述しましたが、ファイル順を無視できるファイル構成ならば@importは1行で済みます

更に短いimport
@import "**";

import文は半分以下になり、ファイルの追加・削除

globを用いることで10行あった@importは、3行(構成によっては1行)に減りました。

機能ごとにファイルを分割して見通しのよいSassコードを書いたり、OOCSSに基づくCSS設計を行ったとしても、大量の@import記述に時間を使う必要はありません。glob機能を使いこなし、効率的なSassのコーディングを行いましょう。