学习Gulp的使用

简介

Gulp中文网
Gulp是一个构建系统,通过执行相应的任务,可以让我们加快前端开发的速度。使用它,我们可以实现压缩文件、js校验、编译预处理css和刷新浏览器等功能。

使用步骤

  1. 全局安装gulp

    1
    npm install gulp -g
  2. 作为项目的开发依赖安装

新建文件夹,再npm init生成package.json文件,然后安装gulp

1
npm install gulp --save-dev
  1. 创建gulpfile.js文件

在项目根目录下创建gulpfile.js文件

  1. 运行

打开命令行窗口,执行命令gulp

API

学习gulp,我们首先主要掌握四个API:gulp.src(),gulp.dest(),gulp.task(),gulp.watch()

Gulp的工作方式是基于流的,大概流程就是你先通过gulp.src()获得相应文件,然后逐步使用pipe()来处理文件,最后用gulp.dest()来指定一个文件夹来存放处理过的文件。

gulp.src()

gulp.src()是用来获取文件的。

1
gulp.src(globs[, options])

globs参数是文件匹配模式(类似正则表达式),用来匹配文件路径(包括文件名)。当有多个匹配模式时,该参数可以为一个数组。
options为可选参数。通常情况下我们不需要用到。

下面我们了解一下glob的具体使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
* 匹配文件路径中的0个或多个字符,但不会匹配路径分隔符,除非路径分隔符出现在末尾
例子:
*能匹配a.js,x.y,abc,abc/,但不能匹配a/b.js;
*.*能匹配a.js,style.css,a.b,x.y

** 匹配路径中的0个或多个目录及其子目录,需要单独出现,即它左右不能有其他东西了。如果出现在末尾,也能匹配文件
例子:
**能匹配abc,a/b.js,a/b/c.js,x/y/z,x/y/z/a.b,能用来匹配所有的目录和文件;
**/*.js能匹配x.js,a/x.js,a/b/x.js,a/b/c/x.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

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

1
gulp.src(['js/*.js','css/*.css','html/*.html'])

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

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

gulp.dest()

gulp.dest()方法是用来写文件的。

1
gulp.dest(path[,options])

gulp.dest()传入的路径参数,只能用来指定要生成的文件的目录,而不能指定生成文件的文件名,它生成文件的文件名使用的是导入到它的文件流自身的文件名,所以生成的文件名是由导入到它的文件流决定的,即使我们给它传入一个带有文件名的路径参数,然后它也会把这个文件名当做是目录名,例如:

1
2
3
4
var gulp = require('gulp');
gulp.src('script/b.js')
.pipe(gulp.dest('dist/a.js'));
//最终生成的文件路径为 dist/a.js/b.js,而不是dist/a.js

options参数我们通常配置base,base的默认值为通配符开始出现之前那部分路径,比如

1
2
a/**/*.js //此时base会替换a
a/b/*.js //此时base会替换a/b

但如果我们设置了自定义参数,就会替换自定义路径。
例子:

1
2
3
4
5
6
7
gulp.src(script/lib/*.js) //没有配置base参数,此时默认的base路径为script/lib
//假设匹配到的文件为script/lib/a.js
.pipe(gulp.dest('build')) //生成的文件路径为 build/a.js

gulp.src(script/lib/*.js, {base:'script'}) //配置了base参数,此时base路径为script
//假设匹配到的文件为script/lib/a.js
.pipe(gulp.dest('build')) //此时生成的文件路径为 build/lib/a.js

用gulp.dest()把文件流写入文件后,文件流仍然可以继续使用。

gulp.task()

gulp.task()是用来定义任务的。

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

如果我们要执行对应的任务,我们可以在命令行窗口执行gulp taskName。也可以在webstorm可以直接执行。
name任务名;
deps是当前定义的任务需要依赖的其他任务,为一个数组。当前定义的任务会在所有依赖的任务执行完毕后才开始执行。如果没有依赖,则可省略这个参数;
fn为任务函数,我们把任务要执行的代码都写在里面。该参数也是可选的。

1
2
3
gulp.task('lastTask', ['firstTask', 'secondTask', 'thirdTask', 'forthTask'], function() { 
// Do something
});

如果我们定义任务名为default,我们可以直接执行gulp,而不用添加任务名就可以了。

gulp.watch()

gulp.watch()用来监视文件的变化。如果文件发生变化,我们就可以执行相应的任务。

1
gulp.watch(glob[, opts], tasks)

glob为要监视的文件匹配模式,规则和用法与gulp.src()方法中的glob相同。
opts为一个可选的配置对象,通常不需要用到
tasks为文件变化后要执行的任务,为一个数组

1
2
3
4
5
6
7
gulp.task('one',function(){
//do something
});
gulp.task('two',function(){
//do something
});
gulp.watch('js/**/*.js', ['one','two']);

以上例子,如果有任何js文件发生改变,则会执行one和two两个任务。

gulp插件

  • 自动加载插件gulp-load-plugins
  • 重命名gulp-rename
  • js文件压缩gulp-uglify
  • css文件压缩gulp-minify-css
  • html文件压缩gulp-minify-html
  • js代码检查gulp-jshint
  • 文件合并gulp-concat
  • less编译gulp-less和sass编译gulp-sass
  • 图片压缩gulp-imagemin
  • 自动刷新gulp-livereload

参考文章

前端构建工具gulpjs的使用介绍及技巧,这是我目前阅读过的最详细的一篇文章。
gulp教程之gulp中文API