クイック エンジニアリングブログ

株式会社クイック Web事業企画開発本部のエンジニアリングチームが運営する技術ブログです。

より便利になった gulp 4.0 への移行方法と変更点をまとめました

こんにちは。フロントエンドエンジニアのhikaruです。

直近担当しているリニューアル案件で、過去に作った gulpfile を修正している際に、

ついでに gulp v4 にアップデートしてみよー!

という軽い気持ちでろくに下調べもせずにアップデートしてみたところ、タスクの記述方法の修正が必要だったので、アップデートを考えている方のお役に立てばと思い、遭遇したエラーと対処方法をまとめてみました。

  • gulpfile 修正しなきゃいけないの…?
  • 他のプロジェクトで使ってる gulp のバージョンに影響ないの…?

と思った方もご安心ください(๑•̀ㅂ•́)و✧

他のプロジェクトに影響を与えない & これだけ修正すれば大丈夫!というポイントをお伝えします。

まずは結論から

修正が必要なのは以下3点のみです。

  1. gulp.task の引数の変更
  2. gulp.watch の引数の変更
  3. ローカルの gulp を参照するようにする

1. gulp.task の引数の変更

ローカルに gulp v4 をインストールしてそのまま gulp を実行すると、以下のエラーが出ます。

assert.js:351
    throw err;
    ^

AssertionError [ERR_ASSERTION]: Task function must be specified
    at Gulp.set [as _setTask] (/project/node_modules/undertaker/lib/set-task.js:10:3)
    at Gulp.task (/project/node_modules/undertaker/lib/task.js:13:8)
...

これは gulp.task の引数が 3つから 2つに変更されたため起こるエラーです。

  • v3:gulp.task(name [, deps] [, fn])
  • v4:gulp.task([name,] fn)

Gulp Documentation -gulp.task

依存関係のあるタスクは、gulp v4 で追加された API を使って指定します。

  • gulp.series:タスクを直列処理する
  • gulp.parallel:タスクを並列処理する

Gulp Documentation -gulp.series

たとえば、一度ディレクトリを削除してからビルドを実行したい場合、次のように書き換えます。

gulp v3

gulp.task('sass', ['clean'], function() {
  ...
});

gulp.task('js', ['clean'], function() {
  ...
});

gulp.task('build', ['sass', 'js']);

gulp v4

gulp.task('build',
  gulp.series('clean', // 直列処理
  gulp.parallel('sass', 'js') // 並列処理
));

今までは個別のタスクの引数に依存関係を指定したり、run-sequence などのプラグインを使用する必要がありましたが、標準の API でより直感的に記述できるようになりました。

2. gulp.watch の引数の変更

gulp.watch の引数も以下のように変更されました。

  • v3:gulp.task(glob [, opts], tasks)
  • v4:gulp.task(glob [, opts] [, fn])

Gulp Documentation -gulp.watch

次のように書き換えます。

gulp v3

gulp.watch('src/sass/**/*.scss', ['sass']);

gulp v4

gulp.watch('src/sass/**/*.scss', gulp.task('sass'));

第二引数には gulp.task, gulp.series, gulp.parallel の他、関数名や無名関数をそのまま記述しても大丈夫です。

3. ローカルの gulp を参照するようにする

ここまで修正して gulp を実行すると、以下のエラーが出ます。

    gulpInst.start.apply(gulpInst, toRun);
                   ^

TypeError: Cannot read property 'apply' of undefined
    at /usr/local/lib/node_modules/gulp/bin/gulp.js:129:20
    at internalTickCallback (internal/process/next_tick.js:70:11)
...

グローバルとローカルのバージョンが違うことで出るエラーのようです。

現状 ↓

[14:57:20] CLI version 3.9.1
[14:57:20] Local version 4.0.0

他のプロジェクトの gulpfile も修正が必要になっちゃうなー… どうしたものか… と思い調べていたら、ローカルの gulp を参照する方法がありました(`・ω・´)

package.json に 以下のように定義することで npm run gulp で実行できるようになります。

"scripts": {
  "gulp": "gulp"
}

gulp 公式の導入手順にもグローバルにインストールするようかかれていますが、アップデートの際に他のプロジェクトや環境でのバージョンの違いを考慮する必要があるため、プロジェクト内の node_modules だけで完結させられたほうが便利ですね。

補足1:npm scripts の登録

  • 個別のタスクを実行したいときに、いつもの感じで gulp taskname とコマンドをたたくと、グローバルが参照され上記の TypeError が出てしまうので、デフォルト以外に個別で使うことがあるタスクは npm scripts として設定して npm run taskname で実行できるようにしたほうがよいでしょう。
  • 登録したタスク一覧は npm run で見ることができます。

わたしはこんな感じで設定しました。

package.json

  "scripts": {
    "gulp": "gulp",
    // よく使うタスク
    "watch": "gulp",
    "dev": "gulp build --development",
    "prod": "gulp build --production",
    // たまに個別で使うタスク
    "sass": "gulp sass",
    "js": "gulp js",
    "copy": "gulp copy",
    "image": "gulp image",
    "ejs": "gulp ejs"
  },

補足2:タスクの終了を明示的にする

1〜3 まで修正して npm run gulp を実行したところ、こんなエラーがでました。

[15:14:22] 'default' errored after 14 ms
[15:14:22] The following tasks did notcomplete: server
[15:14:22] Did you forget to signal async completion?

gulp v4 では、タスクの終了を明示的にしないと、タスクが完了せずにそこでエラーとなるようになりました。

タスクが1つであれば、今まで通り return をしてストリームを返すようにすれば解決します。

gulp.task('somename', function() {
  return gulp.src('client/**/*.js')
    .pipe(minify())
    .pipe(gulp.dest('build'));
});

タスクの終了を gulp に明示的に伝えるためには以下の 5つの方法があるようです。

  1. 最後に callback を実行する
  2. streamを返す
  3. promiseを返す
  4. child processを返す
  5. RxJS observableを返す

Gulp Documentation -Async support

公式ドキュメントにサンプルコード付きで解説されています。

まとめ

今回はパパっとアップデートすることが目的だったので、最低限対応が必要なことのみまとめました。

他にも

  • gulp.tree メソッドの追加
  • gulp.registry メソッドの追加
  • gulp.srcgulp.dest のオプションの追加
  • タスクの定義を gulp.task ではなく JavaScript で関数を定義するように記述できるようになった

などさまざまな変更点があるので、気になる方は 公式のAPIドキュメント を見てみてください。

gulp.taskgulp.watch の書き方を見直せば問題なく移行できるので、gulp v4 への移行はそれほど大変じゃない!というお話でした。


\\『明日のはたらくを創る』仲間を募集中!! // 919.jp