【実用 gulp】gulp入門

gulp 入門者向けの gulp を使うために必要な基礎知識を解説します。目標は、gulp を使う準備が整うことです。JavaScript の基本的な知識を前提としています。

gulp とは

gulp は、いわゆるタスクランナーの一種で、予めタスクを登録しておくことで、後から手動または自動でタスクを実行してくれるツールです。

例えば、Sass ファイルを CSS へとコンパイルする場合、一口にコンパイルといってもいろいろなオプションや中間処理が考えられます。そういった一連の処理をタスクとして設定しておくと、コマンド1つで実行することができるようになります。

タスクランナーは他に、Grunt や npm などがありますがありますが、機能が充実していて扱いやすい gulp がおすすめです。

gulp を導入する

gulp を使うには、 Node.js の環境が必要です。ここでは、Node.js がコンピュータにインストールされているという前提で解説を行います。

まず、カレントディレクトリをプロジェクトルートに移動します。

  1. cd my-project

次に、gulp をローカルインストールします。

  1. npm install --save-dev gulp
  1. CLI version: 2.2.0
  2. Local version: 4.0.2

これにより、プロジェクト my-project は、次のような構成になっています。

  1. my-project/
  2. ├─ node-modules/
  3. │ ├─ ...
  4. │ └─ gulp/
  5. ├─ package.json
  6. ├─ package.lock.json
  7. ...

ここで、合わせて gulpfile.js を作成しましょう。gulpgile.js は、gulp で処理を記述するためのファイルです。とりあえずの作成なため、何も記述せずにファイルの作成だけ行ってしまいましょう。

最終的なプロジェクトの構成:

  1. my-project/
  2. ├─ node-modules/
  3. ├─ gulpfile.js
  4. ├─ package.json
  5. ├─ package.lock.json
  6. ...

gulpfile.js

gulp では、gulpfile.js に実行する処理の記述を行っていきます。ファイル名から分かる通り、 JavaScript (Node.js)で記述を行います。

gulp は API が用意されており、API を使って処理内容を定義していきます。

gulpfile.js
  1. // はじめに、gulp オブジェクトをインポートします。API はこのオブジェクトに含まれています。
  2. const gulp = require('gulp');

タスクの定義

JavaScript の関数を使って gulp に処理させるタスクを定義していきます。

gulpfile.js
  1. function task1(callback) {
  2. // ここにタスクの処理を記述
  3. callback();
  4. }

タスクは、非同期で実行されるため、第一引数にコールバックを受け取ります。

タスクにはパブリックなタスクプライベートなタスクがあります。

  • パブリックなタスクは、gulp コマンドで利用できます。タスクは、gulpfile からエクスポートするとパブリックになります。エクスポート名を default とするとデフォルトタスクになります。
  • プライベートなタスクは、内部で series() メソッドまたは parallel() メソッドで利用されます。
gulpfile.js
  1. function publicTask(callback) {
  2. // タスクの処理...
  3. callback();
  4. }
  5.  
  6. function privateTask(callback) {
  7. // タスクの処理...
  8. callback();
  9. }
  10.  
  11. exports.publicTask = publicTask;
  12. exports.default = series(privateTask, publicTask);

gulp コマンドによる実行は次のように行います。

デフォルトタスクの実行
  1. gulp
名前付きタスクの実行
  1. gilp タスク名

タスクの実行(直列)

タスクを直列に実行するには、series() メソッドを使います。

gulpfile.js
  1. // series() メソッドをインポートします。
  2. const { series } = require('gulp');
  3.  
  4. // 「タスクA」を定義
  5. function taskA(callback) {
  6. // タスクAの処理...
  7. callback();
  8. }
  9.  
  10. // 「タスクB」を定義
  11. function taskB(callback) {
  12. // タスクBの処理...
  13. callback();
  14. }
  15.  
  16. // タスクA→タスクBの順に実行されるパブリックな「タスクAB」
  17. exports.taskAB = series(taskA, taskB);

例えば、上記の例に当てはめるなら、タスクAがトランスパイル処理、タスクBがバンドル処理にすれば、タスクABはビルド処理とすることができます。

