stream

极力推荐让你所写的插件支持 stream。这里有一些关于让插件支持 stream 的一些有用信息。

请确保使用处理错误的最佳实践,并且加入一行代码,使得 gulp 能在转换内容的期间在捕获到第一个错误时候正确报出错误。

什么是stream

概念比较复杂,简单的说,它就是我们经常说的“流”,比如“流媒体”“流式文件”。这种文件的特征就是可以“流”式传输,这里用双引号引起来的“流”,就是stream。

那么什么是流式传输呢?就是一个文件不是一次性传输,而是像流水一样,慢慢传,可以分成一段一段的,而这一段一段的东西,我们就可以成为buffer,但是buffer不是stream,buffer只是stream附带了一种东西。

比较典型的是视频,我们看网络视频的时候,不会等到整个视频都缓存到浏览器了才开始观看,而是打开浏览器的时候,视频就已经流式下载,下载到一定的量的时候就可以开始播放。

而在node的体系里,读取文件可以以stream的形式进行读取,读取过程中会产生buffer。除了读,stream还可以被写入。但是stream不是文件本身,而是文件的内容的某种形式,所以只要文件的内容还是以stream的形式存在,那这个文件相当于只有灵魂没有肉体。

使用stream

让我们来实现一个用于在文件头部插入一些文本的插件,这个插件支持 file.contents 所有可能的形式。

var through = require('through2');
var gutil = require('gulp-util');
var PluginError = gutil.PluginError;

// 常量
const PLUGIN_NAME = 'gulp-prefixer';

function prefixStream(prefixText) {
  var stream = through();
  stream.write(prefixText);
  return stream;
}

// 插件级别函数 (处理文件)
function gulpPrefixer(prefixText) {
  if (!prefixText) {
    throw new PluginError(PLUGIN_NAME, 'Missing prefix text!');
  }

  prefixText = new Buffer(prefixText); // 预先分配

  // 创建一个让每个文件通过的 stream 通道
  var stream = through.obj(function(file, enc, cb) {
    if (file.isBuffer()) {
      this.emit('error', new PluginError(PLUGIN_NAME, 'Buffers not supported!'));
      return cb();
    }

    if (file.isStream()) {
      // 定义转换内容的 streamer
      var streamer = prefixStream(prefixText);
      // 从 streamer 中捕获错误,并发出一个 gulp的错误
      streamer.on('error', this.emit.bind(this, 'error'));
      // 开始转换
      file.contents = file.contents.pipe(streamer);
    }

    // 确保文件进去下一个插件
    this.push(file);
    // 告诉 stream 转换工作完成
    cb();
  });

  // 返回文件 stream
  return stream;
}

// 暴露(export)插件的主函数
module.exports = gulpPrefixer;

上面的插件可以像这样使用:

var gulp = require('gulp');
var gulpPrefixer = require('gulp-prefixer');

gulp.src('files/**/*.js', { buffer: false })
  .pipe(gulpPrefixer('prepended string'))
  .pipe(gulp.dest('modified-files'));

一些使用 stream 的插件

  • gulp-svgicons2svgfont

results matching ""

    No results matching ""