gulp でディレクトリ構造を維持したコピー
失敗談 & そこから得られた知見の記録。いままで gulp で複数ディレクトリの構造を維持してコピーするとき以下のようにしていた。
var gulp = require( 'gulp' );
gulp.task( 'copy', function() {
gulp.src( 'src/*.html' ).pipe( gulp.dest( 'dest' ) );
gulp.src( 'src/css/**' ).pipe( gulp.dest( 'dest/css' ) );
gulp.src( 'src/js/*.js' ).pipe( gulp.dest( 'dest/js' ) );
} );この処理だと gulp.dest が冗長なうえ同期実行のためにコールバック関数を呼び出す場合も個別に end/error イベントをハンドリングする必要があり面倒だ。それにもかかわらずこうしているのは gulp.src の対象は配列を指定可能だけど gulp.dest は単一であるため。
しかし gulp/API.md を読み直したら gulp.src の options に base というプロパティがあって、これに処理対象のベースとしたいディレクトリを指定すると gulp.dest 上で構成を再現してくれるようだ。よってはじめの処理はこう書ける。
var gulp = require( 'gulp' );
gulp.task( 'copy', function() {
return gulp.src(
[ 'src/*.html', 'src/css/**', 'src/js/*.js' ],
{ base: 'src' }
)
.pipe( gulp.dest( 'dest' ) );
} );src 以下のものを dest へ出力する際に src 時点のディレクトリ構成を維持してくれる。gulp.src のパス指定は非常に柔軟なので、これと base オプションを組み合わせれば単一の gulp.src だけで大抵は十分だろう。コピーを独立した task で定義するときもストリームが単一ならそれを返すだけで同期実行をサポートできて便利だ。
base オプションは gulp API の冒頭あたりで解説されている基本機能なのに見逃していた。はずかしい。