Help us understand the problem. What is going on with this article?

Gulp4の変更点と新しい書き方

More than 1 year has passed since last update.

gulpjs公式ブログでもアナウンスされたように、2018年12月にGulp4が正式にリリースされました。Gulp4未満は数ヶ月後から非推奨になるようです。

「Gulp4」で検索すると、それぞれが違う書き方をしていました。この記事ではgulp.jsの公式ドキュメントを参考に、Gulp3からGulp4に移行するための情報をまとめています。

  • gulp.task()が非推奨になり、関数宣言とexportsが推奨になった
  • run-sequenceを使った直列・並列処理を、公式APIのseries()parallel()で実行できるようになった
  • gulp.watch()の第二引数が配列から関数名になった
  • 公式APIにsourcemapsオプションが追加された
  • 公式APIのgulp.lastRun()で差分ビルドができるようになった

gulp.task()が非推奨になり、関数宣言とexportsが推奨になった

Creating Tasksにあるように、関数宣言(function タスク名(){})でプライベートタスクを作成、exportsでパブリックタスクにする書き方へ変わりました。

// 非推奨
gulp.task('task', function() {
  ...
});
gulp.task('task', () => {
  ...
});
// 推奨
function task() { // この時点では`gulp`コマンドで実行不可能
  ...
}
exports.task = task; // `gulp task`で実行可能

Async Completionにあるように、returnを返さない処理の場合はコールバック関数で完了を知らせる必要があります。

基本的なタスクはreturn gulpから始めれば大丈夫です。

// OK
function task() {
  return
    gulp
      .src('')
      .pipe()
      .pipe(
        gulp.dest()
      )
  );
}

browser-syncではreturnを使っていないので、done()というコールバック関数を実行するようにしました(公式ではcb()となっています)。

// OK
function serve(done) {
  browserSync({
    server: {
      baseDir: '',
    },
    ghostMode: false,
    open: 'external',
    notify: false,
  });
  done();
}

run-sequenceを使った直列・並列処理を、公式APIのseries()parallel()で実行できるようになった

直列・並列処理はrun-sequenceをインストールしていましたが、直列をseries()で、並列をparallel()で実行できるようになりました。

// run-sequenceを使った場合
const runSequence = require('run-sequence');
gulp.task('default', function() {
  runSequence(
    ['pug', 'sass', 'js'],
    'server'
    );
});
// `series()`と`parallel()`を使った場合
exports.default = gulp.series(
  gulp.parallel(pug, sass, js),
  server,
);

gulp.watch()の第二引数が配列から関数名になった

Gulp3では、gulp.watch()の第二引数に配列でタスク名を渡していましたが、Gulp4ではタスクの関数を渡すようになりました。

// Gulp3
gulp.watch([''], ['task']);
// Gulp4
gulp.watch('', task);

gulp.seriesfunction()を渡すこともできます。

gulp.watch('', gulp.series(task));
gulp.watch('', gulp.parallel(task));
gulp.watch('', function(done) {
  done();
});

公式APIにsourcemapsオプションが追加された

sourcemapsはgulp-sourcemapsをインストールしていましたが、gulp.src()gulp.dest()optionssourcemapsが追加されました。

// Gulp3
const sourcemaps = require('gulp-sourcemaps');
gulp.task('task', function() {
  gulp.src('')
    .pipe(sourcemaps.init())
    .pipe(sourcemaps.write())
    .pipe(gulp.dest(''));
});
// Gulp4
function task() {
  return gulp
    .src('', {
      sourcemaps: true, // init
    })
    .pipe(dest('',{
      sourcemaps: true, // write
    }));
}

gulp.dest()sourcemaps: trueにするとインラインで、パスを渡すと別ファイルで出力されます。たとえばsourcemaps: '.'とすると、同階層に出力されます。

公式APIのgulp.lastRun()で差分ビルドができるようになった

差分ビルドにはgulp-changedなどをインストールしていましたが、gulp.src()sinceオプションにgulp.lastRun()を渡して実行できるようになりました。

// gulp-changedの場合
const changed = require('gulp-changed');
gulp.task('image', function() {
  return gulp
    .src(src.img)
    .pipe(changed(dest.img)) // `gulp.dest()`のパスを渡す
    .pipe(imagemin())
    .pipe(gulp.dest(dest.img));
);
// `gulp.lastRun()`の場合
function image() {
  return gulp
    .src(src.img, {
      since: lastRun(image) // タスク名を渡す
    })
    .pipe(imagemin())
    .pipe(dest(dest.img));
}

試したときは若干不安定に感じたので、まだ導入はしていません。

名前の衝突に気をつける

書き方が変わって名前の衝突が起こりやすくなっています。

実際にあったのが、browser-syncでの名前の衝突。

// NG
const browserSync = require('browser-sync');
function browserSync(done) { // const browserSyncと衝突している
  browserSync({
    server: {
      baseDir: '',
    },
    ghostMode: false,
    open: 'external',
    notify: false,
  });
  done();
}

browserSyncが衝突していてエラーになりました。

function browserSync(done) {
^

SyntaxError: Identifier 'browserSync' has already been declared

ここではserveというタスク名にすることで回避しました。

// OK
const browserSync = require('browser-sync');
function serve(done) {
  browserSync({
    server: {
      baseDir: '',
    },
    ghostMode: false,
    open: 'external',
    notify: false,
  });
  done();
}

公式ドキュメントで以下のように名前付きインポートをしている箇所があります。

const { src, dest, lastRun, watch } = require('gulp');

const gulp = require('gulp');だとgulp.src()のようにしますが、名前付きインポートを使うとsrc()のようにできます。

ただ、srcdestはパスを変数化するときに使ったり、watchはタスク名に使っていることも多いです。名前付きインポートは使わない方がベターなのかなと思いました。

Gulp4に移行したgulpfile.jsは以下のリンクを参考にしてください。

https://github.com/manabuyasuda/website-template/blob/v4/gulpfile.js

manabuyasuda
Frontend Engineer. Empathize ECSS.
https://github.com/manabuyasuda
tam-tam
TAM はパートナー型デジタルプロダクションです。
http://www.tam-tam.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした