Gulp Stream分析

Gulp Stream分析

标签(空格分隔): gulp stream


Gulp一个基于流的前端构建工具,可以通过它定制任务。使用的基本格式如下:

var gulp = require("gulp");

// 一个task内部实现
gulp.task("test", function(){
    return gulp.src(String | [])
        .pipe(someHandler)
        .pipe(someOtherHandler)
        .pipe(gulp.dest(String));
});

此处我为了简便起见,列举了一个task任务,着重强调task内部实现。
由上述代码,我们看出,gulp通过gulp.src,加载一个Stream,然后通过通过gulp.pipe方法注入一个类似于管道的处理函数(为什么是类似于管道?后续讨论),最后将Stream交由gulp.dest生成的类似管道处理。

下面我们对gulp的执行流程做一个简单的介绍。

流程简介

我们以通过控制台输入gulp命令为例,输入gulp taskName,然后按下回车,系统执行流程如下:

  1. 识别命令,分析task列表,解析输入参数;
  2. 编译gulpfile,注册task任务,加载相关模块;
  3. 根据task列表匹配已经注册的任务,如果存在不匹配的情况,则抛出异常;否则执行第4步;
  4. 按照任务列表执行,各任务之间均是异步执行,默认情况下,所指定的任务并不是串行的。
  5. 执行指定的任务,如上文所说的test,调用task对应的函数。
  6. 通过gulp.src生成一个Stream,并且将所匹配的文件以vinyl实例的形式加入到流中。
  7. 注册并pipe,每个pipe中的传入参数均为一个Transform Stream

分析到这里,出现了两个概念,一个是Vinyl File,另外一个是Transform Stream,他们是什么呢?

Vinyl

” Vinyl is a very simple metadata object that describes a file. When you think of a file, two attributes come to mind: path and contents. These are the main attributes on a Vinyl object. A file does not necessarily represent something on your computer’s file system. You have files on S3, FTP, Dropbox, Box, CloudThingly.io and other services. Vinyl can be used to describe files from all of these sources. ”
大致意思为:Vinyl是一个文件的描述对象,包含两个基本属性path和contents。它是文件的抽象表现,可以用之表述为任何形式的文件对象,如操作系统文件、网络文件等等。

从上可以看出,Vinyl两个基本属性:
path
文件的绝对路径
contents
文件的内容,支持Buffer和Stream,也允许为空(null)
除此之外,还提供了一些便利的API,具体请参考Vinyl

Transform Stream

Transform Stream,如字面意思,它是一个转换流,将输入chunk进行转换。
Transform包括两个核心方法:
transform
function(chunk, encoding, callback),转换函数,转换成功后调用callback function(err, chunk),chunk是例如:

var {Transform, Readable} = require("stream");

class MyReader extends Readable {
    constructor(options){
        var op = options || {};
        super(op);
        this._index = typeof op.index === "number" ? op.index : 1;
        this._max = typeof op.max === "number" ? op.max : 100;
        this._start = this._index;
    }
    _read(){
        if(this._start > this._max){
            this.push(null);
        }
        else{
            this.push(Buffer.from("index" + this._start);
        }
        this._start ++;
    }
}

var transform = new Transform({
    transform: function(chunk, encoding, callback){
        // 执行一些逻辑,执行完之后必须调用callback
        console.info(chunk)
        // callback 参数第一个为err,如果没有抛出异常,则至null
        callback(null, chunk);
    }, 
    flush: function(callback){
        console.info("end");
        callback(null);
    }
});

var reader = new MyReader({
    index: 1,
    max: 10
})
reader.pipe(transform)

注意事项

  • 在Transform处理函数中运行往Stream新增chunk,通过this.push(chunk, encoding)实现.
  • 通过push的chunk,在本次transform中不会被处理,而是会被接下来的pipe的transform处理。

flush
function(callback),指定flush操作,处理完成之后调用callback。

流的处理流程

介绍了基本概念,再回到gulp的处理流程上来,gulp最主要是流的处理。
此处输入图片的描述
Stream有三个状态,初始态、暂停态和读入态。
* 初始态,对应_readableState.flowing = null,通过以下方式即可进入读入态;
1) 注册data事件on("data")
2) 调用read()方法
3) 调用pipe()方法,添加一个管道接收器(pipe destination)。
* 暂停态,对应_readableState.flowing = false, 通过以下方式可以进入读入态;
1) 注册data事件on("data")
2) 调用resume()方法
3) 调用pipe()方法,添加一个管道接收器(pipe destination)。
* 读入态,对应_readableState.flowing = true,一旦从初始态进入读入态,不可再恢复为初始态,暂停态和读入态可以互转。通过以下方式可以进入暂停态;
1) 如果没有管道接收器(pipe destination),则调用pause()方法。
2) 如果添加了管道接收器(pipe destination),则需要移除所有的data事件处理函数和所有的管道处理器(pipe destination)。

由此可见,gulp通过pipe方法注册了一系列管道接收器(pipe destination),stream也由初始态进入可读态。

未完待续。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值