Gulp:插件编写入门

之前挖了个坑,准备写篇gulp插件编写入门的科普文,之后迟迟没有动笔,因为不知道该肿么讲清楚Stream这货,毕竟,gulp插件的实现不像grunt插件的实现那么直观。

好吧,于是决定单刀直入了。文中插件示例可在这里找到:https://github.com/chyingp/gulp-preprocess

写在前面

我们来看看下面的gruntfile,里面用到了笔者刚写的一个gulp插件gulp-preprocess。好吧,npm publish的时候才发现几个月前就被抢注了。为什么星期天晚上在 http://npmjs.org/package/ 上没有搜到 TAT

这个插件基于preprocess这个插件,插件使用方法请自行脑补。本文就讲解下如何实现 gulp-preprocess 这个插件

var gulp = require('gulp'),
    preprocess = require('gulp-preprocess');

gulp.task('default', function() {
    gulp.src('src/index.html')
        .pipe(preprocess({USERNAME:'程序猿小卡'}))
        .pipe(gulp.dest('dest/'));
});

进入实战

关键代码

我们来看下最关键的几行代码。可以看到,上文的 preprocess() 的作用就是返回一个定制的 Object Stream ,这是实现gulp的流式操作必需的,其他gulp插件也大同小异。

gulp-preprocess/index.js

module.exports = function (options) {
    return through.obj(function (file, enc, cb) {
        // 主体实现忽略若干行
    });
};

接着,看下具体实现。实际上代码很短

引入依赖

首先,引入插件的依赖项。其中:

  • gutil:按照gulp的统一规范打印错误日志
  • through2:Node Stream的简单封装,目的是让链式流操作更加简单
  • preprocess:文本预处理器,主要就是文本替换啦
'use strict';
var gutil = require('gulp-util');
var through = require('through2');
var pp = require('preprocess');

核心逻辑

其次,定义gulp-preprocess的主体代码。没错,就是下面这么短的代码。代码结构也比较清晰,下面还是简单做下分解介绍。

module.exports = function (options) {
    return through.obj(function (file, enc, cb) {
        if (file.isNull()) {
            this.push(file);
            return cb();
        }

        if (file.isStream()) {
            this.emit('error', new gutil.PluginError(PLUGIN_NAME, 'Streaming not supported'));
            return cb();
        }

        var content = pp.preprocess(file.contents.toString(), options || {});
        file.contents = new Buffer(content);

        this.push(file);

        cb();
    });
};

核心代码分解

还是直接上代码,在关键位置加上注释。对 through2 不熟悉的童鞋可以参考这里

module.exports = function (options) {
    return through.obj(function (file, enc, cb) {

        // 如果文件为空,不做任何操作,转入下一个操作,即下一个 .pipe()
        if (file.isNull()) {
            this.push(file);
            return cb();
        }

        // 插件不支持对 Stream 对直接操作,跑出异常
        if (file.isStream()) {
            this.emit('error', new gutil.PluginError(PLUGIN_NAME, 'Streaming not supported'));
            return cb();
        }

        // 将文件内容转成字符串,并调用 preprocess 组件进行预处理
        // 然后将处理后的字符串,再转成Buffer形式
        var content = pp.preprocess(file.contents.toString(), options || {});
        file.contents = new Buffer(content);

        // 下面这两句基本是标配啦,可以参考下 through2 的API
        this.push(file);

        cb();
    });
};

写在后面

要把gulp插件内部实现的原理讲透不是件容易的事情,因为实现还是比较复杂的,首先需要对Buffer、Stream 有一定的了解,包括如何通过Node暴露的API对Stream进行定制化。可以参考笔者的另一篇随笔《gulp.src()内部实现探究》,虽然也只是讲了很小的一部分。

时间: 2024-08-30 23:06:02

Gulp:插件编写入门的相关文章

自己动手丰衣足食之征服jQuery插件编写

原文地址:http://www.cnblogs.com/Wayou/p/jquery_plugin_tutorial.html 要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台一样,得平台者得天下.苹果,微软,谷歌等巨头,都有各自的平台及生态圈. 学会使用jQuery并不难,因为它简单易学,并且相信你接触jQuery后肯定也使用或熟悉了不少其插件.如果要将能力上升一个台阶,编写一个属于自己的插件是个不错的选择.

