Gulp简明教程

Gulp是前端开发过程中对代码进行构建的工具,合理的使用能大大的提升我们的工作效率。Gulp借鉴了unix的管道的思想(pipe),使用起来更加直观方便。

使用前准备

gulp安装

  1. 由于国内网络问题,通过npm直接安装gulp速度会很慢,所以一般要先设置淘宝景象:

npm --registry https://registry.npm.taobao.org info underscore

  1. 全局安装:

npm install --global gulp

  1. 作为项目的开发依赖(devDependencies)安装:

npm install --save-dev gulp

安装成功后在项目根目录下创建一个名为 gulpfile.js 的文件(设置相关工作流):

var gulp = require('gulp');

gulp.task('default', function() {
    // 将你的默认的任务代码放在这
});

基本函数只有五个:

src方法

gulp.src(globs[, options])    

说明:指定需要处理的源文件的路径

globs:(必填 String or Array)

文件匹配模式(类似正则表达式),用来匹配文件路径,也可以直接指定某个具体文件路径,当有多个匹配模式时,该参数可以为一个数值.

options:(可选 Object) 可选参数

  • options.buffer:是否返回buffer,默认值为true

  • options.read:是否读取该文件,默认为true。如果设置为false,返回的file.content为null,而且不会读取该文件。

  • options.base:指glob开始匹配的任意目录,为后面dest定义输出文件目录

