はじめに
この記事はGulpを使ってSassをコンパイルしているけど、なんだかよくわかってないという人に向けた記事です。Sassをただコンパイルするだけではなく、AutoprefixerやMinify・Source mapなどあると便利だと思う必要最低限の構成の作り方とそれぞれの使い方を解説していきます。
前提
- npmコマンドをなんとなく使ったことがある
- gulpfile.jsというものは知っている
目指す構成
- Sassのコンパイルをする
- Source mapを作成する
- Minifyする
- Autoprefixerでベンダープレフィックスを自動的に付与する
- 1〜4のことをファイルの変更があったら自動的に行う
学べること
- Gulp実行までの手順
- Gulpのタスクの作り方
- Gulpのタスクの実行の方法
- ファイル監視の方法
環境設定
まずはGulpを動かすための環境を整えましょう。Gulpを使ったことがある人は既にNode.jsがインストールされていると思いますが、まだ使ったことがない人はNode.jsの推奨版をインストールしてください。
Node.jsをインストールすると同時にnpmというコマンドを実行できるようになります。
今回はnpm 5.2から実装されたnpxコマンドも使用していきますので、コマンドラインからnpm -v
を実行してバージョンがnpm5.2未満だったらnpm i -g npx@latest
でnpmを最新バージョンにアップデートしてください。
バージョンアップ後、npx -v
でバージョンが表示されれば実行環境が整った状態です。
package.jsonの作成
GulpはNode.js上で動くツールです。使用するためにはnpmコマンドでモジュールをインストールする必要があります。
npmでのモジュールのインストールのためには、package.jsonが必要でこのpackage.jsonにインストールしたモジュールの名前やバージョンが記述されることにより、同じ環境の再構築がコマンドひとつで済むようになっています。
ではGulpをインストールするためにコマンドライン上でGulpを使用するフォルダに移動します。
1 |
cd 移動したいフォルダのパス(絶対パスか相対パス) |
その後
1 |
npm init -y |
を実行します。
本来であればプロジェクト名やバージョンなどをこのタイミングで設定することが出来ますが、今回は不要ですので-y
オプションでスキップしました。
これでプロジェクトフォルダにpackage.jsonが作成されましたので確認してみてください。
いろいろなプロパティが記述されていますが、これから作成するものをnpmモジュールとしてパブリックな場所に登録しない限りは設定は不要です。
なお、同じ設定を別のプロジェクトフォルダで使いたい場合はpackage.jsonをコピーするだけで済みますので、必ずしもnpm init
でpackage.jsonを作成する必要はありません。
これでnpmモジュールをインストール出来るようになりました。早速Gulpをインストールしていきます。
Gulpをインストール
Gulpはnpmモジュールとして提供されています。今回は下記のコードでローカルにインストールします。
1 |
npm install -D gulp |
なお、ローカルにインストールした場合は他のフォルダではgulpコマンドは使えません。また直接gulpコマンドを実行することも出来ません。どこでもgulpコマンドを実行できるようにするには下記のコマンドでグローバルにインストールします。
1 |
npm install -g gulp |
下記のように+ gulp@バージョン
と表示されればインストールが完了しています。
1 2 |
+ gulp@3.9.1 added 186 packages in 3.259s |
gulpコマンドが使えるかどうか、gulpのバージョンを表示して確認してみましょう。
1 |
npx gulp -v |
npxコマンドは有り体にいえばローカルにインストールしたgulpを実行するためのコマンドです。グローバルにgulpをインストールしなかった場合はgulp -v
というコマンドでは実行できないため、このようにnpxコマンドを使います。
グローバルではなくローカルにインストールする意味がないように思えますが、プロジェクトごとにGulpのバージョンが違い動かない場合もありますのでローカルにインストールすることをオススメします。
GulpでHello World!
めでたくGulpが使えるようになりましたので、トレーニングとして「Hello World!」を表示してみましょう。
Gulpで実行する内容はタスクで管理されます。例えばSassをコンパイルするタスク、ファイルの変更を監視するタスクといった形で用途に合わせてタスクを分けることが出来るようになっています。
まずは「Hellow World!」というメッセージを表示するだけのタスクを作ってみましょう。
結果はコマンドライン上に出力されることになります。
package.jsonが作成されたフォルダにgulpfile.jsを作成し下記のコードを記述してください。拡張子を見て分かる通りGulpといえど中身はJavaScriptです。怖がらずにいきましょう。
1 2 3 4 5 |
var gulp = require('gulp'); gulp.task('default', function() { console.log("Hello World!"); }); |
1行目ではgulpを読み込んでいます。
3〜5行目ではgulp.taskというメソッドを使い、「default」という名前のタスクを登録しています。このタスク名は好きに付けることができ、gulpコマンドのオプションでタスク名を指定して実行することが出来ます。
しかし毎回タスク名を指定するのは大変なため、タスク名の指定がない場合に実行されることになっている「default」という名前にしました。
jQuery的にコードの解説すると1行目でjQueryを読み込み、3〜5行目で下記のようなon click
イベントを記述しているようなものです。
1 2 3 |
$('.button').on('click', function() { console.log("Hello World!"); }); |
ただし実行の仕方はクリックではありません。コマンドライン上で動きますので実行もコマンドで行います。
ということでgulpfile.jsを保存して下記のコードでGulpを実行してください。
1 |
npx gulp |
このようにコマンドライン上に「Hello World!」と表示されれば成功です。
1 2 3 4 |
[16:16:46] Using gulpfile ~/hoge/gulpfile.js [16:16:46] Starting 'default'... Hello World! [16:16:46] Finished 'default' after 116 μs |
ではもう少しこのタスクというものに慣れるために「Hello World!」をdefaultタスクではなく、別のタスクとして分けてdefaultタスクからそのタスクを実行する形にしてみましょう。
1 2 3 4 5 6 7 |
var gulp = require('gulp'); gulp.task('default', ['message']); gulp.task('message', function(){ console.log('Hello World!'); }); |
このようにgulp.taskの第二引数に実行したいタスク名を指定することでタスクから更に別のタスクを実行することが出来ます。
配列型になっていることから分かる通り、複数のタスクを指定することが出来ます。
コードを修正したら実行してみてください。
messageタスクとdefaultタスクが実行されていることがわかるかと思います。
1 2 3 4 5 6 |
[16:32:54] Using gulpfile ~/hoge/gulpfile.js [16:32:54] Starting 'message'... Hello World! [16:32:54] Finished 'message' after 107 μs [16:32:54] Starting 'default'... [16:32:54] Finished 'default' after 46 μs |
また、次のようにタスク名を指定することで直接タスクを実行することもできます。
1 |
npx gulp message |
さて、Gulpでのコードの実行に慣れてきた気がします。
では続いてSassをコンパイルするタスクを作成していきましょう。
GulpでSassをコンパイルするタスクを作成する
SassのコンパイルはGulpのプラグインであるgulp-sassで行います。jQueryプラグインのようなものです。
では下記のコマンドでプラグインをインストールしてください。
1 |
npm install -D gulp-sass |
インストールが完了したらgulpfile.jsにsassのタスクを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var gulp = require('gulp'); var sass = require('gulp-sass'); gulp.task('default', ['message', 'sass']); gulp.task('message', function () { console.log('Hello World!'); }); gulp.task('sass', function () { gulp.src('./httpdocs/**/*.scss') .pipe(sass().on('error', sass.logError)) .pipe(gulp.dest('./httpdocs/')); }); |
GulpのプラグインもjQueryプラグインと同じように読み込んで使用します。
2行目でgulp-sassを変数sassに代入し、10〜14行目のsassタスクの中で使用します。
11行目ではgulp.srcメソッドを使用しコンパイルするファイルを参照しています。参照の記述ではワイルドカード(*)を使用してhttpdocsにある.scssファイルすべてを対象にすることが出来ます。
ファイルの参照ができたらjQueryのメソッドチェーンのようにメソッドを続けて記述します。
処理としては「対象ファイルの参照(11行目)」→「参照したファイルへの処理(12行目)」→「処理した結果の出力(13行目)」という流れが基本的なものとなっています。
gulp-sassを使用しているのは12行目だけになります。
このとき12行目は.pipe(sass())
だけでもSassのコンパイルが可能ですが、このままでは後述するファイル監視状態でSassのコンパイルエラーが起きたときにファイル監視状態が停止してしまいますので、.pipe(sass()).on('error', sass.logError))
とした方がよいです。
13行目ではgulp.destメソッドを使用してコンパイルしたファイルの出力フォルダを指定しています。ワイルドカードを使用して不特定のファイルを参照した場合には、このように記述することでpathを維持してそれぞれのフォルダに出力されます。
逆にワイルドカードを使わず明示的にファイルを参照した場合にはgulp.destで指定したフォルダに出力されます。
httpdocs/css/フォルダにscssファイルを作成しgulpを実行してみてください。
1 2 3 4 5 |
#main { .title { font-size: 30px; } } |
同フォルダにcssファイルが出力されていれば成功です。
続いてSource mapを作成してみましょう
GulpでSassのSource mapを作成する
Source mapの作成にはgulp-sourcemapsを使用します。最後に「s」が付きますので間違えないよう注意してください。
1 |
npm install -D gulp-sourcemaps |
gulpfile.jsには次のように記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var gulp = require('gulp'); var sass = require('gulp-sass'); var sourcemaps = require('gulp-sourcemaps'); gulp.task('default', ['message', 'sass']); gulp.task('message', function () { console.log('Hello World!'); }); gulp.task('sass', function () { gulp.src('./httpdocs/**/*.scss') .pipe(sourcemaps.init()) .pipe(sass().on('error', sass.logError)) .pipe(sourcemaps.write()) .pipe(gulp.dest('./httpdocs/')); }); |
13〜15行目に注目してください。sassのコンパイル処理を囲うようにgulp-sourcemapsの記述を行います。
実行するとcssファイルにSource mapが記述されます。
続いてはAutoprefixerを使用してベンダープレフィックスを自動的に付けましょう。
GulpでAutoprefixerを使用してベンダープレフィックスを自動的に付ける
ベンダープレフィックスを自動的に付けるにはgulp-autoprefixerを使用します。
1 |
npm install -D auto-prefixer |
gulpfile.jsは次のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
var gulp = require('gulp'); var sass = require('gulp-sass'); var sourcemaps = require('gulp-sourcemaps'); var autoprefixer = require('gulp-autoprefixer'); gulp.task('default', ['message', 'sass']); gulp.task('message', function () { console.log('Hello World!'); }); gulp.task('sass', function () { gulp.src('./httpdocs/**/*.scss') .pipe(sourcemaps.init()) .pipe(sass().on('error', sass.logError)) .pipe(sourcemaps.write({includeContent: false})) .pipe(sourcemaps.init({loadMaps: true})) .pipe(autoprefixer(['last 3 versions', 'ie >= 8', 'Android >= 4', 'iOS >= 8'])) .pipe(sourcemaps.write()) .pipe(gulp.dest('./httpdocs/')); }); |
sourcemapsが複数登場していますが、このように記述しないとAutoprefixerを使用した際にSource mapの参照が切れてしまうようです。
参考:Problem with gulp-sass ? Or gulp-autoprefixer ? Or gulp-sourcemaps ?
参考:Autoprefixerの対象ブラウザって、どうやって選べばいいの?
GulpでcssファイルのMinifyをする
今回はgulp-sassを使用していますので、outputStyleをcompressedにしてMinifyします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
var gulp = require('gulp'); var sass = require('gulp-sass'); var sourcemaps = require('gulp-sourcemaps'); var autoprefixer = require('gulp-autoprefixer'); gulp.task('default', ['message', 'sass']); gulp.task('message', function () { console.log('Hello World!'); }); gulp.task('sass', function () { gulp.src('./httpdocs/**/*.scss') .pipe(sourcemaps.init()) .pipe(sass({outputStyle: 'compressed'}).on('error', sass.logError)) .pipe(sourcemaps.write({includeContent: false})) .pipe(sourcemaps.init({loadMaps: true})) .pipe(autoprefixer(['last 3 versions', 'ie >= 8', 'Android >= 4', 'iOS >= 8'])) .pipe(sourcemaps.write()) .pipe(gulp.dest('./httpdocs/')); }); |
参考:Different Sass Output Styles
これでSassをコンパイルするときに一緒に実行しておきたい便利な機能も追加できました。
続いてはscssファイルを変更したとき、自動的にsassタスクを実行してコンパイルするようにしてみましょう。
Gulpでファイル状態を監視し変更があったら自動的にSassをコンパイルする
ファイルの監視にはgulp.watchメソッドを使用し、監視対象のファイルの指定と変更があったときに何のタスクを実行するか記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
var gulp = require('gulp'); var sass = require('gulp-sass'); var sourcemaps = require('gulp-sourcemaps'); var autoprefixer = require('gulp-autoprefixer'); gulp.task('default', ['watch', 'sass']); gulp.task('watch', function () { gulp.watch('./httpdocs/**/*.scss', ['sass']); }); gulp.task('sass', function () { gulp.src('./httpdocs/**/*.scss') .pipe(sourcemaps.init()) .pipe(sass({outputStyle: 'compressed'}).on('error', sass.logError)) .pipe(sourcemaps.write({includeContent: false})) .pipe(sourcemaps.init({loadMaps: true})) .pipe(autoprefixer(['last 3 versions', 'ie >= 8', 'Android >= 4', 'iOS >= 8'])) .pipe(sourcemaps.write()) .pipe(gulp.dest('./httpdocs/')); }); |
残していたmessageタスクをwatchタスクに書き換えました。
9行目でgulp.watchを使用し第一引数に監視するファイル、第二引数に変更があったときに実行するタスクを記述します。
npx gulp
を実行するとwatchタスクが実行されます。
watchタスクが実行された場合、これまでとは違ってコマンドラインが監視状態となりコマンドの入力ができなくなります。
この状態でscssファイルを更新すると自動的にSassのコンパイルが行われますので試してみてください。
監視状態から抜け出すにはCtrl+C
かControl+C
を入力します。
おわりに
どうでしょうか。Source mapがAutoprefixerやMinifyとの組み合わせで上手く動かずトリッキーな書き方をしなくてはいけないところ以外、ひとつひとつは簡単だと個人的には思っています。
それこそjQueryとそのプラグインを使うより簡単だと思いますので、Gulpで一気にいろいろなことをしようとせず、とりあえずはSassのコンパイルとついでにとても便利なAutoprefixerを使ってみるところからはじめて見るとよいと思います。