#5 「SCSS入門講座」 @importでSCSSファイルの読み込みとgulp-sassの導入

SCSSにはCSSとは違う @import という拡張機能があります。また、今後SCSSを使うにあたって必須となる gulp を導入して、より楽に開発ができるようにしていきます。

@import

CSSの@import


@import 'foo.css';             /* ファイル名(シングルクォーテーション) */
@import "foo.css";             /* ファイル名(ダブルクォーテーション) */
@import 'css/foo.css';         /* 相対パス */
@import "foo.css" screen;          /* メディアタイプ */
@import "http://foo.com/bar.css";  /* 絶対パス */
@import url('foo.css');        /* url() */
@import url(foo.css);          /* url()(クォーテーションなし) */

CSSの @import を使って外部CSSを読み込むにはこのような書き方で書く必要があります。また、 必ずCSSファイルの一番上@charset の直後)に記述する必要があります。 CSSの @import はファイルを分割できて非常に便利なのですが、 読み込みが非常に遅くなる という欠点もあります。そこで、便利なのが SCSS@import 機能です。

SCSSの@import


@import 'foo.scss'; // ファイル名(シングルクォーテーション)
@import "foo.scss"; // ファイル名(ダブルクォーテーション)
@import 'foo';      // .scss省略
@import 'scss/foo'; // 相対パス+.scss省略

SCSSの @import も同じような感じで読み込むことができます。SCSSの場合、 .scss 拡張子を省略することもできます。また、SCSSの @import はCSSと違って コンパイル時に展開 されます。実際に見ていきましょう。


.foo {
  display: block;
}

確認用としてこんな感じで記述した foo.scss ファイルを用意します。


// foo.scss読み込み
@import 'foo';

.main {
  color: red;
}

次に、 sample.scss 内で foo.scss を読み込んでみます。


node-sass sample.scss sample.css --output-style=expanded

あとはいつも通りコンパイルします。


.foo {
  display: block;
}
.main {
  color: red;
}

すると、このように sample.cssファイル内に展開 されます。このようにSCSSの @import では複数のSCSSファイルを1つにまとめることができるようになります。

しかし、このようにコマンドを入力してコンパイルする方法だと、ファイル数が増えてきたときに いちいちコマンドを入力する 必要があり非常に面倒です。そんなときに便利なのが、 gulp というツールです。

gulpの導入

gulp は、SCSSのコンパイルなどの色々な処理を自動化してくれるタスクランナーです。

package.jsonの作成


npm init -y

現在作業中の sample フォルダ内でWindowsなら コマンドプロンプト、Macなら ターミナル を起動してコマンドを入力すると package.json が作成されます。 npm install でインストールされたものを管理するためのファイルだと思っておいてください。

インストール


npm install gulp -g

gulp をグローバルにインストールします。どのフォルダからも使えるようにグローバルにインストールしています。次回以降グローバルにインストールする必要はありません。


npm install gulp gulp-sass --save-dev

次に gulp とSCSSをコンパイルするための gulp-sass をインストールします。

gulpfile.jsの作成


const gulp = require('gulp');
const scss = require('gulp-sass');

// SCSSファイルをコンパイルするタスク
gulp.task('scss', function() {
  gulp
    .src('*.scss')           // .scssで終わる全ての(*)ファイルを読み込む
    .pipe(scss())            // SCSSをコンパイル
    .pipe(gulp.dest('./'));  // 同じ階層(./)に出力
});

sample フォルダ内にこのような gulpfile.js を作成してください。JSを使っているので初めての方は難しく感じるかもしれませんが、単なる 設定ファイル のようなものです。pipe() で処理を繋げていっているのが分かるかと思います。もちろん、間に pipe() で別の処理を挟むことも可能です。

SCSSのコンパイル


sample/
  ├─ node_modules/       インストールしたモジュール
  ├─ sample.scss         コンパイルするSCSSファイル
  ├─ foo.scss            sample.scssでインポートされるSCSSファイル
  ├─ gulpfile.js         設定ファイル
  ├─ package.json        インストールしたモジュールの管理ファイル
  └─ package-lock.json   自動生成されるファイル

sample フォルダの中身はこんな感じになっていると思います。sample.scssfoo.scss は先ほど作成したものをそのまま使います。


gulp scss

gulp <タスク名> でgulpfile.jsで定義したタスクを実行することができます。このコマンドを入力すると foo.csssample.css の2つのファイルが生成されていると思います。こんな感じで gulp を使うと複数のSCSSファイルを同時にコンパイルすることができます。

しかし今回の場合、 foo.css ファイルは sample.css 内でインポートされているので生成する必要がありません。そういった場合は、SCSSの パーシャル という機能を活用できます。

パーシャル

先ほどのように @import で読み込ませるファイルをCSSファイルとして生成する必要がない場合はファイル名の前に _ (アンダースコア)をつけると生成されなくなります。これを パーシャル といいます。

試しに、 foo.scss から _foo.scss にファイル名を変更して同じように gulp scss コマンドでコンパイルしてみてください。(コンパイルする前に foo.css ファイルが生成されないことを確認するため、foo.css ファイルは削除しておきましょう。)

すると、 foo.css ファイルが生成されないことが確認できると思います。


// _foo.scss読み込み(どれでもよい)
@import 'foo';
@import '_foo';
@import 'foo.scss';
@import '_foo.scss';

.main {
  color: red;
}

_foo.scss ファイルの読み込みは _ をつけてもつけなくても読み込むことができます。ただ、 _ を省略すると、 foo.scss を読み込んでいるのか _foo.scss を読み込んでいるのか分からなくなる可能性もあるので注意が必要です。

自動でコンパイル


const gulp = require('gulp');
const scss = require('gulp-sass');

// SCSSファイルをコンパイルするタスク
gulp.task('scss', function() {
  gulp
    .src('*.scss')           // .scssで終わる全ての(*)ファイルを読み込む
    .pipe(scss())            // SCSSをコンパイル
    .pipe(gulp.dest('./'));  // 同じ階層(./)に出力
});

// 自動で監視してコンパイル
gulp.task('watch', function() {
  // .scssファイル変更時にscssタスクを実行
  gulp.watch('*.scss', ['scss']);
});

gulpfile.jswatch というタスクを追加します。


gulp watch

このコマンドを入力して、SCSSファイルを変更すると自動的にコンパイルされるようになります。終了したい場合は、 Ctrl + C で終了できます。

その他の設定


const gulp = require('gulp');
const scss = require('gulp-sass');

// SCSSファイルをコンパイルするタスク
gulp.task('scss', function() {
  gulp
    .src('*.scss')                 // .scssで終わる全ての(*)ファイルを読み込む
    .pipe(scss({                   // SCSSをコンパイル
      outputStyle: 'expanded'      // 出力形式を指定(nested/expanded/compact/compressed)
    }).on('error', scss.logError)) // SCSSエラーのとき終了させない
    .pipe(gulp.dest('./'));        // 同じ階層(./)に出力
});

// 自動で監視してコンパイル
gulp.task('watch', function() {
  // .scssファイル変更時にscssタスクを実行
  gulp.watch('*.scss', ['scss']);
});

node-sass のときに --output-style で出力形式を指定できましたが、 gulp-sass でもこのように指定することができます。また、SCSSでコンパイルエラーが起きた時に watch タスクを終了させないような設定を書いておくと捗ると思います。