【Gulp】插件

2021/11/30 18:17:56

使用 gulp 其实就是将需要的插件组合起来处理文件。

gulp 插件可以通过 BuffersStreams 两种格式处理文件内容。

gulp 插件需要返回一个转换流。

编写 gulp 插件的注意事项open in new window

已有插件

拼接: gulp-concatopen in new window

增加头部:gulp-headeropen in new window

分流处理:gulp-tapopen in new window

gulp-tap 可以在当前文件流中使用其他插件去处理当前文件流。

在一个文件流中对 coffeejs 文件分开处理。

gulp
  .src("src/**/*.{coffee,js}")
  .pipe(
    tap(function (file, t) {
      if (path.extname(file.path) === ".coffee") {
        // 处理 .coffee 文件
        return t.through(coffee, []); // 一参为要处理当前文件的插件,二参为传递给该插件的参数列表
      } else {
        // 处理 .js 文件
      }
    })
  )
  .pipe(gulp.dest("build"));

编写插件

src() 方法的返回值是一个 stream.pipe() 方法中同样需要传入一个 stream

gulp 插件需要返回一个 object modeopen in new window 形式的 transform streams 转换流open in new window用来处理经过插件的文件流。

直接传入 stream

let { src, dest } = require("gulp");
let through = require("through2");
let stream = through.obj(function (file, enc, cb) {
  // 确保文件进入下一个 gulp 插件
  this.push(file);
  // 告诉 stream 引擎,我们已经处理完了这个文件
  cb();
});

function defaultTask() {
  return src("./*.json").pipe(stream).pipe(dest("./json"));
}

exports.default = defaultTask;

判断文件流类型

gulp 插件可以通过 BuffersStreams 两种格式处理文件内容。

如果编写的插件不支持某种格式需要提前判断,避免在插件内进行转换。

.isBuffer() 方法判断文件是否为 buffer 格式。

let stream = through.obj(function (file, enc, cb) {
  if (file.isBuffer()) {
    this.emit("error", new PluginError("type error", "Buffers not supported!"));
    return cb();
  }

  // 确保文件进入下一个 gulp 插件
  this.push(file);

  // 告诉 stream 引擎,我们已经处理完了这个文件
  cb();
});

.isStream() 方法判断文件是否为 stream 格式。

let stream = through.obj(function (file, enc, cb) {
  if (file.isStream()) {
    this.emit("error", new PluginError("type error", "Streams not supported!"));
    return cb();
  }

  // 确保文件进入下一个 gulp 插件
  this.push(file);

  // 告诉 stream 引擎,我们已经处理完了这个文件
  cb();
});

错误处理

stream 外的错误直接抛出,stream 内的错误使用 .emit() 方法触发。

使用 gulp-util/PluginError 模块抛出的错误有更清晰的错误信息。

let { src, dest, series, parallel } = require("gulp");
var gutil = require("gulp-util");
var PluginError = gutil.PluginError;
let through = require("through2");

function gulpPrefixer(prefixText) {
  if (!prefixText) {
    throw new PluginError("pre-fixer", "Missing prefix text!");
  }

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

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

  // 返回文件 stream
  return stream;
}

function defaultTask() {
  return src("./*.json").pipe(gulpPrefixer()).pipe(dest("./json"));
}

exports.default = defaultTask;

对必要步骤的封装

插件有两个必须的步骤:

  • 确保文件进入下一个 gulp 插件 —— this.push(file)

  • 告诉 stream 引擎,我们已经处理完了这个文件 —— cb()

gulp-tap 将该行为封装为 next()方法。

module.exports = function (lambda) {
  return through.obj(
    function (file, enc, cb) {
      next = (function (_this) {
        return function () {
          _this.push(file);
          return cb();
        };
      })(this);
      next();
    },
    function (cb) {
      return cb();
    }
  );
};