参考にしたところ:http://horicdesign.com/js/entry-146.html
上記サイト様を見ればほぼ分かります。といっても、gulpfile.jsすらまだまともに書けるか怪しい身としては(ついでに素のnode.jsすらいじったことがない)、through2が一体何をしているのかよく分からなかったので追々調べる。
上記サイトさんだと解説がなかったんで適当に他のプラグインを覗き見したところ、taskからオプションを受け取りたい場合は、module.exportsに入れる関数に引数を設定してやればいいみたい。
ブラウザで動かすようなのと同様に、オブジェクト化して受け取って、||なりなんなりで初期値をセットしてやると使う時に楽。
今回作ったのだと、出力用の拡張子をいじりたくなることが確定しているので、拡張子だけ受け取る。もしかしたら、後々拡張するかもなので、最初からオブジェクトを受けている。
through2.obj()に投げてreturn しないといけない関数 transform(多分、through2とgulpがよしなにしてくれる)はfile, encode, callbackの3引数を取り、それぞれ
- ファイル(入力)のメタと実態
- エンコード
- コールバック
となり、今回わたしが作ったのは例外なんか出ようもないくらいシンプルなリプレース用プラグインだったのであんまり関係ないが、エラーなんかで途中で関数を抜けたりする場合なども必ずcallbackは呼ばないといけない(終了通知となる)。
通常、ファイルを加工して一つのファイルを出力するようなプラグインだと余り関係ないが、through2.obj()の第二引数にも関数オブジェクト(flush)を代入することができ、こちらはファイル単位ではなくてtaskの実行ごと、最後のファイル実行後に呼び出される関数のようで引数はcallbackのみを取る。
例えば、CSSファイルを一つにまとめて最適化する場合やCSS Spriteなどを作成する場合などはファイル単位の処理ではファイルを出力せず(this.push(output_stream)しなければいい)、このflushでまとめてthis.push()する、という形になるんだと思う。
また、あわせて気をつけないといけないのが、transformの中でうっかり、module.exports直下の変数を書き換えてしまうと、スコープの関係でそれ以降のファイル処理に悪影響を与える可能性があるということ。
逆に、flushに残すデータはmodule直下で宣言しておかないと参照できないのでインスタンス変数的な使い方となるようだ。
そこに気をつけておけば、1ファイルずつ加工していく場合は、(テキストファイルが期待される場合は)file.contents.toString()でまず加工しやすい文字列に変換してから好きなように加工して、file.contentsに今度はnew Buffer(StringContents)で内容を戻してやり、拡張子をいじりたい場合などはfile.pathをgulp-utilのreplaceExtension()で加工してから、this.push(file)してやれば以降のチェインにも続いていくし、特に変なことをしなくてもdestが勝手にパスをいじってくれるのでプログラム歴1年生でも色々作れて楽しそうだと思う。
ただnode.jsのテンプレートエンジンやらコンパイラやらのラッパーになってくると、それ自体がファイルを出力したりするのでそういう場合はなにやらちゃんとしてやらないといけない模様(/.tmpに出力されたファイル自体を読み取って、改めてcontentsに入れてpushするなど)。
バイナリファイルの処理はよく分からない(し、するつもりもない)のでひとまずは放置かな。
ちなみに作成したものは、HTMLの特定の書式のコメントを削除し、特定のコメントに囲まれた部分を削除するという、実に簡単なもの。
用途としてはWordpressとかMovableTypeとかその他諸々テンプレートやらなんやら、node.jsでないサーバーで動かすソースの、プレースホルダーと本番環境用のコードを切り替えるというもの。
インデントとか改行とか全く削除しないてきとーっぷりなので、他のプラグインで整理すること前提ですが、モックを組んでからばらしてテンプレート化するのが大嫌いというようなタイプには便利に使ってもらえるんじゃないかと。
npm install gulp-switcher
そのうち使い方(もクソもないが)書きます。