タスクの実行(並列)

タスクを並列に実行するには、parallel() メソッドを使います。

gulpfile.js
  1. // parallel() メソッドをインポートします。
  2. const { parallel } = require('gulp');
  3.  
  4. // 「タスクA」を定義 function taskA(callback) {
  5. // タスクAの処理...
  6. callback();
  7. }
  8.  
  9. // 「タスクB」を定義
  10. function taskB(callback) {
  11. // タスクBの処理...
  12. callback();
  13. }
  14.  
  15. // タスクAとタスクBを実行するパブリックな「taskAll」
  16. exports.taskAll = parallel(taskA, taskB);

例えば、こちらも上記の例に当てはめるなら、タスクAがJavaScriptトランスパイル処理、タスクBがSassコンパイル処理にすれば、タスクABはプロジェクト全体のトランスパイル・コンパイル処理にかかる時間を短縮できます。

gulp でファイルを読み込むには src() メソッドを使います。書き出しは dest() メソッドを使います

gulpfile.js
  1. const { src, dest } = require('gulp');
  2.  
  3. exports.default = function() {
  4. return src('src/*.js')
  5. .pipe(dest('output/'));
  6. }

この例では、タスクの完了をコールバック関数を呼び出すのではなく、ストリームを返すという方法をとっています。src() メソッドは、ストリームを生成するので、それを pipe() メソッドで引き継いでいます。

グロブ(ワイルドカード)

src() メソッドではグロブ*)が使用できます。グロブはワイルドカードとも呼ばれ、任意の文字列を表します。

ファイルをグロブで表す:

  1. src('src/*.scss')

ディレクトリをグロブで表す:

  1. src('src/*/*.scss')

ディレクトリをグロブで再起的に表す:

src('src/*/.scss')

node_modules/ を除外する:

  1. src(['**/*.js', '!node_modules/**'])

プラグインの利用

gulp プラグインは、パイプラインでファイルを変換する一般的な動作をカプセル化するノード変換ストリームです。難しい言い方をしてしまいましたが、要するに、ファイルの入力と出力の間で使う便利な機能です。gulp は、このプラグインを使うことでかなり便利になります。

ワンポイント
ファイルの入力は src() メソッドで、ファイルの出力は dest() メソッドで、そしてプラグインはその間に挟んで使用します。ストリームを扱うので、コールバック呼び出しではなく return する方法が一般的です。

gulpfile.js
  1. const { src, dest } = require('gulp');
  2.  
  3. // プラグインのインポート
  4. const sass = require('gulp-sass');
  5. exports.sassCompile = function () {
  6. return src('src/scss/style.scss')
  7. .pipe(sass())
  8. .pipe(dest('dist/'));
  9. }

ファイル監視

ファイル監視を行えば、ファイルに変更があった際にタスクを実行できます。ファイル監視は watch() メソッドを使用します。

  1. const { watch, series } = require('gulp');
  2.  
  3. function clean(callback) {
  4. // ...
  5. callback();
  6. }
  7.  
  8. function javascript(callback) {
  9. // ...
  10. callback();
  11. }
  12.  
  13. function css(callback) {
  14. // ...
  15. callback();
  16. }
  17.  
  18. exports.default = function() {
  19. // CSS ファイルを監視
  20. watch('src/*.css', css);
  21. // JS ファイルを監視
  22. watch('src/*.js', series(clean, javascript));
  23. };

特定のイベントを監視する

デフォルトでは、ファイル監視は、ファイルの作成、変更、または削除の度にタスクを実行します。これを変更するには、events オプションにキーワードを指定します。

  1. const { watch } = require('gulp');
  2.  
  3. exports.default = function() {
  4. // All events will be watched
  5. watch('src/*.js', { events: ['add', 'change'] }, function(callback) {
  6. // ...
  7. callback();
  8. });
  9. };

キーワードには、次のものが指定できます。

  • add
  • addDir
  • change
  • unlink
  • unlinkDir
  • ready
  • error
  • all