Gulp使用的是node-glob模块来实现其文件匹配功能(node的glob模块允许你使用 * 等符号, 来写一个glob规则,获取匹配对应规则的文件,是一个简化的正折表达式):

  • * 匹配单个路径中的0个或多个字符(不会匹配以.符号开始的字符),而且只会匹配到目录这一层,不会去匹配目录内部的字符

    script/* 匹配script目录下的所有文件和目录,但不会匹配目录内的文件

  • ** 匹配路径中的0个或多个字符,并且可以匹配目录内部字符

    script/** 匹配script目录下的所有文件和目录,会匹配目录下所有文件

  • ? 匹配文件路径中的一个字符(不会匹配路径分隔符)

    script/? 匹配script目录下的是一个字符的文件或者目录

  • [...] 匹配方括号中出现的字符中的任意一个,当方括号中第一个字符为^或!时,则表示不匹配方括号中出现的其他字符中的任意一个

    script/k[0-1].js 匹配script目录下的k0.js和k1.js.
    script/k[!0-1].js 匹配script目录下的以

  • !(pattern|pattern|pattern) 匹配任何与括号中给定的任一模式都不匹配的

    script/!(k0|k2|app) 匹配除了k0,k2,app(包括文件和目录)以外的文件和目录(不会匹配到目录内的文件)

  • *(pattern|pattern|pattern) 匹配括号中给定的任一模式0次或多次或任意组合

    script/*(k|1|2|app)b.js 匹配script目录下k,1,2,app有关组合的任意文件,比如k1b.js,k2b.js,appb.js,kappb.js,app1b.js...等等,pattern也可以一个也不出现,可以匹配b.js

  • +(pattern|pattern|pattern) 匹配括号中给定的任一模式至少1次或任意组合,但pattern至少出现一次

    script/+(k|1|2|app)b.js 规则同上,但与之不同的是,不会匹配b.js

  • ?(pattern|pattern|pattern) 匹配括号中给定的任一模式0次或1次,不会匹配任意组合

    script/?(k|a|s)b.js 匹配script目录下,kb.js,ab.js,sb.js,不会匹配相关组合,同时允许pattern为空,也可以匹配b.js

  • @(pattern|pattern|pattern) 匹配括号中给定的任一模式1次,不会匹配任意组合

    script/?(k|a|s)b.js 规则同上,但不允许pattern为空,不匹配b.js

下面以一系列例子来加深理解:
* 能匹配 a.js,x.y,abc,abc/,但不能匹配a/b.js
*.* 能匹配 a.js,style.css,a.b,x.y
*/*/*.js 能匹配 a/b/c.js,x/y/z.js,不能匹配a/b.js,a/b/c/d.js
** 能匹配 abc,a/b.js,a/b/c.js,x/y/z,x/y/z/a.b,能用来匹配所有的目录和文件
**/*.js 能匹配 foo.js,a/foo.js,a/b/foo.js,a/b/c/foo.js a/**/z 能匹配 a/z,a/b/z,a/b/c/z,a/d/g/h/j/k/z
a/**b/z 能匹配 a/b/z,a/sb/z,但不能匹配a/x/sb/z,因为**只有在规则最后出现才能匹配多级目录
?.js 能匹配 a.js,b.js,c.js
a?? 能匹配 a.b,abc,但不能匹配ab/,因为?不会匹配路径分隔符
[xyz].js 只能匹配 x.js,y.js,z.js,不会匹配xy.js,xyz.js等,整个中括号只代表一个字符
[^xyz].js 能匹配 a.js,b.js,c.js等,不能匹配x.js,y.js,z.js

当有多种匹配模式时可以使用数组

gulp.src(['js/.js','css/.css','*.html']) //使用数组的方式来匹配多种文件

使用数组的方式还有一个好处就是可以很方便的使用排除模式,在数组中的单个匹配模式前加上!即是排除模式,它会在匹配的结果中排除这个匹配,要注意一点的是不能在数组中的第一个元素中使用排除模式

gulp.src([.js,'!b.js']) //匹配所有js文件,但排除掉以b开头的js文件
gulp.src(['!b.js',.js]) //不会排除任何文件,因为排除模式不能出现在数组的第一个元素中

此外,还可以使用展开模式。

展开模式以花括号作为定界符,根据它里面的内容,会展开为多个模式,最后匹配的结果为所有展开的模式相加起来得到的结果。
展开的例子如下:
a{b,c}d 会展开为 abd,acd
a{b,}c 会展开为 abc,ac
a{0..3}d 会展开为 a0d,a1d,a2d,a3d
a{b,c{d,e}f}g 会展开为 abg,acdfg,acefg
a{b,c}d{e,f}g 会展开为 abdeg,acdeg,abdeg,abdfg

gulp.src("script/k{1,2}.js") //会展开匹配script目录下的k1.js,k2.js

gulp.src()方法正是用来获取流的,但要注意这个流里的内容不是原始的文件流,而是一个虚拟文件对象流(Vinyl files)(以stream或者buffer的格式),这个虚拟文件对象中存储着原始文件的路径、文件名、内容等信息

task方法

gulp.task(name[,deps],fn)     

说明:定义一个gulp任务

name:(必填 String)

指定任务的名称

deps:(选填 StringArray)

在任务执行前要执行和完成的任务的数组

fn: (必填 Function)

任务函数

gulp.task('testLess', function () {       
  return gulp.src(['less/style.less'])              
  .pipe(less())              
  .pipe(gulp.dest('./css'))    
})    
gulp.task('minicss', ['testLess'], function () { 
//minicss依赖于testLess任务,minicss一定会在testLess任务后再运行       
  gulp.src(['css/*.css'])            
  .pipe(minifyCss())            
  .pipe(gulp.dest(./dist/css'));    
})        
gulp.task('build', ['css', 'js', 'img']);    

上面代码先指定build任务,它由css、js、imgs三个任务所组成,task build方法会并发执行这三个任务。每个任务都是异步调用,没办法保证 js的执行时间一定是在css任务之后.

异步任务执行(这里目前尚不明白,暂时跳过)

通过task定义的任务,如果满足如下任意一点,即可进行异步任务:

这个方法最主要是指定任务的执行顺序

dest方法

gulp.dest(path[,options])    

说明:dest方法是指定处理后文件输出写入文件,如果目录不存在,将会被新建

path:(必填 string or function)

指定文件输出路径,或者定义函数返回文件输出路径亦可;
options:(选填 Object)
有2个属性cwd,mode

  • options.cwd:(string) 指定写入路径的基准目录,默认是当前目录
  • options.mode:(string) 指定写入文件的权限,默认是0777

这个方法最主要是理解好它传入的路径参数与最终生成的文件关系.生成的文件名是由导入到它的文件流决定的,即使传入一个带有文件名的路径参数,也会把这个文件名当作是目录名。

gulp.dest(path)生成的文件路径是我们传入的path参数后面再加上gulp.src()中有通配符(base的参数)开始出现的那部分路径:

var gulp = require('gulp');    
gulp.src('script/jquery.js')
     .pipe(gulp.dest('dist/foo.js'));    
//最终生成的文件路径为 dist/foo.js/jquery.js,而不是dist/foo.js 

没有通配符出现的情况

gulp.src('script/avalon/avalon.js')
     .pipe(gulp.dest('dist')); 
//最后生成的文件路径为 dist/avalon.js 

有通配符的情况

通配符开始出现的那部分路径为 **/underscore.js
假设匹配到的文件为script/util/underscore.js

