精华 【Gulp Tips】gulp流为何流
发布于 9 年前 作者 soliury 6031 次浏览 最后一次编辑是 8 年前 来自 分享

gulp tips

这个也是系列文章中得一篇。

gulp流为何流

gulp是基于流进行操作的,整个插件都是通过pipe()函数来赋予。gulp插件每次读取和返回都是一个object mode流,使用gulp.src()读取文件时,就会转换成viny File的格式。插件读入viny File objects,然后在输出viny File objects。一般我们叫它transform stream

A “transform” stream is a duplex stream where the output is causally connected in some way to the input, such as a zlib stream or a crypto stream.———node.js doc

transform stream就是一个可读可写duplex stream,好吧,我叫它‘双工’。可以理解为,它不保存数据,只是处理经过的数据。而且gulp就是利用这一点,gulp的插件就是如此作为一个transform stream来处理经过的数据。

vinyl File Content

vinyl通常有三种形式来展现内容:Stream,Buffer,Empty。

一般的插件都支持Buffer,当然最好是两者都支持。但是由于某些操作,例如js压缩等,用stream对content进行操作很困难,因为这个需要对全局的content有个掌握才能进行压缩,不然会出问题的。所以当进行的操作需要对全局有所掌握才能进行的,最好使用Buffer。

vinyl File是怎么样的

最简单的一个例子:

var File = require('vinyl');

var coffeeFile = new File({
  cwd: "/",
  base: "/test/",
  path: "/test/file.coffee",
  contents: new Buffer("test = 123")
});

每个File都有个cwdbasepathcontents属性。当插件进行操作时就是封装成一个transform stream,例如我写的gulp-react-native-css

var through = require("through2"),
	gutil = require("gulp-util"),
	parseCss = require('./lib/parseCss');

var ext = gutil.replaceExtension;

module.exports = function () {
	"use strict";

	function reactNativeCss(file, enc, callback) {
		/*jshint validthis:true*/

		// Do nothing if no contents
		if (file.isNull()) {
			this.push(file);
			return callback();
		}

		if (file.isStream()) {
			// accepting streams is optional
			this.emit("error",
				new gutil.PluginError("gulp-react-native-css", "Stream content is not supported"));
			return callback();
		}

		// check if file.contents is a `Buffer`
		if (file.isBuffer()) {
			var source = file.contents.toString();

			var style = parseCss(source.replace(/\r?\n|\r/g, ""));

			var prefix = "module.exports =";

			file.contents = new Buffer(prefix + style);

			file.path = ext(file.path, '.js');

			this.push(file);

		}
		return callback();
	}

	return through.obj(reactNativeCss);
};

through2这个库实现了对node stream的简单封装,对于生成一个双工的stream很方便。因为gulp采用的是object mode,所以直接调用through.obj()就ok了。而上面的reactNativeCss就作为一个transform函数了。

有关transform stream的知识,可以看node.js stream doc。其中提到:

Rather than implement the _read() and _write() methods, Transform classes must implement the _transform() method, and may optionally also implement the _flush() method. (See below.)

而上面例子中得reactNativeCss就是赋给了_transform。也就是这个函数:transform._transform(chunk, encoding, callback)

1 回复

好吧,既然加精了,那我就继续写了。

回到顶部