gulp初体验记录

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

  【什么是gulp】

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

  可以说,gulp和grunt有点类似,但是从书写角度上来说,写grunt的gruntfile就是在写一个配置文件,相对繁琐且起初语义不是很清晰,而写gulp的gulpfile就相当于在写代码一样。再加上流式解决方法,使其配置文件代码结构更清晰,从这一点上来说哪个更好其实也见仁见智,至少我用了gulp之后对这种配置写法觉得更合适自己,也会在之后的项目中尝试替代grunt。

  从gulp和grunt的具体构建上来说,grunt的每一次插件调用,就是一次新的IO操作,也就是:

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

  当项目足够大时,大量的IO操作会使整个构建过程效率极其低下。而gulp采用了一种更高效的构建思想,也就是使用流将各个插件的构建串联起来,也就形成了:

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

  效率的提升很显而易见。

  【gulp的使用】

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

  1、安装gulp命令行工具:npm install -g gulp

  创建test目录,打开test目录,新建一个test1.js文件,再新建一个test2.js文件

  2、在test目录下安装gulp:npm install --save-dev gulp

  3、安装concat工具:npm install gulp-concat

  4、创建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/"))
})

  5、打开命令行输入gulp,敲下回车,就发现在build目录下多出了一个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;
时间: 2024-10-16 21:37:12

gulp初体验记录的相关文章

gulp 初体验

1,全局安装 gulp npm install --global gulp 但是一直无法成功,后来才知被墙了,于是使用了如下命令,安装cnpm npm install -g cnpm --registry=https://registry.npm.taobao.org 最后使用cnpm 安装成功 ,以后就使用cnpm 2,安装项目的开发依赖 cnpm install --save-dev gulp

gulp初体验

项目流程 安装nodejs -> 全局安装gulp -> 项目安装gulp以及gulp插件 -> 配置gulpfile.js -> 运行任务 常用命令简介: node -v 查看node版本npm -v 查看npm版本cd 定位到目录,用法:cd + 路径 :dir 列出文件列表:cls 清空命令提示符窗口内容 安装包npm install <name> [-g] [--save-dev]-g:全局安装.将会安装在C:\Users\Administrator\AppDa

前端工业工具Gulp初体验

1. 全局安装 gulp: npm install --global gulp 2.在项目目录下,用以下命令创建一个基本的package.json文件 npm init 3.安装Gulp npm install --save-dev gulp 4.安装所需插件如: npm install gulp-contrib-uglify --save-dev 5.在项目根目录下创建一个名为 gulpfile.js 的文件: var gulp = require('gulp'); //引入插件 var ug

Net Core平台灵活简单的日志记录框架NLog初体验

Net Core平台灵活简单的日志记录框架NLog初体验 前几天分享的"[Net Core集成Exceptionless分布式日志功能以及全局异常过滤][https://www.cnblogs.com/yilezhu/p/9339017.html]" 有人说比较重量,生产环境部署也比较麻烦.因此就有了今天的这篇文章.如果你的项目(网站或者中小型项目)不是很大,日志量也不多的话可以考虑NLog+Mysql的组合.因为NLog具有高性能,易于使用,易于扩展和灵活配置的特点能够让你快速集成日

erlang 初体验

最近测试了一下 erlang的坑... 如不出意外.... 大家第一眼看到这语法... 心里第一句一定是"我擦.这TM都是啥!!!!!" 没有变量!!! 没有结构体!!! 没有循环!!! 好吧,至少我是这样想的. 找了半天..连个if也不知道怎么写.. 这记录一些基本常识.. -module(module_name)  %%定义模块 括号内的要和文件名相同. -export([fun1/1 fun2/2]) %%这里是导出2个函数对外使用  函数名/参数名. 一个简单的函数定义如下 f

【Spark深入学习 -15】Spark Streaming前奏-Kafka初体验

----本节内容------- 1.Kafka基础概念 1.1 出世背景 1.2 基本原理 1.2.1.前置知识 1.2.2.架构和原理 1.2.3.基本概念 1.2.4.kafka特点 2.Kafka初体验 2.1 环境准备 2.2 Kafka小试牛刀 2.2.1单个broker初体验 2.2.2 多个broker初体验 2.3 Kafka分布式集群构建 2.3.1 Kafka分布式集群构建 2.3.2 Kafka主题创建 2.3.3 生产者生产数据 2.3.4消费者消费数据 2.3.5消息的

Oracle SQL篇(一)null值之初体验

    从我第一次正式的写sql语句到现在,已经超过10年的时间了.我写报表,做统计分析和财务对账,我一点点的接触oracle数据库,并尝试深入了解.这条路,一走就是10年,从充满热情,到开始厌倦,我不知道我还能坚持多久,未来的路,谁知道呢? 也许是该抓紧时间,做一点什么了,我不知道该开始写些什么,我从来没有在网上写东西的习惯.     先从简单的开始吧,那当然就是SQL,这是我SQL系列的第一篇,希望我能够坚持. 在Oracle数据库中,如果一个表中的列没有值的话,我们可以说是空值,比如IT员

SSH初体验系列--Hibetnate--2--crud操作

Ok,今天比较详细的学习一下hibernate的C(create).R(read).U(update).D(delete) 相关api... 前言 Session: 是Hibernate持久化操作的基础,提供了众多的数据库操作方法,如save(),update(),delete()...etc,用于完成对象的增加,修改,删除等方法. 后面代码中使用到的HinernateUtil类:是用于构建SessionFactory(Hibernate提供的获取session的工厂类)的一个封装类,在前面的文

Shell脚本编程初体验

Shell脚本编程初体验 分类 编程技术 通 常,当人们提到"shell脚本语言"时,浮现在他们脑海中是bash,ksh,sh或者其它相类似的linux/unix脚本语言.脚本语言是与计算机 交流的另外一种途径.使用图形化窗口界面(不管是windows还是linux都无所谓)用户可以移动鼠标并点击各种对象,比如按钮.列表.选框等等.但 这种方式在每次用户想要计算机/服务器完成相同任务时(比如说批量转换照片,或者下载新的电影.mp3等)却是十分不方便.要想让所有这些事情变得简单并 且自动