Gulp插件制作指南

我们强烈建议每个开发者遵循本指导规范,没有人喜欢使用差的插件,这些规范会帮助你制作出更加完美的插件。

指南规范

  1. 您的插件不应该做非常容易实现的功能
    • 比如:删除文件目录不需要插件,在任务里面使用del功能就可以了;
    • 不要为了包装而包装,这样可能会降低插件质量;
    • Gulp插件是基于文件的操作,如果你发现自己强制在一个流中处理复杂的操作,请替换为正常的node模块来代替;
    • 一个好的插件实例应该像`gulp-cooffee`一样,`coffee-script` 和`Vinyl`脱离box将无法工作,所以我们将此功能抽象打包为插件使之正常工作;
  2. 您的插件应该只做一件事,并且将之做好
    • 避免配置选项让插件做不同的工作;
    • 例如:一个JS压缩插件不应该有添加header的选项;
  3. 不要重复其他插件的工作
    • 不要实现concat功能,因为已有了gulp-concat插件;
    • 不要实现添加headers功能,因为已有了gulp-header插件;
    • 不要实现添加footers功能,因为已有了gulp-footer插件;
    • 如果它是常见且可选的用例,注明你得插件一般同其他插件使用;
    • 尽量使用现有插件,这将减少你得代码量并且确保生态系统的稳定;
  4. 你得插件必须经过测试
    • 测试gulp插件非常容易,你甚至都不需要gulp去测试它;
    • 多看一下其他插件的例子;
  5. 在`package.json`中添加`gulpplugin`作为关键词,这样搜索的时候才会展示你的插件;
  6. 不要在流里面抛出错误
    • 替而换之,你应该发出一个错误时间;
    • 如果你在流的外面遇到了错误,例如你在创建流的时候发现无效的配置,可以跑出错误;
  7. 以你的插件名字作为错误信息的开头
    • 例如:gulp-replace: Cannot do regexp replace on a stream;
    • 使用`gulp-util`的 PluginError 对象使之更加简单;
  8. `file.contents`类型的文件,自始至终保持一致
    • 如果文件为null或者无法读取,请忽略并继续;
    • 如果文件作为流输入,并且你的插件不支持,请抛出错误;不要缓冲一个流强制塞进插件中与其他流一起工作,这将可能引起严重的问题。
  9. 在做完操作之前,不要进入下一个管道处理。
  10. 克隆一个文件或者基于文件创建新文件的时候,请使用 file.clone() .
  11. 使用推荐模块页面上面的模块将会使你的工作更加简单。
  12. 不要作为依赖来引用 gulp
    • 使用 gulp 测试或者自动化你的插件工作流程非常酷,需要确保将之放在devDependency里
    • 作为依赖引用gulp,意味着安装你的插件还需要安装gulp和它的所有依赖;
    • 一般来说,插件没有任何必要需要依赖gulp,如果你的代码中确实这么做了,请告诉我们来帮助你。

为何规范如此严格?

`gulp`的目标是让开发者使用更加简单,严格的规范会让我们做出更高质量的插件,遵循规范多做一点校工作,就会尽可能减少问题的产生。

如果不遵循规范会导致什么后果?

`npm`对每个人都是开放的,你可以免费做你想做的,这也是规范出现的的原因。不就我们就会在搜索的功能中集成测试工具,如果不能满足规范,将会通过积分制来呈现和排序,人们总是更倾向使用匹配度较高的插件。

好的插件应该看起来是什么样子?

// through2 is a thin wrapper around node transform streams
var through = require('through2');
var gutil = require('gulp-util');
var PluginError = gutil.PluginError;

// Consts
const PLUGIN_NAME = 'gulp-prefixer';

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

// Plugin level function(dealing with files)
function gulpPrefixer(prefixText) {

  if (!prefixText) {
    throw new PluginError(PLUGIN_NAME, 'Missing prefix text!');
  }
  prefixText = new Buffer(prefixText); // allocate ahead of time

  // Creating a stream through which each file will pass
  return through.obj(function(file, enc, cb) {
    if (file.isNull()) {
      // return empty file
      cb(null, file);
    }
    if (file.isBuffer()) {
      file.contents = Buffer.concat([prefixText, file.contents]);
    }
    if (file.isStream()) {
      file.contents = file.contents.pipe(prefixStream(prefixText));
    }

    cb(null, file);

  });

};

// Exporting the plugin main function
module.exports = gulpPrefixer;

发表评论