gulp.src('script/**/underscore.js')
     .pipe(gulp.dest('dist')); 
//则最后生成的文件路径为 dist/util/underscore.js      

有通配符出现的那部分路径为 *
假设匹配到的文件为script/zepto.js

gulp.src('script/*')
     .pipe(gulp.dest('dist')); 
//则最后生成的文件路径为 dist/zepto.js            

通过指定gulp.src()方法配置参数中的base属性,我们可以更灵活的来改变gulp.dest()生成的文件路径。
当我们没有在gulp.src()方法中配置base属性时,base的默认值为通配符开始出现之前那部分路径,例如:

gulp.src('app/src/**/*.css') //此时base的值为 app/src    

gulp.dest()所生成的文件路径的规则,其实也可以理解成,用我们给gulp.dest()传入的路径替换掉gulp.src()中的base路径,最终得到生成文件的路径。

如下例dest传入值为dist,由于没有设置base值,所以这里的base值默认为app/src,该模式匹配到了文件 app/src/css/normal.css,dest路径对base替换,所以输出路径最终地址为:dist/css/normal.css

gulp.src('app/src/**/*.css')
     .pipe(gulp.dest('dist')) 
//用dist替换掉base路径,最终得到dist/css/normal.css

watch方法

gulp.watch(glob[, opts], tasks) 或
gulp.watch(glob[, opts, cb])    

说明:watch方法用于指定需要监视的文件,一旦这些文件发生变化它总会返回一个 EventEmitter 来发射(emit) change 事件。

glob:(必填 String or Array)

需要处理的源文件匹配符路径

opts:(选填 Object)

可选的配置对象,通常不需要用到

tasks:(必填 Array)

文件变化后要执行的任务

gulp.task('uglify',function(){ //do something });   
gulp.task('reload',function(){ //do something });  
gulp.watch('js/**/*.js',['uglify','reload']);

cb:(选填 Function)

回调函数,代替指定的任务(其中回调函数包含一些基本信息:type为变化类型,path为变化文件路径)

gulp.watch('js/**/*.js', 
    function(event){
        //变化类型added为新增,deleted为删除,changed为改变     
        console.log(event.type);
        //变化的文件的路径
        console.log(event.path);
    }
);

常用插件

gulp-uglify

说明:压缩js代码    
安装:npm install --save-dev gulp-uglify    

gulp-minify-css

说明:压缩css代码    
安装:npm install --save-dev gulp-minify-css    

gulp-minify-html

说明:压缩html文件    
安装:npm install --save-dev gulp-minify-html    

gulp-jshint

说明:用来检查js代码    
安装:npm install --save-dev gulp-jshint    

gulp-concat

说明:把多个文件合并为一个文件,我们可以用它来合并js或css文件等,这样就能减少页面的http请求数了    
安装:npm install --save-dev gulp-concat    

gulp-less

说明:编译less    
安装:npm install --save-dev gulp-less    

gulp-sass

说明:编译sass    
安装:npm install --save-dev gulp-sass    

gulp-imagemin

说明:图片压缩    
安装:npm install --save-dev gulp-imagemin    

gulp-load-plugins

说明:按package.json加载文件    
安装:npm install --save-dev gulp-load-plugins    

gulp-rename

说明:用来重命名文件流中的文件    
安装:npm install --save-dev gulp-rename    

gulp-minify-css

说明:要压缩css文件时可以使用该插件    
安装:npm install --save-dev gulp-minify-css  

gulp-del

说明:删除文件  
安装:npm install --save-dev gulp del
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,440评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,814评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,427评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,710评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,625评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,014评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,511评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,162评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,311评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,262评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,278评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,989评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,583评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,664评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,904评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,274评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,856评论 2 339

推荐阅读更多精彩内容