gulp是一个即grunt后出现的一个前端构建工具,跟grunt相比,gulp的API不多而且很简单,使用nodejs中stream来读取和操做数据,其速度比grunt更快,下面让咱们来学习一下如何使用gulp快速构建你的项目。javascript
本文主要介绍html
gulp的安装和使用前端
gulp的APIjava
gulp的经常使用插件node
1.全局安装gulp正则表达式
$ npm install --global gulp
2.做为项目依赖安装gulpshell
$ npm install --save-dev gulp
3.使用gulpnpm
1.在你的文件目录下面创建一个package.json和gulpfile.js的文件。json
package.json:此文件被npm用于存储项目的元数据,以便将此项目发布为npm模块。你能够在此文件中列出项目依赖的gulp插件,放置于devDependencies配置字段内;
gulpfile:用来配置或定义任务(task)并加载gulp插件的。gulp
2.安装gulp插件
$ npm install --save-dev gulp-uglify
--save-dev和--save的区别
若是只写上--save,gulp插件在package.json的dependencies里面保存,而写--save-dev 的话,gulp插件会保存在package.json的devDependencies,这里有关于这两个属性的区别http://www.cnblogs.com/jes_sh...
安装包的两种方式
$ npm insatll
devDependencies和dependencies都会安装
$ npm install --production
只安装dependencies而不安装devDependencies。
$ npm install packagename
那么只会安装dependencies,而不安装devDependencies。
$ npm install packagename --dev
devDependencies和dependencies都会安装
举个例子
咱们新建一个文件夹只有package.json文件,执行 会默认读取package.json的
devDependencies和dependencies里面的属性,而且安装devDependencies和dependencies下面的包。
以下所示,会安装gulp和gulp-concat,而后还会读取gulp和gulp-concat
里面的dependencies里面的包,在安装gulp和gulp-concat所依赖的包,可是这个时候并不会安装devDependencies里面的包了
{ "name": "grunt_test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies":{ "gulp": "^3.9.1" }, "devDependencies": { "gulp-concat": "^2.6.0" }, "author": "", "license": "ISC" }
$ gulp npm install --save stream-combiner2
{ "name": "application-name", "version": "0.0.1", "devDependencies": { "del": "^2.2.1", "gulp": "^3.9.1", "gulp-concat": "^2.6.0", "gulp-load-plugins": "^1.2.4", "gulp-uglify": "^1.5.4", "pump": "^1.0.1" }, "dependencies": { "stream-combiner2": "^1.1.1" } }
3.编写gulpfile.js
var gulp = require('gulp'); var uglify = require('gulp-uglify'); gulp.task('uglifyTask', function (cb) { return gulp.src('www/**') .pipe(uglify()) .pipe(gulp.dest('dest')); })
4.运行task
$ gulp uglifyTask
执行上述命令,就会执行uglifyTask这个task,若是只输入gulp 那么会默认执行default这个任务;
若是gulpfile中没有设置default这个任务,直接执行gulp,就会抛出如下错误
➜$ gulp [22:40:37] Using gulpfile ~/WebstormProjects/gulp/gulpfile.js [22:40:37] Task 'default' is not in your gulpfile [22:40:37] Please check the documentation for proper gulpfile formatting
gulp.src(globs,option)
gulp.dest(path, options)
task(name, deps, fn)
gulp.watch(glob , opts, tasks) 或 gulp.watch(glob , opts, cb)
就这四个API是否是特别少,在介绍这些API以前先说一下gulp的工做方式,gulpfile.js充分利用了Node.js的 Streams(流) API ,首先获取到须要的stream,而后能够经过stream的pipe(管道)方法把流导入到你想要的地方,好比Gulp的插件中,通过插件处理后的流又能够继续导入到其余插件中,固然也能够把流写入到文件中。
1.gulp.src(globs,option)
gulp.src就是输出符合所提供的匹配模式(glob)或者匹配模式的数组(array of globs)的文件。 将返回一个流,能够经过管道pipe输入别的gulp插件,内容不是原始的文件流,而是一个虚拟文件对象流(这个是看一篇介绍说的,具体理解不深),咱们能够简单理解为读取一个符合globs匹配的文件
globs是文件匹配模式的一个字符串或者一个数组,下面是经常使用文件匹配模式
* 匹配任意数量的字符,但不匹配 /
? 匹配单个字符,但不匹配 /
** 匹配任意数量的字符,包括 /,只要它是路径中惟一的一部分
[pattern,pattern1] 匹配方括号中出现的字符中的任意一个,当方括号中第一个字符为^或!时,则表示不匹配方括号中出现的其余字符中的任意一个,相似js正则表达式中的用法
! 在模式的开头用于排除一个匹配模式所匹配的任何文件
下面以一系列例子来加深印象,个人目录结构是这样的
'www/*' 匹配 www/a.js www/js 'www/?.js' 匹配 www/a.js 'www/**/*.js' 匹配 www/全部二级目录下的js ['www/**/*.js','src/**/*.js'] 匹配 www和src下面的全部的子级目录下面的js文件; ['www/**/*.js','!www/*.js'] 匹配不包含www下面的a.js的全部其余的js文件;
option经过 glob-stream 所传递给 node-glob 的参数,除了 node-glob 和 glob-stream 所支持的参数外,gulp 增长了一些额外的选项参数:
1.options.buffer 类型: Boolean 默认值: true
那么将会以 stream 方式返回 file.contents 而不是文件 buffer 的形式返回;
2.options.read 类型: Boolean 默认值: true
若是该项被设置为 false, 那么 file.contents 会返回空值(null),也就是并不会去读取文件。
3.ptions.base 类型 string
修改 base的值 默认的base的值为通配符开始出现以前那部分路径,若是设置了base值,那么将依照这个base值为基准
return gulp.src('www/js/**/*.js') //假设匹配上的是www/js/module/a.js,那么base是www/js .pipe($.uglify()) .pipe(gulp.dest('dest')); //dest输出的是 dest/module/a.js return gulp.src('www/js/**/*.js',{base:'www'}) //设定了base,那么base是www .pipe($.uglify()) .pipe(gulp.dest('dest')); //dest输出的是 dest/js/module/a.js
2.gulp.dest(path, options)
path:文件输出的目录,只能是目录地址,若是包含文件名,那么会把文件名也当作目录的一部分建对应的路径,path将替换gulp.src里面的base生成对应的目录存放文件。
gulp.task('uglifyTask', function (cb) { return gulp.src('www/js/**/*.js',{base:'www'}) .pipe($.uglify()) .pipe($.rename({extname: '.min.js'})) .pipe(gulp.dest('dest/uglfy.min.js')); })
options,这个通常不用,这里就不作介绍了,须要了解的能够去官方api进行了解;
3.task(name, deps, fn)
gulp.task 定义一个任务,name类型:string,这个任务的名称;deps类型:array,这个任务依赖的其余任务;fn类型:function 任务的具体操做,有一个参数,是执行完的回调函数cb
这个方法比较简单,这里我主要讲一下执行顺序
/** 压缩 **/ gulp.task('uglifyTask',['clean:dest'],function (cb) { console.log('uglifyTask执行') return gulp.src('www/js/**/*.js',{base:'www'}) .pipe($.uglify()) .pipe($.rename({extname: '.min.js'})) .pipe(gulp.dest('dest/uglfy.min.js')); }) /** 删除 **/ gulp.task('clean:dest', function (cb) { console.log('dest已经执行完毕') del([ 'dest/**/*' ]) })
$ gulp uglifyTask
上面代码咱们会认为首先输出‘dest已经执行完毕’,‘而后输出uglifyTask执行’,结果咱们去命令行输出的结果是这个样子滴
➜ gulp gulp uglifyTask [00:10:54] Using gulpfile ~/WebstormProjects/gulp/gulpfile.js [00:10:54] Starting 'clean:dest'... dest已经执行完毕 ➜ gulp
只输出了dest已经执行完毕,这是为何?
原来,默认的,task 将以最大的并发数执行,也就是说,gulp 会一次性运行全部的 task 而且不作任何等待。若是你想要建立一个序列化的 task 队列,并以特定的顺序执行,你须要在依赖的task里面给出提示,告诉这个task已经执行完毕
提示的三种方式:
返回一个流
返回一个promise
执行回调函数;
了解这些后,上面的咱们简单改变一下,就可让clean执行完后,执行uglify的task;
gulp.task('clean:dest', function (cb) { console.log('dest已经执行完毕') return del([ //这是返回一个流 'dest/**/*' ]) // if (err) return cb(err); // 返回 error // cb(); 执行回调函数 // return Promise.resolve('success'); 返回一个成功的promise })
4.gulp.watch(glob , opts, tasks) 或 gulp.watch(glob , opts, cb)
gulp.watch 监视文件,而且能够在文件发生改动时候作一些事情。或者执行一些task
glob跟gulp.src的glob相同,这里就不作介绍了,opts,这个也不常常用API上没有详细的介绍。咱们主要讲一下第三个参数为tasks 或者 cb的
当第三个参数是tasks,监听的文件改变的时候会依次执行tasks数组里面的task,而且会返回一个EventEmitter,能够监听EventEmitter的change事件,事件的回调函数会被传入一个名为 event 的对象。这个对象描述了所监控到的变更:
第三个参数是function,那么监听的文件改变的时候,会执行回调函数里面的内容,一样的回调函数也有一个event对象,包含如下属性;
event.type 类型: String 发生的变更的类型:added, changed 或者 deleted。 event.path 类型: String 触发了该事件的文件的路径。
/** 监听文件变化 tasks**/ var wachEvet=gulp.watch('www/js/**/*.js',['uglifyTask']) wachEvet.on('change',function(event){ console.log(event.type+event.path); }) /** fn **/ gulp.watch('www/js/**/*.js',function(event){ console.log(event.type+event.path); })
执行watch 应该创建一个task,而后在命令行里面输入 gulp watch
gulp.task('watch',function(){ gulp.watch('www/js/**/*.js',function(event){ console.log(event.type+event.path); }) })
gulp的插件比较多,这里我就简单说几个经常使用到的插件,别的插件咱们能够经过这个网址去查询https://www.npmjs.com/browse/...
1.gulp-load-plugins
做用:自动加载gulp插件
地址:https://www.npmjs.com/package/gulp-load-plugins
使用方法:
var $ = require('gulp-load-plugins')(); $.uglify() // 同上面同样 var uglify = require('gulp-uglify'); uglify()
2.gulp-rename
做用:重命名
地址:https://www.npmjs.com/package...
使用方法:
// 字符串形式 gulp.src("./src/main/text/hello.txt") .pipe(rename("main/text/hello.js")) .pipe(gulp.dest("./dist")); // ./dist/main/text/hello.js // 方法 gulp.src("./src/**/hello.txt") .pipe(rename(function (path) { path.dirname += "/rname"; path.basename += "-goodbye"; path.extname = ".md" })) .pipe(gulp.dest("./dist")); //base=main/text ./dist/main/text/rname/hello-goodbye.md // 对象 gulp.src("./src/main/text/hello.txt") .pipe(rename({ dirname: "main/text/rname", basename: "aloha", prefix: "bonjour-", suffix: "-hola", extname: ".md" })) .pipe(gulp.dest("./dist")); // ./dist/main/text/rname/bonjour-aloha-hola.md
3.gulp-uglify
做用:压缩js代码,这个只是单纯的压缩,并不像grunt同样还能改变名称,因此要配合上面的rename使用
地址:https://www.npmjs.com/package...
使用方法:
gulp.task('uglifyTask',['clean:dest'],function (cb) { return gulp.src('www/js/**/*.js',{base:'www'}) .pipe($.uglify()) .pipe($.rename({extname: '.min.js'})) .pipe(gulp.dest('dest/uglfy.min.js')); })
4.grunt-concat
做用:合并文件,下面实例会合并一个js,放在dest/concat/all.js
地址:https://www.npmjs.com/package...
使用方法:
gulp.task('concatTask', function (cb) { return gulp.src('src/**/*.js') .pipe($.concat('concat/all.js')) .pipe(gulp.dest('dest')); })
5.gulp-jshint
做用:语法检查
地址:
使用方法:
gulp.task('jshint',function(){ return gulp.src('src/**/*.js') .pipe($.jshint()) .pipe($.jshint.reporter('default')) //使用默认的错误提示 //.pipe(myReporter) 使用map-stream自定义错误信息 })
6.del
做用:删除文件
地址:
使用方法:
gulp.task('clean:dest', function (cb) { return del([ 'dest/**/*' ]) })
7.stream-combiner2
做用:监听流中的错误信息
使用方法:
var combiner = require('stream-combiner2'); var uglify = require('gulp-uglify'); var gulp = require('gulp'); gulp.task('test', function() { var combined = combiner.obj([ gulp.src('bootstrap/js/*.js'), uglify(), gulp.dest('public/bootstrap') ]); // 任何在上面的 stream 中发生的错误,都不会抛出, // 而是会被监听器捕获 combined.on('error', console.error.bind(console)); return combined; });
8.lazypipe
做用:提出流中的公共部分
网址:http://www.gulpjs.com.cn/docs...
以上是本身的学习记录笔记。