精华 【Gulp Tips】gulp流为何流
发布于 1天前 作者 soliury 145 次浏览 来自 分享

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 回复

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

回到顶部