Skip to content

Commit b61e9eb

Browse files
committed
feat(gulp): 仕組みについてを完了
1 parent efd2707 commit b61e9eb

File tree

1 file changed

+63
-7
lines changed

1 file changed

+63
-7
lines changed

ja/gulp/README.md

+63-7
Original file line numberDiff line numberDiff line change
@@ -97,29 +97,32 @@ Transform Streamというものが出てきましたが、Node.jsのStreamは次
9797
そのデータを変更したもの次のStreamに流すということを行っています。
9898

9999
「gulpから流れてきたデータ」を扱うために`readableObjectMode``writableObjectMode`をそれぞれ`true`にしています。
100-
この _ObjectMode_ というのは名前の通り、Streamでオブジェクトが流れるという設定のことです
100+
この _ObjectMode_ というのは名前の通り、Streamでオブジェクトが流すための設定です
101101

102102
通常のNode.js Streamは[Buffer](https://nodejs.org/api/buffer.html "Buffer")というバイナリデータを扱います。
103-
この[Buffer](https://nodejs.org/api/buffer.html "Buffer")は文字列オブジェクトと相互変換が可能ですが、複数の値を持ったオブジェクトを扱うのは少し変更です
103+
この[Buffer](https://nodejs.org/api/buffer.html "Buffer")は文字列オブジェクトと相互変換が可能ですが、複数の値を持ったオブジェクトを扱うのは少し大変です
104104

105105
そのため、Node.js Streamには[Object Mode](https://nodejs.org/api/stream.html#stream_object_mode "Object Mode")があり、
106106
JavaScriptのオブジェクトそのものをStreamで流せるようになっています。
107107

108108
### vinyl
109109

110-
gulpでは[vinyl](https://github.com/gulpjs/vinyl "vinyl")オブジェクトがStreamとして流れてきます
111-
このvinylは _Virtual file format_ というように、データをラップした抽象フォーマットのオブジェクトです
110+
gulpでは[vinyl](https://github.com/gulpjs/vinyl "vinyl")オブジェクトがStreamで流れてきます
111+
このvinylは _Virtual file format_ という呼ばれているもので、ファイル情報と中身をラップしたgulp用の作成された抽象フォーマットです
112112

113113
なぜこういった抽象フォーマットが必要なのかは次のことを考えてみると分かりやすいと思います。
114114

115115
`gulp.src`で読み込んだファイルの中身のみが、Transform Streamに渡されてしまうと、
116116
Transform Streamからはそのファイルのパスや読み取り属性などの詳細な情報を知ることができません。
117+
117118
そのため、`gulp.src`で読み込んだファイルはvinylでラップされ、ファイルの中身は`contents`として参照できるようになっています。
118119

119-
この抽象フォーマットの`contents`はStreamまたはBufferとなっているので、
120-
両方対応する場合は以下のように両方のパターンに対応したコードを書く必要があります。
120+
### vinylの中身を処理する
121+
122+
先ほどのTransform Streamの中身を見てみましょう。
121123

122124
```js
125+
// file は `vinyl` オブジェクト
123126
if (file.isBuffer()) {
124127
file.contents = prefixBuffer(file.contents, prefix);
125128
}
@@ -129,8 +132,61 @@ if (file.isStream()) {
129132
}
130133
```
131134

135+
`vinyl`抽象フォーマットの`contents`プロパティには、読み込んだファイルのBufferまたはStreamが格納されています。
136+
そのため両方のパターンに対応したコードする場合はどちらが来ても問題ないように書く必要があります。
137+
138+
> **NOTE**: gulp pluginは必ずしも両方のパターンに対応しないといけないのではなく、Bufferだけに対応したものも多いです。しかし、その場合にStreamが来た時のErrorイベントを通知することがガイドラインで推奨されています。 - [gulp/guidelines.md at master · gulpjs/gulp](https://github.com/gulpjs/gulp/blob/master/docs/writing-a-plugin/guidelines.md "gulp/guidelines.md at master · gulpjs/gulp")
139+
140+
`contents`にどちらのタイプが格納されているかは、ひとつ前のStreamで決定されます。
141+
142+
```js
143+
gulp.src("./*.*")
144+
.pipe(gulpPrefixer("prefix text"))
145+
.pipe(gulp.dest("build"));
146+
```
147+
148+
この場合は、`gulp.src`により決定されます。
149+
`gulp.src`はデフォルトでは、`contents`にBufferを格納するので、この場合はBufferで処理されることになります。
150+
151+
`gulp.src`はオプションに`{ buffer: false }`を渡すことで`contents`にStreamを流すことも可能です。
152+
153+
```js
154+
gulp.src("./*.*", { buffer: false })
155+
.pipe(gulpPrefixer("prefix text"))
156+
.pipe(gulp.dest("build"));
157+
```
158+
159+
### 変換処理
160+
161+
最後にBufferとStreamのそれぞれの変換処理を見てみます。
162+
163+
```js
164+
export function prefixBuffer(buffer, prefix) {
165+
return Buffer.concat([Buffer(prefix), buffer]);
166+
}
167+
168+
export function prefixStream(prefix) {
169+
return new Transform({
170+
transform: function (chunk, encoding, next) {
171+
// chunkにはBufferが流れてくる
172+
let buffer = prefixBuffer(chunk, prefix);
173+
this.push(buffer);
174+
next();
175+
}
176+
});
177+
}
178+
```
179+
180+
やってみたBufferの先頭に`prefix`の文字列をBufferとして結合して返すだけの処理が行われています。
181+
182+
この変換処理自体は、gulpに依存したものはないため、通常のライブラリに渡して処理するということが可能です。
183+
BufferはStringと相互変換が可能であるため、多くのgulpプラグインと呼ばれるものは、`gulpPrefixer``prefixBuffer`にあたる部分だけを実装しています。
184+
185+
つまり、prefixを付けるといった変換処理自体は、既存のライブラリをそのまま使うことができるようになっています。
186+
187+
132188
- [ ] どういう用途に向いている?
133189
- [ ] どういう用途に向いていない?
134190
- [ ] この仕組みを使っているもの
135191
- [ ] 実装してみよう
136-
- [ ] エコシステム
192+
- [ ] エコシステム

0 commit comments

Comments
 (0)