基本规范

你在开发一个gulp插件的时候,最好遵守下面的规范:

  • 你的插件不应该去做一些现有 node 模块已经能很容易做到的事情

    比如:删除一个文件夹并不需要做成一个 gulp 插件,在 task 里使用一个类似 del 这样的插件即可。

    只是为了封装而封装一些的东西进去,这只会增加很多低质量的插件到生态中,这不符合 gulp 的期望。

    gulp 插件都是以文件为基础操作的,如果你发现你正在把一些很复杂的操作塞进 stream 中去,那么,请直接写一个 node 模块就好。

    一个好的 gulp 插件例子像是 gulp-coffee,coffee-script 模块并不能直接和 vinyl 做很好的适配,因此,才去封装它来使用相应的功能,并且将一些比较痛苦的操作抽象出来,做成更简单的 gulp 插件来使用。

  • 你的插件应该只做一件事,并且做好。

    避免使用配置选项,使得你的插件能胜任不同场合的任务。

    比如:一个 JS 压缩插件不应该有一个加头部的选项

  • 你的插件不能去做一些其他插件做的事:

    不应该去拼接,用 gulp-concat 去做

    不应该去增加头部,用 gulp-header 去做

    不应该去增加尾部,用 gulp-footer 去做

    如果是一个常用的可选的操作,那么,请在文档中注明你的插件通常和其他某个插件一起使用

    在你的插件中使用其他的插件,这能大大减少你的代码量,并保证生态系统的稳定。

  • 你的插件必须被测试过

    测试一个插件很简单,你甚至不需要 gulp 就能测试

    参考其他的插件是怎么做的

  • 在 package.json 中增加一个名为 gulpplugin 的关键字,这可以让它能在我们的搜索中出现

  • 不要再 stream 里面抛出错误

    你应该以触发 error 事件来代替

    如果你在 stream 外面遇到错误,比如在创建 stream 时候发现错误的配置选项等,那么你应该抛出它。

  • 错误需要加上以你插件名字作为前缀

    比如: gulp-replace: Cannot do regexp replace on a stream

    使用 gulp-util 的 PluginError 类来完成它

  • file.contents 的类型需要总是在输入输出中保持一致

    如果 file.contents 为空 (不可读) 请将他忽略,并传过去

    如果 file.contents 是一个 stream,但是你不支持,那么请触发一个错误

    不要把 stream 硬转成 buffer 来使你的插件支持 stream,这会引发很严重的问题。

  • 在你处理完成之前,不要将 file 传到下游去

  • 使用 file.clone() 来复制一个文件或者创建另一个以此为基础的文件
  • 使用我们 模块推荐页 上列举的模块来让你的开发更加轻松
  • 不要把 gulp 作为一个依赖

    使用 gulp 来测试你的插件的工作流这的确很酷,但请务必确保你将它放到 devDependency 中

    在你的插件中依赖 gulp,这意味着安装你的插件的用户将会重新安装一遍 gulp 以及所有它所依赖的东西。

    没有任何理由说明你需要将 gulp 写到你的插件代码中去,如果你发现你必须这么做,那么请开一个 issue,我们会帮你解决。

为什么这些指导这么严格?

gulp 的目标是为了让用户觉得简单,通过提供一些严格的指导,我们就能提供一致并且高质量的生态系统给大家。不过,这确实给插件作者增加了一些需要考虑的东西,但是也确保了后面的问题会更少。

如果我不遵守这些,会发生什么?

npm 对每个人来说是免费的,你可以开发任何你想要开发的东西出来,并且不需要遵守这个规定。我们承诺测试机制将会很快建立起来,并且加入我们的插件搜索中。如果你坚持不遵守插件导览,那么这会反应在我们的打分/排名系统上,人们都会更加喜欢去使用一个 "更加 gulp" 的插件。

一个插件大概会是怎么样的?

// through2 是一个对 node 的 transform streams 简单封装
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 通道
  return through.obj(function(file, enc, cb) {
    if (file.isNull()) {
      // 返回空文件
      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);

  });

};

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

以上就是本节的内容。

results matching ""

    No results matching ""