[gulp4] gulpfileのつまずきアレコレ

初めてgulpfileを書きました。
ググると色々紹介記事が出てきましたが、いろんな書き方があり迷走したので、つまずいたこと、この先またつまずきそうなことのメモです。

##前置き
- gulp4使ってます
- 見出しは、「[関連パッケージ・API]見出し」の形式で書いてます

##[gulp-ejs] 拡張子が変わらないままエクスポートされる
###▶︎ gulp-renameが別途必要！
gulp4からは、gulp-ejsの引数extに拡張子を渡す方法がなくなったらしいです。
参考にしたサイトがgulp3系を使っていた場合、注意です。

```JS:gulpfile
const gulp = require('gulp'); //gulp
const rename = require('gulp-rename'); //名前変更

//NGパターン
function htmlFunc() {
  return gulp
    .src('ejsファイルのパス')
    .pipe(ejs({}, {}, {ext: '.html'})) 
    .pipe(gulp.dest('出力先のパス'));
}

//OKパターン
function htmlFunc() {
  return gulp
    .src('ejsファイルのパス')
    .pipe(ejs())
    .pipe(rename({extname:'.html'})) 
    .pipe(gulp.dest('出力先のパス'));
}
```
参考サイト：[gulp：「gulp-ejs」Ver 4.0.0でファイル出力時の拡張子を変更する方法](https://www.nxworld.net/services-resource/gulp-plugin-gulp-ejs-rename-file-extension.html)

##[autoprefixer] gridレイアウトにプレフィックスがつかない
###▶︎ コードの記載が足りないかも？
gridレイアウトにプレフィックスを自動でつけるには、追加の記載が必要のようです。
flexレイアウト、@support へのプレフィックスは、デフォルトでonになっています。

```JS:gulpfile.js
const postcss = require('gulp-postcss'); //autoprefixerを使うのに必要
const autoprefixer = require('autoprefixer'); //prefixをつける

function stylesFunc() {
  return gulp
    .src('scssファイルのパス')
    .pipe(sass().on('error', sass.logError))
    .pipe(postcss([ autoprefixer({
      grid: 'autoplace', //gridレイアウトのプレフィックスを有効にする
    }) ]))
    .pipe(gulp.dest('出力先のパス');
}
```
参考サイト：[npm autoprefixer](https://www.npmjs.com/package/autoprefixer#features)


##[browser-sync] ブラウザが自動更新されない
###▶︎ ``<body>``をちゃんとhtmlファイルに書く！

ちゃんと``body``タグを書かないと、自動でブラウザ更新してくれないようです。
「まだ作り途中だから...」と、端折ってはいけないのですね...。

参考サイト：[【Gulp】browser-syncのLiveReloadが動かないときの直し方](https://ecmemo.net/gulp-browser-sync-error)

###▶︎ こっちもありかも？リロード用関数を独立させる
全く同じ症状で質問しているstackOverflowのスレッドに、「リロード用の関数は別で作らないとダメみたい」というコメントがついていました。bodyタグあるのに更新されない時は、これを試すのも良さそう。
>There was an issue with my watch function and it seems necessary to have reloading done in a separate function.
引用元： [Page not reloading/autoinjecting with Gulp 4 and Browsersync](https://stackoverflow.com/questions/56203000/page-not-reloading-autoinjecting-with-gulp-4-and-browsersync)

##[watch] 監視下のファイルを削除したら、エクスポート先の同ファイルも消したい
###▶︎ ``.on(eventName, eventHandler)``の形式で書く

[公式ドキュメントのwatchのusage](https://gulpjs.com/docs/en/api/watch#usage)に載ってるこの形式``.watch(globs, [options], [task])`` で書いてたけども、コールバック内でeventやpathが取れずにかなり迷走しました...。（もしかしたら、私の書き方がどこか違うだけなのかも？）

よーく見たら、同じページにやり方書いてあった！
[gulp #chokidar-instance](https://gulpjs.com/docs/en/api/watch#chokidar-instance)

下の例ではこういうことをしています。

- 監視下のファイルに変更またはファイル/フォルダ追加があった場合 → 関数A実行（①）
- 監視下のファイルが削除された場合 → パスの文字列を出力先に置換（②）

```JS:gulpfile.js
const gulp = require('gulp'); //gulp
const del = require('del'); //フォルダやファイルを削除

//NGパターン
//①はうまくいくけど②は ``TypeError: Cannot read property 'replace' of undefined``とエラー
gulp.watch('ファイル取得元のパス', {events: ['change', 'add']}, gulp.series(関数A)); //①
gulp.watch('出力先のパス', {events: 'unlink'},(event, path) => {
  return del(path.replace(/src\/views/, '出力先のパス')); //②
});

//OKパターン
gulp.watch('ファイル取得元のパス')
  .on('all', (event, path) => {
    if (event === 'unlink') {
      return del(path.replace(/src\/views/, '出力先のパス'); //②
    }
    return 関数A; //①
});
```
参考サイト：[gulp #chokidar-instance](https://gulpjs.com/docs/en/api/watch#chokidar-instance)

指定できるイベントの種類は以下の通り。便利！
``add`` / ``addDir`` / ``change`` / ``unlink`` / ``unlinkDir`` / ``ready`` / ``error`` / ``all``



#終わりに
公式ドキュメントって大事...！
参考にさせていただいた記事の執筆者さま、ありがとうございました。

「間違いがあるよ！」「こっちの書き方がいいよ！」など、お気付きの点がありましたらご指摘いただけると嬉しいです...！