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

CSSの拡張言語[Sass](http://sass-lang.com/)の強力な機能の一つは、ファイルを複数に分割できる「[Partials](http://sass-lang.com/documentation/file.SASS_REFERENCE.html#partials)」です。ファイルを機能ごとに分割することで、見通しのよいコードを記述できます。近年注目を浴びている「[OOCSS](http://www.slideshare.net/stubbornella/object-oriented-css)」をSassで実現する上でもよく使われています。

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

![](https://qiita-image-store.s3.amazonaws.com/0/67884/81140fe4-68f6-fce0-4e68-6aa5ff122260.png)

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

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

```scss:_a.scss
.classA {
  background-color: red;
}
```

```scss:_b.scss
.classB {
  background-color: blue;
}
```

```scss:style.scss
@import "a";
@import "b";
```

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

```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`を記述しなければなりません。

```scss
@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](https://www.npmjs.com/package/gulp-sass-glob)」やNode.jsの「[node-sass-globbing](https://www.npmjs.com/package/node-sass-globbing)」といったプラグインを使うと、Sassにおいても`@import "hoge/ **";`の記述でSassファイルの読み込みが可能になります。今回は、Gulp(※)での設定事例を紹介します。

※ 参考記事「[5分で導入！ タスクランナーGulpでWeb制作を効率化しよう - ICS MEDIA](https://ics.media/entry/3290)」

## 環境のセットアップ
まずは環境設定を行います。Gulpがグローバルにインストールされていない場合は、インストールしておいてください（`npm install -g gulp-cli`）。

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

```bash
npm init -y
```

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

```bash
npm i -D gulp gulp-sass gulp-sass-glob
```

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

```js: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]よりダウンロードできますので、サンプルを試したい場合はご利用ください。

- [import用のSassのサンプルファイル](https://github.com/ics-kano/kano-box/tree/sample/sass-glob)


```
└── 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ファイル名を記述する必要はなく、最低限の行数のコードで記述可能です。

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

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

```bash:コマンドラインで実行
gulp
```

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

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

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

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

```sass:更に短いimport
@import "**";
```

# `import`文は半分以下になり、ファイルの追加・削除
globを用いることで10行あった`@import`は、3行（構成によっては1行）に減りました。

![](https://qiita-image-store.s3.amazonaws.com/0/67884/3321eb8d-39b4-118e-c840-6346e52c76b1.png)

機能ごとにファイルを分割して見通しのよいSassコードを書いたり、[OOCSS](http://www.slideshare.net/stubbornella/object-oriented-css)に基づくCSS設計を行ったとしても、大量の`@import`記述に時間を使う必要はありません。glob機能を使いこなし、効率的なSassのコーディングを行いましょう。