いいとこすぎて移住しちゃいました / LAMP壱岐
いいとこすぎて移住しちゃいました / LAMP壱岐
2016.09.16
#17
それいけ!フロントエンド

リリース間近??より便利になったgulp 4.0の変更点と移行へのポイントを紹介します!

いなば

こんにちは、フロントエンドエンジニアのいなばです。

今回は、案件で使っているgulpをv4.0にあげてみたので、その主要な変更点をいくつかご紹介したいと思います。

インストール方法

gulp 4.0の正式リリースはまだなので、下記のコマンドを叩いて直接gitリポジトリからgulpをインストールします。

npm install git://github.com/gulpjs/gulp.git#4.0 --save-dev

今回はお試しなのでローカルにインストールしています。

バージョンアップ後の大きな変更点

本稿では、変更点の中で主要な4点をピックアップしてご紹介します。

  1. タスクに渡す関数の制約
  2. gulp.taskの引数
  3. 直列/並列の処理
  4. gulp.watchの引数

そのほかの変更点はこちらで確認することができます。

1. タスクに渡す関数の制約

Gulp v4 requires a stream, promise, event emitter, child process or observable to be returned from a function or task.

gulp 4.0では、gulp.taskに渡す関数に制約があり、

  • 最後にcallbackを実行する
  • streamを返す
  • Promiseを返す
  • child processを返す
  • Rx.Observableを返す

のいずれかでないと、タスクが完了せずにそこでエラーとなるようになりました。

 

{
    /* 省略 */
    "scripts": {
        "gulp.a": "gulp a"    // 追記
    },
    /* 省略 */
    "devDependencies": {
        "gulp": "github:gulpjs/gulp#4.0"
    }
}

今回はローカルにインストールしたgulp 4.0を使いたいので、npm run scriptsから実行できるようにするためpackage.jsonに上記のように追記します。

 

まずはgulpfileにタスクを登録して実行してみましょう。

"use strict";
const gulp = require('gulp');

// a タスクを登録
gulp.task('a', () => {
    console.log('task:a done');
});

↑ gulpfile.js

 

$ npm run gulp.a

それでは、さっそく登録した aタスク を実行してみます。

 

$ npm run gulp.a

> gulp-v4-sample@1.0.0 gulp.a /Users/inaba_satoshi/Documents/github/gulp-v4-sample
> gulp a

[11:29:37] Using gulpfile ~/Documents/github/gulp-v4-sample/gulpfile.js
[11:29:37] Starting 'a'...
task:a done
[11:29:37] The following tasks did not complete: a
[11:29:37] Did you forget to signal async completion?

実行してみるとThe following tasks did not complete: aというエラーが出て終了する結果となりました。

 

gulp.task('a', (done) => {
    console.log('task:a done');
    done();    // タスク内の処理が完了したタイミングでcallbackを呼ぶ
});

先ほどの例では、taskに渡した関数の引数からcallbackをとり、処理が完了したタイミングでcallbackを呼ぶことで、タスクが正常に終了するようになります。

 

scssをコンパイルするタスクの例

下記の例では、taskがstreamを返すため今までどおりscssのコンパイルを行うことができます(実はこのタスクはgulp 3.0で使ってたものそのままなのですが、すんなり実行できています)。

"use strict";

const gulp = require('gulp');    // v4
const sass = require('gulp-sass');
const plumber = require('gulp-plumber');
const notify = require('gulp-notify');
const browser = require('browser-sync');
const config = {
    path: {
        sass: {
            src: 'src/sass/**/*.scss',
            dest: 'dist/css'
        }
    }
}

gulp.task('style', () => {
    return gulp.src(config.path.sass.src)
        .pipe(plumber({errorHandler: notify.onError('<%= error.message %>')}))
        .pipe(sass())
        .pipe(gulp.dest(config.path.sass.dest))
        .pipe(browser.stream());
});

The following tasks did not complete: {タスク名} とエラーが出たときは、タスクの戻り値、もしくは処理の完了時にcallbackを呼んでいるかを確認しましょう。

2. gulp.taskの引数が変わった

gulp.taskは、これまで最大3つの引数を取ることができましたが、4.0では最大で2つとなりました。

タスクの依存関係

いままでは、タスク名の後にタスク名の文字列、またはタスク名が入った配列を渡すことで、タスクの依存関係を指定することができました。

 

gulp.task('default', ['a', 'b', 'c'], () => {
    // タスクをaからcまで直列に実行した後に処理を行う
});

しかし、4.0では引数を3つとらなくなったため、上記のタスクを実行することができません

 

gulp.task('default', gulp.series('a', 'b', 'c', (done) => {
    // タスクをaからcまで直列に実行した後に処理を行う
    done();
}));

代わりに、直列/並列の処理を扱うためのgulp.seriesgulp.parallel関数が新たに追加されました。

 

3. 直列/並列の処理

先ほど紹介したgulp.seriesとgulp.parallelを使うことで、今までrunSequenceを使って行っていた直列/並列の処理がgulpのみで完結できるようになります。

// aタスクの実行を待ってbとcを並列に実行、bとcの完了を待つ
gulp.task('default', (callback) => {
    return runSequence('a', ['b', 'c'], callback);
});

gulp 3.0までは上記のように並列/直列の制御をおこなっていたものが……、

 

// aタスクの実行を待ってbとcを並列に実行、bとcの完了を待つ
gulp.task('default', gulp.series('a', gulp.parallel('b', 'c'), (done) => {
    done();
}));

gulp 4.0ではこうなります。

直列でタスクの実行はgulp.seriesで指定、並列でタスクの実行はgulp.parallelで行うことができます。

 

しつこいですが、The following tasks did not complete: {タスク名} とエラーが出た時はタスクの戻り値、もしくは処理の完了時にcallbackを呼んでいるか を再度確認しましょう。

4. gulp.watchの引数も変わった

gulp.task('watch', () => {
    gulp.watch(config.path.sass.src, 'style');
});

今までは、watch関数の第二引数にタスク名の文字列、またはタスク名が入った配列を渡すことでタスクを実行させることができていましたが……、

 

gulp.task('watch', () => {
    gulp.watch(config.path.sass.src, gulp.parallel('style'));
});

gulp 4.0では、タスクを実行する関数を引数にとるように変更されました。

 

scssファイルを監視するタスクの例

また、gulp 4.0のwatchタスクは実行後のファイル追加や削除にも反応してくれるように改善されています。

"use strict";

const gulp = require('gulp');
const sass = require('gulp-sass');
const config = {
    path: {
        sass: {
            src: 'src/sass/**/*.scss',
            dest: 'dist/css'
        }
    }
};
gulp.task('style', () => {
    return gulp.src(config.path.sass.src)
        .pipe(sass())
        .pipe(gulp.dest(config.path.sass.dest));
});

gulp.task('watch', () => {
    gulp.watch(config.path.sass.src, gulp.parallel('style'));
});

const defaultTasks = gulp.series('watch');
gulp.task('default', defaultTasks);

終わりに

いかがでしたでしょうか。

実際にgulp 4.0への移行作業をしてみたところ、タスクに渡す関数の戻り値の部分と、直列/並列の部分の書き換えでほぼほぼ終わるので、思っていたよりもすんなりと移行することができました。