之前挖了个坑,准备写篇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()内部实现探究》,虽然也只是讲了很小的一部分。

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

  1. 如何编写一个gulp插件

    很久以前,我们在"细说gulp"随笔中,以压缩JavaScript为例,详细地讲解了如何利用gulp来完成前端自动化. 再来短暂回顾下,当时除了借助gulp之外,我们还利用了第三方 ...

  2. chrome插件编写基本入门

    chrome插件编写基本入门  http://igeekbar.com/igeekbar/post/331.htm #精选JAVASCRIPTCHROME 作为一名程序猿,怎么能不会写chrome插件 ...

  3. Gulp资料大全:入门、插件、脚手架、包清单

    awesome-gulp中文版 一份gulp的资源,插件和使用实例清单, 致力于打造更好的前端工程构建流程. 被老外的awesome 清单刺激到,觉得有必要翻译一份,为国产的程序员们做点事情,本清单将 ...

  4. gulp 插件

    原文链接:http://www.mamicode.com/info-detail-517085.html gulp是什么? http://gulpjs.com/ 相信你会明白的! 与著名的构建工具gr ...

  5. 将less编译成css的gulp插件

    简介:gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器:她不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成:使用她,我们不仅可以很愉快的编写代码, ...

  6. 常用 Gulp 插件汇总 —— 基于 Gulp 的前端集成解决方案(三)

    前两篇文章讨论了 Gulp 的安装部署及基本概念,借助于 Gulp 强大的 插件生态 可以完成很多常见的和不常见的任务.本文主要汇总常用的 Gulp 插件及其基本使用,需要读者对 Gulp 有一个基本 ...

  7. jQuery插件编写及链式编程模型小结

    JQuery极大的提高了我们编写JavaScript的效率,让我们可以愉快的编写代码,做出各种特效.大多数情况下,我们都是使用别人开发的JQuery插件,今天我们就来看看如何把我们常用的功能做出JQu ...

  8. gulp.js基础入门

    安装 Node 去 nodejs.org 根据系统选择性按照教程安装Node. 创建项目 创建项目文件夹 进入项目文件夹 初始化项目 使用npm命令:npm init,根据提示完成. 安装 Gulp ...

  9. gulp插件(gulp-jmbuild),用于WEB前端构建

    源码地址:https://github.com/jiamao/gulp-jmbuild https://github.com/jiamao/gulp-jmbuild gulp-jmbuild gulp ...

随机推荐

  1. 三种方法实现java调用Restful接口

    1,基本介绍 Restful接口的调用,前端一般使用ajax调用,后端可以使用的方法比较多, 本次介绍三种: 1.HttpURLConnection实现 2.HttpClient实现 3.Spring ...

  2. 编写脚本-SQL SERVER 用户权限分配

    USE   [TXM];GOCREATE USER  [WIN-JO\Administrator]FOR LOGIN  [WIN-JO\Administrator];GOEXEC sp_addrole ...

  3. django模板系统(上)

    filters 过滤 default 替代作用 filesizeformat 格式化为人类可读 add 给变量加参数 lower 小写 upper 大写 title 标题 ljust 左对齐 rjus ...

  4. Asp.net core 2.0.1 Razor 的使用学习笔记(六)

    Asp.net core 2.0.1 Razor 的使用学习笔记——基本页面的建立 VS这版(vs版本:15.5.6  .net版本:4.7.02558)的Razor页面自动生成就是坑爹货,它自动生成 ...

  5. Geometric Search

    几何搜索 平衡搜索树(BST)在几何方面的应用,处理的内容变成几何对象,像点,矩形. 1d range search 先来看一维的情况,一维的范围搜索是后面的基础,处理的对象是在一条线上的点.这是符号 ...

  6. 详解Web请求中的DNS域名解析

    当我们打开浏览器,输入一个URL去请求我们需要的资源,但是URL是需要解析成对应的IP地址才能与远程主机建立连接,如何将URL解析成IP就是DNS的工作范畴,即使作为开发人员,这个过程我们也感觉不到, ...

  7. 当我们跑SparkSQL时候为了更好地了解SparkSQL运行,可以WEBUI看SQL的Tab

  8. 理解RHEL上安装oracle的配置参数 :/etc/security/limits.conf, /etc/profile, /etc/pam.d/login

    无论安装什么版本的Oracle,在安装之前,都需要配置 /etc/pam.d/login   /etc/profile   /etc/security/limits.conf这三个文件 那这三个文件究 ...

  9. FreeBSD 12.0 版发布

    FreeBSD 是一个自由且开源的类 Unix 操作系统,是 BSD Unix 的直系继承者.起始于 1993 年,FreeBSD 拥有悠久的历史与诸多衍生版本.其饱经考验,是最广泛应用的开源 BSD ...

  10. redis主从搭建

    两台服务器 127.0.0.101 A 主服务器 127.0.0.108 B 从服务器 从服务器设置 1.修改redis.conf 依次修改daemonize no改为daemonize yes  默 ...