typecho插件编写教程(一):Hello World

  这篇文章主要介绍了typecho插件编写教程(一):Hello World,本文讲解了插件的文件结构.插件信息.插件结构.插件流程等内容,需要的朋友可以参考下 最近老高正在编写一个关于typecho的插件,由于typecho不像wordpress,有那么多的文档参考,写一个插件还是遇到了很多的坑,不过随着研究的不断深入,老高也慢慢上手了,于是总结出此篇编写教程分享给大家! I. 从HelloWorld说起 基本信息 想必想要开发typecho的你一定阅读过官方示例插件HelloWorld的源

typecho插件编写教程(二):写一个新插件

  这篇文章主要介绍了typecho插件编写教程(二):写一个新插件,本文是系列文章的第二篇,需要的朋友可以参考下 第一节我们了解了一个插件的基本构成,下面我们需要一个实例练习巩固. 真赶巧,老高最近正在改版百度sitemap提交插件for typecho,下面和老高一起改版吧! 准备 不知道大家用过WP版的百度结构化插件没?老高就是研究了那个插件,观察其API,然后就写出了typecho版的. 为什么要改版呢? 百度站长最近推出新的接口,使用起来更简单,工作量不算大,索性就改改吧! 新版插件需

typecho插件编写教程(三):保存配置

  这篇文章主要介绍了typecho插件编写教程(三):保存配置,本文讲解了完善方法.如何保存配置.使用需要注意的问题等内容,需要的朋友可以参考下 上一节我们制作了一个裸插件,下面我们开始让我们的插件开始工作! I. 完善方法 两个方法 我们实现activate和deactivate方法 代码如下: public static function activate(){ return 'activate'; } public static function deactivate(){ return

typecho插件编写教程(四):插件挂载

  这篇文章主要介绍了typecho插件编写教程(四):插件挂载,本文讲解了如何找到插件点并挂载插件的方法,需要的朋友可以参考下 终于,在能够保存配置信息后,我们可以开始编写插件的挂载功能了. 首先我们需要知道系统为我们在各个关键的环节都预留了插件点给我们,系统运行到插件点时,会检测到是否有插件挂在这个点上,然后执行插件的逻辑! 插件的工作就是找到合适的插件点,挂上去,然后执行自己的逻辑. 插件点,插件钩子,插件接口...在老高这儿是一个概念 官方的插件接口及功能列表 我们的插件需要执行的逻辑在

typecho插件编写教程(五):核心代码

  这篇文章主要介绍了typecho插件编写教程(五):核心代码,本文讲解了完整的插件核心代码的示例,需要的朋友可以参考下 之前啰嗦了很多,现在开始写核心代码. 分析一下,发布文章的时候,我们需要的信息就是当前文章的URL,我们需要想办法从$contents. $class中拿到他. 目前我们的插件类代码如下(请注意render被我改成了send) 代码如下: class BaiduSubmitTest_Plugin implements Typecho_Plugin_Interface { p

typecho插件编写教程(六):调用接口

  这篇文章主要介绍了typecho插件编写教程(六):调用接口,这是系列文章的最后一篇,需要的朋友可以参考下 此篇我们开始调用接口,我们在插件类中新定义一个方法,起名为send_post,在方法中我们通过系统配置获取接口调用地址. 百度给的例子中使用了php的CURL,更高级的使用方法可以学习PHP_cURL初始化和执行方法 下面我们结合一下百度站长提供的代码. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 2

Jquery插件编写简明教程

 这篇文章主要介绍了Jquery插件编写简明教程,jquery插件开发实例,需要的朋友可以参考下  代码如下: /*  1.jQuery插件文件名推荐命名为 jquery.[插件名].js 以免和其他javascript库插件混淆.例如命名为jquery.color.js  2.所有的对象方法名都应当附加到jQuery.fn对象上而所有的全局函数都应当附加到jQuery对象本身上.  3.在插件内部,this指向的是当前通过选择器获取的jquery对象,而不像一般方法哪样,例如chick()方法

Xcode7 插件制作入门

概述 我们平时也使用了很多的xcode插件,虽然官方对于插件制作没有提供任何支持,但是加载三方的插件,默认还是被允许的.第三方的插件,需要存放在 ~/Library/Application Support/Developer/Shared/Xcode/Plug-ins文件夹中,后缀名必须是.xcplugin (不过其实际上是一种bundle). 所以我们创建一个插件工程,直接创建bundle工程即可,然后通过修改后缀名为.xcplugin,将其放到~/Library/Application Su