blog icon indicating copy to clipboard operation
blog copied to clipboard

比Grunt更好用的前端自动化工具——Gulp

Open pb-cheung opened this issue 9 years ago • 0 comments

比Grunt更好用的前端自动化工具——Gulp

logo

  • 前端构建工具
  • 基于node.js
  • 流式

一、安装

全局安装:

npm install -g gulp

项目目录中安装:

nmp install --save-dev gulp

编辑package.json文件, 或者执行

npm init 

生成package.json,然后执行

npm install

二、API

gulp和插件安装完毕后, 在目录中创建配置文件gulpfile.js。

gulp.src()

指定数据源文件,产生数据流。参数是文件,可以是数组

gulp.src(["js/**/*.js",[!js/**/*.min.js]])

gulp.dest()

将管道的输出写入文件,同事将这些输出继续输出,因此可以多次调用dest方法,将输出写入多个目录。目录不存在则新建。

gulp.task()

用于任务定义。第一个参数是任务名称,第二个参数是任务函数,指定任务具体的操作。

task方法还可以指定按顺序运行的一组任务,例如:

gulp.task("build",["css","js","imgs"]);

上例中,定义一个任务build,执行三个子任务“css”、“js”、“imgs”。这些任务不是同时进行的,不能认为“js”任务结束时“css”任务已经结束。

如果需要确保一个任务在另一个任务结束后执行,可将函数和任务组合结合起来指定依赖关系。例如:

gulp.task("css",["greet"], function(){
    //
});

上例中,定义“css”任务,执行前检查greet任务是否执行完毕,完毕在调用第三个参数定义的函数。

default tasks 执行gulp任务是在命令行中输入:

gulp + taskName

如果不加taskName,就会报“Task ‘default’ is not in your gulpfile”,找不着默认任务。最好在配置文件末,写上默认任务,执行起来比较方便。例如:

gulp.task("scripts",function(){
    //...
});

...

gulp.task("default", ["scripts"]);

gulp.watch()

监听文件的状态,文件发生变化执行某些任务。 用法:

gulp.task("watch",function(){
    gulp.watch("js/src/**/*.js",["copy","concat","uglify"])
})

上例中任务数组可以换成回调函数,

gulp.task("watch",function(){
    gulp.watch("js/src/**/*.js",function(event){
        console.log("Event type: " + event.type + " Event path" + event.path);
    })
})

回调函数中打印事件类型和发生改变文件路径,type值有“added”、“deleted”、“changed”

gulp.watch可配合LiveReload、BrowserSync使用,实现文件修改浏览器立即刷新等功能

三、插件

http://gulpjs.com/plugins/

常用操作 插件名称
文件合并 gulp-concat
文件拷贝 gulp-copy
文件替换 gulp-replace
JS压缩 gulp-uglify
语法检查 gulp-jshint
图片压缩 gulp-imagemin
CSS压缩 gulp-cssmin
添加注释 gulp-wrapper

压缩JS gulp-uglify

https://www.npmjs.com/package/gulp-uglify

举个栗子:

var gulp = require("gulp"),
    uglify = require("gulp-uglify");
gulp.task("uglify",function(){
    gulp.src(["src/common/*.js"])
    .pipe(uglify({
        mangle: {
            except: ["define","require","module","exports"]
        }
    }))
    .pipe(gulp.dest("min/common"))
});

上例中,将src/common/目录下的js进行压缩,压缩文件放到min/common/目录中。参数mangle,可以像上例中那样排除一些关键字以适用sea.js模块管理,或者赋值“false”,在压缩过程中跳过函数名使其不被压缩。

mangle

合并 gulp-concat

https://www.npmjs.com/package/gulp-concat

例子:

var gulp = require("gulp"),
    concat = require("gulp-concat"),
    uglify = require("gulp-uglify");
gulp.task("scripts",function(){
    gulp.src(["src/common/reqData.js","src/common/util.js"])
    .pipe(uglify())
    .pipe(concat("base.min.js",{
        newLine: "\r\n\r\n"
    }))
    .pipe(gulp.dest("min/common"))
});

