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.series
やfunction()
を渡すこともできます。
gulp.watch('', gulp.series(task));
gulp.watch('', gulp.parallel(task));
gulp.watch('', function(done) {
done();
});
公式APIにsourcemaps
オプションが追加された
sourcemapsはgulp-sourcemapsをインストールしていましたが、gulp.src()
とgulp.dest()
のoptions
にsourcemaps
が追加されました。
// 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
にするとインラインで、パスを渡すと別ファイルで出力されます。たとえばdest
の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()
のようにできます。
ただ、src
・dest
はパスを変数化するときに使ったり、watch
はタスク名に使っていることも多いです。名前付きインポートは使わない方がベターなのかなと思いました。
Gulp4に移行したgulpfile.jsは以下のリンクを参考にしてください。