zoukankan      html  css  js  c++  java
  • gulp初体验记录(简介、插件开发介绍)

      目前用的业界比较知名的三个前端构建工具: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;

  • 相关阅读:
    Spring MVC 支持 RESTful 风格编程
    SpringMVC 目标方法返回 json 格式数据
    SpringMVC 文件上传
    使用Eclipse 创建 Maven 项目
    SpringMVC 环境搭建
    SpringMVC运行原理
    Linux(centos)下SVN服务器的搭建及简单配置和使用
    Linux 后台执行脚本命令
    C++入门教程,C++基础教程 更新中...
    Mac开发之HID通讯开发
  • 原文地址:https://www.cnblogs.com/axes/p/4338598.html
Copyright © 2011-2022 走看看