上例中,将src/common/目录下reqData.js和util.js压缩后合并成一个文件base.min.js,参数的作用是在两个文件之间添加两个换行。

四、Stream

类似于*nix将几乎所有的设备抽象为文件一样,Node将文件访问、输入输出、http连接等几乎所有I/O都抽象成了Stream。

Linux中管道的概念

管道命令的处理示意图

通过管道将stdout导入到stdin。command1的正确输出(stand output)作为command2的输入,然后command2的输出作为command3的输入,command1、2的输出不会显示,command3的运行结果会输出。 可以类比理解。shell中的“|”符号和gulp中的pipe()方法作用相同。

gulp翻译

五、其他高级用法

gulp.env

gulp有个env属性可以接受参数,env属性值对应一个对象:

{ _ : [] }

"_"属性值默认是空,当指定执行任务时,它的值是任务名。 例如:

gulp compress

gulp.env是:

{ _ : ["compress"]}

同理指定多个任务,数组中就有多个值。可以获取这些任务名来执行不同的操作,例如根据任务名不同来修改不同目录

命令行传参

用法:

gulp --key1 value1 --key2 value2

获取方式和上面类似,通过gulp.env

gulp.env: { _ : [], key1: value1, key2: value2 }

针对参数使用举个例子:

var gulp = require("gulp"),
    uglify = require("gulp-uglify"),
    header = require("gulp-header"),
    gutil = require("gulp-util");

var dir = gulp.env.dir ? gulp.env.dir : "common",
    date = (new Date()).getTime();

gulp.task("default",function(){
    gutil.log(gutil.colors.bgGreen("/* ------- 用 法 ------- */"));
    gutil.log(gutil.colors.bgGreen("拷贝:gulp copy --dir [目录名]"));
    gutil.log(gutil.colors.bgGreen("压缩:gulp jsmin --dir [目录名] "));
});

gulp.task("copy",function(){
    return gulp.src("src/" + dir + "/*.js")
    .pipe(header("/* timeStapmp="+ date +" */ \r\n"))
    .pipe(gulp.dest("min/" + dir))
});

gulp.task("jsmin",function(){
    return gulp.src("src/" + dir + "/*.js")
    .pipe(uglify())
    .pipe(header("/* timeStapmp="+ date +" */ \r\n"))
    .pipe(gulp.dest("min/" + dir))
});

执行: 执行结果 上例中,定义了两个任务"copy"和“jsmin”,两个任务都能接受一个参数,这个参数指定操作对应的目录。

六、与Grunt比较

与Grunt对比

比Grunt配置少配置简单、运行速度快

  • 不生成中间文件

Gulp基于node.js的Stream机制。每个插件不能单独使用,依靠组合发挥作用,就像一条流水线,上一道工序的产出交给下一道工序,效率高。 Grunt基于文件,很多操作都要需要生成一些中间文件,这些文件在任务完成后就没用了,需要删掉。文件操作时间消耗多,还有无用文件产生。gulp配置代码量相应的也会少。

  • 配置和运行在一起

变量的声明和使用挨在一起最方便。但是Gruntfile中,配置task和调用一般都离得很远,尤其是配置文件比较大的时候。

  • 插件配置语法基本相同

Grunt的很多插件的配置规则有一定差别,有的看起来还有些怪异。Gulp插件配置规则基本都一样。(插件方法调用,第一个参数是文件,第二个是配置json。)

  • 每个插件只专注于做一件事情

Gulp中每个插件单一职责,每个插件的配置就比较简单。 Grunt中每个插件要配置一坨。

七、参考

Gulp开发教程

gulp plugin 插件介绍

Node中的流

鸟哥 管道命令

Gulp挑战Grunt背后的哲学

gulp传参数 实现定制化执行任务

pb-cheung avatar Nov 18 '15 13:11 pb-cheung