1

若效果不佳,参阅https://www.zybuluo.com/bornkiller/note/32907

前言

前端开发近两年工程化大幅飙升。随着Nodejs大放异彩,静态文件处理不再需要其他语言辅助。主要的两大工具即为基于文件的grunt,基于流的gulp。简单来说,如果需要的只是文件处理,gulp绝对首选。如果是其他依赖于文件的任务管理,例如测试(karmamocha),推荐使用grunt

gulp plugin开发依赖

就插件开发难度而言,gulp远低于grunt。如果你只关注如何处理文件,而不关注细节,那么需要依赖Nodejs Transform stream的实现。可以使用官方推荐的through2,但推荐使用through-gulp。后者是基于前者,为gulp插件编写精简优化重写而来。千万不要使用through,这个包时间久远,长时间没有维护,而且部分mock实现的功能,到nodejs 0.10.x已经原生支持。如果只是想学习如何编写gulp插件,through-gulp更适合。
through-gulp: https://github.com/bornkiller/through-gulp
through2: https://github.com/rvagg/through2.git
through: https://github.com/dominictarr/through

gulp plugin正式开发

// PLUGIN_NAME: sample
var through = require('through-gulp');

function sample() {
  // creating a stream through which each file will pass
  var stream = through(function(file, encoding,callback) {
      // do whatever necessary to process the file 
      if (file.isNull()) {

      }
      if (file.isBuffer()) {

      }
      if (file.isStream()) {

      }
      // just pipe data next, or just do nothing to process file later in flushFunction
      // never forget callback to indicate that the file has been processed.
      this.push(file);
      callback();
    },function(callback) {
      // just pipe data next, just callback to indicate that the stream's over
      this.push(something);
      callback();
    });

  // returning the file stream
  return stream;
};

// exporting the plugin 
module.exports = sample;

then use the plugin with gulp

var gulp = require('gulp');
var sample = require('sample');
gulp.task('sample', function() {
    return gulp.src(['source file'])
        .pipe(sample())
        .pipe(gulp.dest('file destiny'))
});

这个sample是一个plugin的基本模板,通常关注的重点在于此处。

if (file.isBuffer()) {
  //文件处理
}

需要特别注意的是,如果你需要处理的不同文件之间没有任何依赖,在第一个函数函数内部处理完后,进行如下调用,即可将该文件的处理结果传递给下一个插件。这种情况下,可以缺省第二个参数flushFunction

if (file.isBuffer()) {
  // 文件处理
  var data = fileProcess(file);
  // 传递处理后数据给下一个插件
  this.push(data); 
  // 声明该文件处理完毕
  callback();
}

如果需要处理的不同文件之间存在依赖,例如文件合并,需要所有文件全部读完之后再处理,那么第一个参数transformFunction将每次传递进来的数据保存在内存中(绝对不要在这里调用this.push()方法),第二个参数flushFunction统一做处理后,再传递给下一个插件。

// transformFunction
var fileStorage = [];
if (file.isBuffer()) {
  // 文件处理
  var data = fileProcess(file);
  // 保存传递进来的数据
  fileStorage.push(data); 
  // 声明该文件处理完毕
  callback();
}
// flushFunction
function(callback) {
  var result = '';
  var final = null;
  fileStorage.foreach(function(file, key) {
    result += file.contents.toString();
  })
  final = new Buffer(result);
  this.push(final);
  callback();
}

后记

就插件编写的角度而言,through-gulp可以把你从through2晦涩的文档中解救出来,不过有一个不幸的地方,在插件开发的单元测试中,常用的assert-stream是基于through2的,但是不影响大局。近期考虑自己重新实现一个版本,基于through-gulp,目的在于为gulp插件编写降低难度。同时through-gulp目前完全可用,欢迎改造。https://github.com/bornkiller/through-gulp


怀疑真爱的流浪者jason
923 声望62 粉丝

For every single second in life, I want to fight with the monster deep within my heart , and I want to win.........


引用和评论

0 条评论