目前用的业界比较知名的三个前端构建工具:grunt、gulp、fis,自己此前一直都是只在用grunt,fis看过一点,gulp则一直都没注意过,直到最近发现好像用的人越来越多,所以今天也就抽了点时间尝试了一下。

【什么是gulp】

  比较官方的一句话就是:gulp是一种基于流的,代码优于配置的新一代构建工具。

  gulp和grunt有点类似,但是从书写角度上来说,写grunt的gruntfile就是在写一个配置文件,写gulp的gulpfile则如同在写代码一样。

  从gulp和grunt的具体构建上来说,grunt的每一次插件调用,就是一次新的IO操作,当项目足够大时,大量的IO操作会使整个构建过程效率极其低下。而gulp采用了一种更高效的构建思想,也就是使用流将各个插件的构建串联起来,效率的提升很显而易见。

  grunt:开始构建=>读文件=>插件改文件=>写文件=>读文件=>插件改文件=>写文件=>构建完成

  gulp:开始构建=>读文件=>插件改文件=>插件改文件=>写文件=>构建完成

【gulp的使用】

  gulp的使用及其简单,由于网上资料极多,所以此处不过多赘述,用个简单的例子概括即可

  1. 安装gulp命令行工具:npm install -g gulp
  2. 创建test目录,打开test目录,新建一个test1.js文件,再新建一个test2.js文件
  3. 在test目录下安装gulp:npm install --save-dev gulp
  4. 安装concat工具:npm install gulp-concat
  5. 创建gulpfile并写入以下内容
var gulp = require("gulp");
var concat = require("gulp-concat") gulp.task("default" , function(){
console.log("gulp is running") return gulp.src(["test1.js" , "test2.js"])
.pipe(concat("result.js"))
.pipe(gulp.dest("./build/"))
})

  最后打开命令行输入gulp,敲下回车,就发现在build目录下多出了一个合并了test1.js和test2.js的result.js文件,至此就构建完成了,更多的使用可以参考http://www.smashingmagazine.com/2014/06/11/building-with-gulp/

【gulp插件的开发】

  gulp的插件开发没有grunt那么直观,grunt的话,只需注册一个任务,然后就可以通过传进的grunt对象里的files里获取到所有文件的路径以及输出路径,然后就只需要用fs模块获取到这些文件后再进行处理就行了。但是gulp有点不大一样,从它配置文件的写法中就可以看出。

  gulp是采用流式的,使用pipe连通。nodejs中的流有四种,包括Readable可读流,Writable可写流,Duplex双工流以及Transform转换流。这四种流的具体解释可看官方文档:http://nodeapi.ucdok.com/#/api/stream.html

  分析一下下面那段配置文件的代码: 

gulp.src(["test1.js" , "test2.js"]).pipe(concat("result.js")).pipe(gulp.dest("./build/"))

  其中gulp.src(["test1.js" , "test2.js"])是获取文件流,也就是一个可读流,获取到文件流后需要处理这些数据,就会通过pipe方法输入到concat("result.js")中,进行处理,处理完还需要再输送到下一个环节,也就是说concat("result.js")这个方法处理完毕后的返回内容必须要是一个转换流对象,因为转换流对象也是双工的,可读也可写。处理完后再执行pipe(gulp.dest("./build/"))进行写出。用张图来说就是:

也就是说,中间的Transform其实就是我们要实现的插件,而我们的插件需要返回一个转换流对象。

知道了这些,我们就可以开始自己的插件开发了。先建个文件,然后写入以下代码

var fs = require("fs")
var gulputil = require("gulp-util")
var stream = require('stream') module.exports = function(){
var transform;
return transform;
}

  这一块尚未实现任何内容,如果gulp里直接引用也肯定是报错的,先不急,一步一步来,上面中gulp-util是gulp提供的一个工具模块,下面的方法主体中,先把要返回的值写好,我们要返回一个转换流对象,所以,我们得先实例化一个转换流对象,也就是

var transform = new stream.Transform({ objectMode: true });

  其中objectMode参数必须要有,顾名思义:对象模式,只有有了这个参数,transform才是一个面向实现者的转换流对象,否则就是一个面向消费者的一堆buffer块。

  转换流对象有了,那我们如何获得文件流,又如何处理呢?通过nodejs的官方文档找到了关于转换流里的一个方法的一段说明:

  也就是说,我们需要给实例化出来的转换流对象实现一个_transform方法,当数据流传入的时候,就会调用该方法并且传入相关参数。所以添加一段代码:

var file;
transform._transform = function(chunk, encoding, callback){ console.log(chunk.contents) //此处输出传入的文件流,就是一段buffer

     file = chunk;
//可以在这里对文件流内容进行处理
var str = chunk.contents.toString(); //比如这里的str为"hello ${arg}"
str = str.replace('${arg}' , 'gulp')
chunk.contents = new Buffer(str) this.push(chunk) callback();
}

  也就是说,对文件内容的处理就是在这里处理。处理完后通过this.push(chunk)推入到转换流对象中,然后调用callback说明执行完毕。然后我们还可以再实现一个方法_flush

transform._flush = function(cb){
//更改文件输出命名
file.path = file.path.substring(0 , file.path.lastIndexOf("\\"))+"\\newfile.js"; this.push(file) cb()
}

  当写入完毕剩下的数据后调用此函数,比如我们如果想更改文件命名,就可以再此前的_transform方法中把chunk保存一下,然后执行_flush的时候将文件名更改,然后再通过this.push()推入转换流对象,再执行callback结束。

  基本上整个插件开发的架子就是这样,就是处理流数据。

  不过有个问题就是,stream.Transform是在nodejs v0.10版本中才有,所以目前的gulp主流插件中,大部分为了兼容以前的版本,实现转换流用的都是第三方工具,比如through2。但是写法差不多:

