上篇文章我们分别对 gulp 的 .src 和 .dest 两个主要接口做了分析,今天打算把剩下的面纱一起揭开 —— 解析 gulp.task 的源码,了解在 gulp4.0 中是如何管理、处理任务的。

在先前的版本,gulp 使用了 orchestrator 模块来指挥、排序任务,但到了 4.0 则替换为 undertaker 来做统一管理。先前的一些 task 写法会有所改变:

///////旧版写法
gulp.task('uglify', function(){
    return gulp.src(['src/*.js'])
        .pipe(uglify())
        .pipe(gulp.dest('dist'));
});
gulp.task('default', ['uglify']);

///////新版写法1
gulp.task('uglify', function(){
    return gulp.src(['src/*.js'])
        .pipe(uglify())
        .pipe(gulp.dest('dist'));
});
gulp.task('default', gulp.parallel('uglify'));

///////新版写法2
function uglify(){
    return gulp.src(['src/*.js'])
        .pipe(uglify())
        .pipe(gulp.dest('dist'));
}
gulp.task(uglify);
gulp.task('default', gulp.parallel(uglify));

更多变化点,可以参考官方 changelog,或者在后文我们也将透过源码来介绍各 task API 用法。

gulp源码解析(三)—— 任务管理

从 gulp 的入口文件来看,任务相关的接口都是从 undertaker 继承:

var util = require('util');
var Undertaker = require('undertaker');function Gulp() {
  Undertaker.call(this);
this.task = this.task.bind(this);
  this.series = this.series.bind(this);
  this.parallel = this.parallel.bind(this);
  this.registry = this.registry.bind(this);
  this.tree = this.tree.bind(this);
  this.lastRun = this.lastRun.bind(this);
}
util.inherits(Gulp, Undertaker);

接着看 undertaker 的入口文件,发现其代码粒化的很好,每个接口都是单独一个模块:

'use strict';

var inherits = require('util').inherits;
var EventEmitter = require('events').EventEmitter;

var DefaultRegistry = require('undertaker-registry');

var tree = require('./lib/tree');
var task = require('./lib/task');
var series = require('./lib/series');
var lastRun = require('./lib/last-run');
var parallel = require('./lib/parallel');
var registry = require('./lib/registry');
var _getTask = require('./lib/get-task');
var _setTask = require('./lib/set-task');

function Undertaker(customRegistry) {
  EventEmitter.call(this);

  this._registry = new DefaultRegistry();
  if (customRegistry) {
    this.registry(customRegistry);
  }

  this._settle = (process.env.UNDERTAKER_SETTLE === 'true');
}

inherits(Undertaker, EventEmitter);

Undertaker.prototype.tree = tree;
Undertaker.prototype.task = task;
Undertaker.prototype.series = series;
Undertaker.prototype.lastRun = lastRun;
Undertaker.prototype.parallel = parallel;
Undertaker.prototype.registry = registry;
Undertaker.prototype._getTask = _getTask;
Undertaker.prototype._setTask = _setTask;

module.exports = Undertaker;

gulp源码解析(三)—— 任务管理

我们先从构造函数入手,可以知道 undertaker 其实是作为事件触发器(EventEmitter)的子类:

function Undertaker(customRegistry) {
  EventEmitter.call(this);  //super()

  this._registry = new DefaultRegistry();
  if (customRegistry) {
    this.registry(customRegistry);
  }

  this._settle = (process.env.UNDERTAKER_SETTLE === 'true');
}

inherits(Undertaker, EventEmitter);  //继承 EventEmitter

这意味着你可以在它的实例上做事件绑定(.on)和事件触发(.emit)处理。

另外在构造函数中,定义了一个内部属性 _registry 作为寄存器(注册/寄存器模式的实现,提供统一接口来存储和读取 tasks)

  this._registry = new DefaultRegistry();  //undertaker-registry模块
  if (customRegistry) {   //支持自定义寄存器
    this.registry(customRegistry);
  }

寄存器默认为 undertaker-registry 模块的实例,我们后续可以通过其对应接口来存储和获取任务:

// 存储任务(名称+任务方法)
this._registry.set(taskName, taskFunction); 
// 通过任务名称获取对应任务方法
this._registry.get(taskName); 
// 获取存储的全部任务
this._registry.task();  // { taskA : function(){...}, taskB : function(){...} }

undertaker-registry 的源码也简略易懂:

function DefaultRegistry() {
    //对外免 new 处理
    if (this instanceof DefaultRegistry === false) {
        return new DefaultRegistry();
    }
    //初始化任务对象,用于存储任务
    this._tasks = {};
}

// 初始化方法(仅做占位使用)
DefaultRegistry.prototype.init = function init(taker) {};

//返回指定任务方法
DefaultRegistry.prototype.get = function get(name) {
    return this._tasks[name];
};

//保存任务
DefaultRegistry.prototype.set = function set(name, fn) {
    return this._tasks[name] = fn;
};

//获取任务对象
DefaultRegistry.prototype.tasks = function tasks() {
    var self = this;

    //克隆 this._tasks 对象,避免外部修改会对其有影响
    return Object.keys(this._tasks).reduce(function(tasks, name) {
        tasks[name] = self.get(name);
        return tasks;
    }, {});
};

module.exports = DefaultRegistry;
View Code

相关文章:

  • 2021-12-01
  • 2021-11-03
  • 2021-11-26
  • 2022-02-20
  • 2021-06-23
  • 2020-07-28
  • 2021-10-05
猜你喜欢
  • 2021-04-12
  • 2021-05-23
  • 2022-12-23
  • 2022-12-23
  • 2019-11-02
  • 2021-12-23
相关资源
相似解决方案