var file
var transform = through2.obj(function(chunk, encoding, callback){
console.log(chunk.contents) //此处输出传入的文件流,就是一段buffer file = chunk;
//可以在这里对文件流内容进行处理
var str = chunk.contents.toString(); //比如这里的str为"hello ${arg}"
str = str.replace('${arg}' , 'gulp')
chunk.contents = new Buffer(str) this.push(chunk) callback();
},function(cb){
file.path = file.path.substring(0 , file.path.lastIndexOf("\\"))+"\\newfile.js"; this.push(file) cb()
}) return transform;

gulp初体验记录(简介、插件开发介绍)的更多相关文章

  1. gulp初体验

    项目流程 安装nodejs -> 全局安装gulp -> 项目安装gulp以及gulp插件 -> 配置gulpfile.js -> 运行任务 常用命令简介: node -v 查 ...

  2. gulp 初体验

    1,全局安装 gulp npm install --global gulp 但是一直无法成功,后来才知被墙了,于是使用了如下命令,安装cnpm npm install -g cnpm --regist ...

  3. 前端工业化工具Gulp初体验

    1. 全局安装 gulp: npm install --global gulp 2.在项目目录下,用以下命令创建一个基本的package.json文件 npm init 3.安装Gulp npm in ...

  4. 痞子衡嵌入式:恩智浦机器视觉模块OpenMV-RT那些事(1)- 初体验

    大家好,我是痞子衡,是正经搞技术的痞子.本系列痞子衡给大家介绍的是机器视觉模块OpenMV-RT初体验. 近些年机器视觉应用一直是个很火的方向,想象一下机器如果能长上"眼睛",是不 ...

  5. 痞子衡嵌入式:走进二维码(QR Code)的世界(2)- 初体验(PyQt5.11+MyQR2.3+ZXing+OpenCV4.2.0)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是走进二维码(QR Code)的世界专题之初体验. 接上篇 <走进二维码(QR Code)的世界(1)- 引言> 继续更文,在 ...

  6. 【微服务】Nacos初体验

    SpringCloud - Nacos初体验 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长 ...

  7. PHP初体验

    PHP初体验 提笔写初体验总不知道从何说起,直接聊PHP中的函数.PHP网络技术.数据库操作.PHP模板等感觉又不是初体验.最后还是决定从PHP的面向对象.PHP的魔术方法.PHP的反射.PHP中的异 ...

  8. gulp快速入门&初体验

    前言 一句话先 gulp 是一个可以简单和自动化"管理"前端文件的构建工具 先说我以前的主要工作,我主要是做游戏服务端的,用c++/python,所以我对东西的概念理解难免要套到自 ...

  9. Net Core平台灵活简单的日志记录框架NLog+Mysql组合初体验

    Net Core平台灵活简单的日志记录框架NLog初体验 前几天分享的"[Net Core集成Exceptionless分布式日志功能以及全局异常过滤][https://www.cnblog ...

随机推荐

  1. 读书笔记——Windows核心编程(8)Interlocked系列函数

    先让我们来复习下小学知识 A+B=C//式中A为被加数,B为加数. A-B=C//式中A为被减数,B为减数. 再让我们来明确一个知识点:返回值为void的Windows函数意味着一定会执行成功. -- ...

  2. Linux date命令的用法

    在linux shell编程中,经常用到日期的加减运算以前都是自己通过expr函数计算,很麻烦.其实date命令本身提供了日期的加减运算非常方便. 例如:得到昨天的时间date  --date=&qu ...

  3. How to use python remove the '^M' when copy words from Windows to Linux

    今天帮同事用Python写了一个小工具,实现了在linux下批量文件名和去掉windows 文件到linux过程中产生^M的脚本,代码如下: !/opt/exptools/bin/python imp ...

  4. C++中对象初始化

    在C++中对象要在使用前初始化,永远在使用对象之前先将它初始化. 1.对于无任何成员的内置类型,必须手工完成此事. 例如: int x=0; double d; std::cin>>d; ...

  5. NOIP2010普及组 三国游戏 -SilverN

    #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> usin ...

  6. Golang 实现简单的滚动读取文本更新

    这个小程序要实现的效果,简单地说,就是将目标文件的内容读取输出到终端,并且目标文件并不是静态的,而是随时会添加新的内容.我们的目标就是一旦目标文件添加了新的内容,就把它读取出来并且显示到终端上. 实现 ...

  7. 双向广搜 codevs 3060 抓住那头奶牛

    codevs 3060 抓住那头奶牛 USACO  时间限制: 1 s  空间限制: 16000 KB  题目等级 : 黄金 Gold   题目描述 Description 农夫约翰被告知一头逃跑奶牛 ...

  8. jquery/js特效代码总结(一):tab切换

    jquery实现tab切换: html代码: <ul class="tabs" id="tabs01"> <li><a href= ...

  9. HDU 4782 Beautiful Soup --模拟

    题意: 将一些分散在各行的HTML代码整理成标签树的形式. 解法: 模拟,具体见代码的讲解. 开始没考虑 '\t' .. 代码: #include <iostream> #include ...

  10. ref out 方法参数

    ref out 相似 ref和out两个关键字的作用大致相同,但是有一些微妙但是重要的区别. 两者的行为相似到连编译器都认为这两者不能被重载:public void SampleMethod(out ...