前端构建工具Gulp的学习和使用
前几天刚鼓捣了Grunt的使用,结果文档还没捂热,老大说我们还是用gulp吧,搞得我又得来整gulp,眼泪流成河了,真是不晓得底层人民的辛苦啊。不过经过对gulp的学习,发现很好用,比grunt舒服!
gulp是一个前端自动化构建工具,与grunt类似,但相对grunt而言gulp更好用。好处是无需写一大堆繁杂的配置参数,API也相对简单很多,学习起来很比grunt容易很多,而且gulp使用Nodejs中流(stream)来读取和操作数据,其速度更快,减少频繁的 IO 操作。
下面是学习过程中的一些总结:
1. gulp的安装
gulp的安装依赖于nodejs,所以安装gulp之前必须确保已经正确安装了nodejs环境。然后再开始安装gulp:
npm install gulp //这条命令是将gulp安装在项目根目录内,安装过程中会自建一个package-lock.json文件和一个node_modules文件夹,里面有gulp的安装文件
如果想在安装gulp时把gulp写进项目的package.json文件依赖中,则需要自己在项目的根目录中新建一个package.json文件,并且在命令中加上--save-dev: **提倡这种方式**
安装结果如图所示:
npm install --save-dev gulp //将gulp安装在项目根目录内,同时将gulp依赖写进package.json文件内的devDependencies中
安装结果及 devDependencies 依赖信息如图所示:
这样就完成了gulp的安装。
2、gulp的使用
2.1 建立gulpfile.js文件
在完成对gulp的安装以后,则开始使用gulp,跟grunt需要一个gruntfile.js文件一样,gulp也需要一个文件作为它的主文件,在gulp中该文件叫gulpfile.js。在根目录新建一个名为gulpfile.js的文件。新建好gulpfile.js文件之后就可以定义任务(此处的任务跟grunt的任务,目标配置是同一个概念)了。
下面以一个简单的gulpfile.js文件作为示例说明,定义一个默认的任务。
var gulp = require('gulp'); //导入我们需要的gulp插件信息,与grunt的pkg: grunt.file.readJSON('package.json'),是同一个作用 gulp.task('default',function(){ //定义一个任务(task), default是任务名,function():定义任务所要执行的一系列操作.通常来说,它会是这种形式:gulp.src().pipe(someplugin())。这是测试实例,没按这个来 console.log('hello world!'); // 做具体的事 });
2.2运行gulp任务
gulpfile.js完成以后,项目目录结构如下:其中gulp在node_modules内
gulpfile.js文件编写完成后,与gruntfile.js一样,要执行这些gulp任务,那么就需要执行这个文件。这时只需在存放gulpfile.js文件的目录上的路径框内输入cmd 回车就行,如下图所示:
当然你也可以在“开始”内执行cmd,然后一步步通过路径找到存放gulpfile.js文件的地方,当然这个更麻烦 (windows平台请使用cmd或者Power Shell等工具),然后在命令行中键入gulp,然后回车执行即可。Gulp和grunt一样,可以在gulp后面加上要执行的任务名,如gulp task,当然如果没有指定任务名,也和grunt一样则会执行任务名为default的默认任务,并且是按照默认任务的先后顺序依次执行,因此当任务较多时一般不指定具体任务名。
3、gulp常用API
上面简单编写了一个gulpfile.js文件,但是没什么功能。要让文件中的各个任务(task)执行不同的功能,则需要知道怎么去组织和编写功能代码,这个时候就需要学习怎么使用gulp的API接口了。辛好gulp够简单,只需知道以下4个API即可玩转大部分gulp功能了:gulp.src(),gulp.dest(), gulp.task(), gulp.watch()。所以很容易就能理解,但要玩转gulp,则有些地方需理解透彻才行。当然官方文档是最好的教程,可以好好看看和理解。
在开始对Gulp的API说明之前,首先说明一下Gulp.js和Grunt.js两者在工作方式和流程上的区别。Grunt主要是以文件为媒介来执行它的工作流程的,即Grunt执行流程是基于一个个不同的临时文件基础上的。Grunt中执行完一项任务后,将结果写入到一个临时文件中,然后在这个临时文件基础上再执行其它任务,执行完成后又将结果写入到另外的临时文件或本临时文件中,然后又以这个新的临时文件为基础继续执行其它任务..如此循环往复。而Gulp中,使用的是Nodejs中的 流(stream),所以首先获取到需要的stream,然后通过stream的pipe()方法把数据流导入需要操作的地方,如Gulp的各种插件中,经过插件处理后的流又可以继续导入到其他插件中,当然也可以把流写入到文件中。所以Gulp是以stream为媒介的,它不需要频繁的生成临时文件,减少频繁的 IO 操作,故而Gulp的速度要比Grunt快很多。
pipe()
require()
/***
* 接口介绍部门抄了大部分,自己写了一部分,加入了一些自己的理解
*/
3.1 gulp.src()
在理解了gulp的工作流程后,开始对gulp的API接口介绍。
首先是gulp.src()方法,语法格式为:gulp.src(globs[, options]),
该方法是用来获取需要操作的文件,即查找需要,但注意返回的”流”里的内容不是原始的文件流,而是一个虚拟文件(Vinyl files)对象流,这个虚拟文件对象流中存储着原始文件的路径、文件名、内容等所有信息。
参数说明:globs参数是文件匹配模式(类似正则表达式),用来匹配文件路径(包括文件名),当然这里也可以直接指定某个具体的文件路径。当有多个匹配模式时,该参数可以是一个数组。
options为可选参数。通常情况下不需要用到,要看的话官网有介绍 http://www.gulpjs.com.cn/docs/api/。
gulp.src()最重要是globs的匹配规则以及一些文件匹配技巧。
Gulp内部使用了node-glob模块来实现文件匹配功能。下面这些特殊的字符可以帮我们匹配出任务需要的文件:
* 匹配任意数量的字符,但不会匹配路径分隔符(“\”),除非路径分隔符出现在末尾(“script\”)
** 匹配路径中任意数量的多个目录及其子目录, 包括路径分隔符(“\”),需要单独出现,即它左右不能有其他东西了(“/**/*.js”)。如果出现在末尾,也能匹配文件。
? 匹配文件路径中的单个字符(但不匹配路径分隔符(“\”));
[...] 匹配方括号中出现的字符中的任意一个。当方括号中第一个字符为^或!时,则表示不匹配方括号中出现的其他字符中的任意一个,类似js正则表达式中的用法。
如:foo/*.js将匹配位于foo/目录下的所有的.js结尾的文件;而foo/**/*js将匹配foo/目录以及其子目录中所有以.js结尾的文件。
!(pattern|pattern|pattern) 匹配”任何与括号中给定的任一模式都不匹配的”
?(pattern|pattern|pattern) 匹配”括号中给定的任一模式0次或1次,类似于js正则中的(pattern|pattern|pattern)?”
+(pattern|pattern|pattern) 匹配”括号中给定的任一模式至少1次,类似于js正则中的(pattern|pattern|pattern)+”
*(pattern|pattern|pattern) 匹配”括号中给定的任一模式0次或多次,类似于js正则中的(pattern|pattern|pattern)*”
@(pattern|pattern|pattern) 匹配”括号中给定的任一模式1次,类似于js正则中的(pattern|pattern|pattern)”
下面举例说明,当然这些例子我也是抄来的,底子不足啊!
* 能匹配 a.js,b.css,abc,abc/,但不能匹配a/b.js
*.* 能匹配 a.js,b.css,a.b,x.y
*/*/*.js 能匹配 a/b/c.js,x/y/z.css,但不能匹配a/b.js,a/b/c/d.css
** 能匹配 abc,a/b.js,a/b/c.js,x/y/z,x/y/z.css,能用来匹配所有的目录及其子目录内的文件。
**/*.js 能匹配 foo.js,a/foo.js,a/b/foo.js,a/b/c/foo.js ”src/**/*.js” 可以通杀src文件夹下所有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,即不匹配含x,y,z的
当然上面这些都是单一匹配模式,当有多种匹配模式时可以使用数组。
//使用数组的方式来匹配多种文件
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
3.2 gulp.dest()
在介绍gulp.dest()接口之前,先介绍下gulp的工作流程:首先通过gulp.src()方法获取到需要处理的文件流,然后把该文件流通过pipe()方法导入到各种gulp的插件中进行处理,最后把经过插件处理后的流再通过pipe()方法导入到gulp.dest()中写入文件,加以保存!
gulp.dest()方法就是用来写文件,并且重新输出(emits)所有数据,因此可以将它 pipe() 到多个文件夹。如果某文件夹不存在,将会自动创建它。
其语法为:gulp.dest(path[,options])
path:为文件将被写入的路径(输出目录)。也可以传入一个函数,在函数中返回相应路径,这个函数也可以由 vinyl 文件实例 来提供。
options:为一个可选的参数对象,通常不需要用到。
gulp.dest()这个接口很重要,若要将此接口使用好,就必须理解给它传入的“路径参数”与“最终生成的文件”之间的关系。给gulp.dest()传入的路径参数,只能用来指定最后生成文件的目录,而不是指定生成文件的文件名,生成文件的文件名还是导入到它的文件流自身的文件名,所以生成文件的文件名是由导入到它的文件流决定的,即使给它传入一个带有文件名的路径参数,然而gulp.dest()也会把这个文件名当做是目录名,如:
var gulp = require('gulp');
gulp.src('script/zTree.js')
.pipe(gulp.dest('dist/zTree.min.js')); //最终生成的文件路径为 dist/zTree.min.js/zTree.js,而不是dist/zTree.min.js
如果真想改变文件名,可以使用插件gulp-rename,后文对该插件的加载和使用有介绍,此处不做说明!
下面以一些具体例子说明“文件路径”与给gulp.dest()方法传入的“路径参数”之间的关系。
gulp.dest(path)生成的文件路径是在传入的path参数后面再加上gulp.src()中通配符(“**”,”*.js”,”/**/*.js”)开始出现后的那部分路径。例如:
var gulp = reruire('gulp');
gulp.src('script/**/*.js') //通配符开始出现的那部分路径为 **/*.js
.pipe(gulp.dest('dist')); //传入的路劲参数是“dist”,最后生成的文件路径为:dist/**,文件名还是“.js”;文件全路径则为:“dist/**/.js”
//假设**/*.js 匹配到的文件为 zTree/zTree.js ,则生成的文件路径及文件名为 dist/zTree/zTree.js
//但如果不是通过通配符匹配的文件,如
gulp.src('script/zTree/zTree.js') //不是通过通配符匹配的文件 .pipe(gulp.dest('dist')); //最后生成的文件路径则为 dist/zTree.js,即gulp.dest()“路径参数/”加文件名 //有通配符出现的那部分路径为 **/zTree.js gulp.src('script/**/zTree.js') //假设匹配到的文件为script/zTree/zTree.js .pipe(gulp.dest('dist')); //则最后生成的文件路径为 dist/zTree/zTree.js //有通配符出现的那部分路径为 *.js gulp.src('script/*.js') //假设匹配到的文件为script/zTree.js .pipe(gulp.dest('dist')); //则最后生成的文件路径为 dist/zTree.js
通过指定gulp.src()方法配置参数中的base属性,可以更灵活的改变gulp.dest()生成的文件路径。如果在gulp.src()方法中没有配置base属性时,base的默认值为“通配符开始出现之前”那部分路径。
例如:gulp.src('src/modules/**/*.css') //此时base的值为 src/modules
其实gulp.dest()生成文件路径的规则,其实也可以理解成,用给gulp.dest()传入的“路径参数”替换gulp.src()中的base路径,最终得到生成文件的路径。
gulp.src(' src/modules/**/*.js ') //此时base的值为src/modules,即base路径为src/modules
//假设该模式下匹配到的文件 src/modules/zTree /zTree.js
.pipe(gulp.dest('dist')) //用dist替换掉base路径,即用dist替换掉src/modules/,最终得到 dist/zTree/zTree.js
所以改变base路径后,gulp.dest()生成的文件路径也会跟着改变,从而变得更灵活!
gulp.src(script/zTree/*.js, {base:'script'}) //配置了base参数,此时base路径为script
//假设匹配到的文件为script/zTree/zTree.min.js
.pipe(gulp.dest('build')) //此时生成的文件路径为 build/zTree/zTree.min.js
gulp.dest()把文件流写入文件后,其在nodejs中流转的文件流仍然可以继续使用,并被写成多个文件!
3.3 gulp.task()
gulp.task()方法:定义一个使用 Orchestrator 实现的任务(task),即该方法内部使用的是Orchestrator。
语法结构为:gulp.task(name[, deps], fn)
name 为任务名,注:如果需要在命令行中运行具体任务,则名字中不能出现空格
deps 是一个包含任务列表的数组,这些任务会在你当前任务运行之前完成。即deps是当前任务的依赖任务,只有等这些依赖任务执行完毕后,才会执行当前任务。如果没有依赖,则可省略这个参数
注意: 你的任务是否在这些前置依赖的任务完成之前就运行了?请一定要确保所依赖的任务列表中的任务都使用了正确的异步执行方式:使用一个 callback,或者返回一个 stream或 promise 。
fn 为任务函数,定义任务所要执行的一些操作,执行代码都写在里面。该参数也是可选的。通常格式:gulp.src().pipe(someplugin())
//定义一个有依赖的任务,下面的['task0', 'task1', 'task2']就是task的依赖
gulp.task('task', ['task0', 'task1', 'task2'], function() {
// Do something
});
gulp.task()这个API很简单,但需要知道执行多个任务时怎么来控制任务执行的顺序。
gulp中执行多个任务,可以通过任务依赖来实现。如想执行task0, task1, task2这三个任务,则可以定义一个空任务,然后把这三个任务当做这个空的任务的依赖就可以了:
//执行default任务,就会把task0, task1, task2这三个任务都执行了
gulp.task('default', ['task0', 'task1', 'task2']), function(){
// Do something
};
如果任务相互之间没有依赖,则会按照书写的顺序来依次执行;若有依赖则会先执行依赖任务。
如果某个任务所依赖的任务是异步的,就必须注意,gulp不会等待那个依赖任务的异步任务完成,而是会接着执行后续的任务。如:
// task是一个异步执行的任务
gulp.task(‘task’,function(){
setTimeout(function(){
console.log('Hello,Today!');
},5000);
});
//task1任务依赖于task任务,但并不会等到task任务中的异步操作完成后再执行
gulp.task('task1',['task'],function(){
console.log(''Very good!');
});
上面例子中执行task1任务时,会先执行task任务,但不会等待task任务中的异步操作完成后再执行task1任务,而是紧接着直接执行task1任务。所以task1任务会在task任务异步操作完成之前就执行了。也就失去了两者的依赖关系,这样的依赖没有实际意义!
所以既要在异步任务中异步操作完成后,再执行后续的任务(即,在依赖的异步任务异步执行完成后,再执行后续的任务),根据接口文档的叙述,可以理解为有以下三种方式:
第一:接受一个 callback。在异步操作完成后执行一个回调函数来通知gulp这个异步任务已经完成, 回调函数作为一个参数传入任务函数,并且是第一个参数。
//task是一个异步执行的任务,而test是用于通知异步任务已经完成的回调函数,作为参数传入任务函数
gulp.task('task',function(test){
setTimeout(function(){
console.log('Hello,Today!');
test(); //执行回调,表示这个异步任务已经完成
},5000);
});
//这就可以让task1任务在task任务中的异步操作完成后再执行,从而避免了异步问题
gulp.task('task1',['task'],function(){
console.log(' Very good!');
});
第二:返回一个 stream。在定义任务时返回一个流对象。对于本身就是操作gulp.src获取到的流的情况。
gulp.task('somename', function() {
var stream = gulp.src('client/**/*.js')
.pipe(doSomething ()) //doSomething()中有某些异步操作
.pipe(gulp.dest('build'));
return stream;
});
gulp.task('task2',[ 'somename'],function(){
console.log(' Do Something!');
});
第三:返回一个promise对象。如
var Q = require('q'); //一个很好的异步处理的库 https://github.com/kriskowal/q
gulp.task('somename', function() {
var deferred = Q.defer();
setTimeout(function() { // 执行异步的操作
deferred.resolve();
}, 5000);
return deferred.promise;
});
gulp.task(' task2',[ 'somename'],function(){
console.log(' Do Something!');
});
注意: 默认的,task 将以最大的并发数执行,也就是说,gulp 会一次性运行所有的 task 并且不做任何等待。如果想要创建一个序列化的 task 队列,并以特定的顺序执行,就需要做两件事:
-
- 给出一个提示,来告知 task 什么时候执行完毕,
- 再给出一个提示,来告知一个 task 依赖的另一个 task 什么时候完成。
gulp.task()就这些了,主要是要知道当依赖是异步任务时该怎么处理。下面接下来是gulp.watch();
3.4 gulp.watch()
gulp.watch()用来监视文件的变化,当文件发生变化后,可以用它执行相应的任务,如自动文件压缩等。其语法为:gulp.watch(glob[, opts], tasks)
glob 为要监视的文件匹配模式,规则和用法与gulp.src()方法中的glob相同。
opts 为一个可选的配置对象,通常不需要用到
tasks 为需要在文件变动后执行的一个或者多个通过 gulp.task() 定义的 task,
//定义了一些任务,再定义一个gulp.watch()
gulp.task('uglify',function(){
//do something
});
gulp.task(‘miniJs’,function(){
//do something
});
gulp.watch('/src/modules/**/*.js', ['uglify', miniJs’]);
gulp.watch()还有第二种使用方式:gulp.watch(glob[, opts, cb])
glob和opts参数与第一种用法相同
cb参数为一个函数,每次变动需要执行的 callback。每当监视的文件发生变化时,就会调用这个函数,并且会给它传入一个名为 event
的对象,该对象描述了所监控到的文件的变动,type属性为变化的类型,可以是added, changed 或者 deleted;path属性为发生变化的文件的路径(即触发了该事件的文件的路径)
gulp.watch('src/modules/**/*.js ', function(event) {
console.log('文件路径' + event.path + ' ,文件变化类型 ' + event.type);
});
//也可以分开写
gulp.watch('src/modules/**/*.js ', function(event){
console.log(event.type); //变化的类型 added为新增, changed为改变,deleted为删除,
console.log(event.path); //发生变化的文件的路径
});
4、gulp常用插件
最后就是插件了,gulp的插件数量虽然没有grunt那么多,但也可以说是应有尽有了(grunt之所有插件比gulp多根本原因还是在工作方式和流程上的区别,grunt是基于文件的工作方式,那么就需要大量处理临时文件的插件,反观gulp则不需要),下面是一些常用的插件。
4.1 自动加载插件 gulp-load-plugins
安装命令:npm install --save-dev gulp-load-plugins
功能:要使用gulp的插件,首先用require()把插件加载进来,如果要使用的插件非常多,那在gulpfile.js文件开头就要写很多的require():
gulp = require('gulp');
runSequence = require('run-sequence');
del = require('del');
uglify = require('gulp-uglify');
concat = require('gulp-concat');
minifyCss = require('gulp-minify-css');
browserSync = require('browser-sync').create();
更多的插件... 这里只是列举一些常用的,至于特别功能需要更多的,则再加。
虽然这没什么问题,但会使gulpfile.js文件变得很冗长,看上去很吓人,咋这么多!gulp-load-plugins插件正是用来解决这个问题。这个插件能自动加载package.json文件里的gulp插件。假设package.json文件里devDependencies依赖是这样的:
{
"devDependencies": {
"gulp": "^3.9.1",
"gulp-concat": "^2.6.1",
"gulp-minify-css": "^1.2.4",
"gulp-uglify": "^3.0.0"
}
}
这么多插件一一用require()太麻烦了,那么就可以在gulpfile.js中使用gulp-load-plugins来加载插件:和grunt的pkg:grunt.file.readJSON('package.json')类似,但是加载方式又有所区别。
首先需要将gulp加载进来
var gulp = require('gulp');
然后,加载gulp-load-plugins插件,并运行它
var plugins = require('gulp-load-plugins')();
//或者:
var gulpLoadPlugins = require('gulp-load-plugins');
var plugins = gulpLoadPlugins();
然后当接下来要使用gulp-concat和gulp-uglify这两个插件的时候,就可以用plugins. concat和plugins. uglify来代替,即将原始插件名去掉gulp-前缀即可。实质是gulp-load-plugins是做了如下的转换:
plugins. concat = require('gulp- concat);
plugins. uglify = require('gulp- uglify ');
当然如果是gulp-minify-css这种的话,则采用驼峰命名方式,即
plugins. minifyCss = require(“gulp-minify-css”);
gulp-load-plugins有一个好处,就是并不会在一开始就加载package.json里面所有的gulp插件,而是工程项目中需要用到某个插件的时候,才去加载那个插件,可以节约一丢丢的内存和缩短一小戳时间,嘎嘎!。既然这些都基于package.json文件来玩的,那么package.json就很有必要存在了。所以,在开始安装gulp的时候建议在命令行中加入 –save-dev 的效果就体现出来了哟。
4.2 文件合并 gulp-concat
安装命令:npm install --save-dev gulp-concat
功能:用于将多个文件合并为一个文件。常用来将多个JS文件或多个CSS文件合并为一个JS文件或一个CSS文件等,从而减小加载网页时下载文件的http请求数量,降低对带宽的占用;同时减少对浏览器内存的占用。
//加载方式:
var gulp = require('gulp'),
var concat = require("gulp-concat");
//或者:
plugins. concat // plugins是var plugins = require('gulp- load-plugins')();
//文件合并任务创建
gulp.task('concat', function () {
gulp.src('/src/modules/Suspension/scripts/*.js') //要合并的文件
.pipe(concat('all.js')) //合并到一个名为"all.js"的新JS文件
.pipe(gulp.dest('dist/ modules/Suspension/scripts')); //将合并成的新JS文件存放到dist/ modules/Suspension/scripts路径下
});
4.3 JS文件压缩 gulp-uglify
安装命令:npm install --save-dev gulp-uglify
功能:用于JS文件的压缩,使用的是uglify引擎。既然文件合并完成了,那就开始压缩!
//加载方式:
var gulp = require('gulp'),
uglify = require("gulp-uglify");
//或者:
plugins. uglify
//JS文件压缩任务创建
gulp.task('miniJs', function () {
gulp.src(' dist/ modules/Suspension/scripts /*.js') // 要压缩的js文件
.pipe(uglify()) //使用uglify进行JS文件压缩,更多配置请参考:
.pipe(gulp.dest(' dist/ modules/Suspension/scripts ')); //压缩后的文件路径(此处压缩的是all.js源文件)
});
4.4 CSS文件压缩 gulp-minify-css
安装命令:npm install --save-dev gulp-minify-css
功能:用于CSS文件的压缩。既然压缩了JS文件,那么接下来就轮到CSS文件了。
//加载方式:
var gulp = require('gulp'),
var minifyCss = require("gulp-minify-css");
//或者:
plugins. minifyCss //驼峰命名方式
// CSS文件压缩任务创建
gulp.task('miniCss', function () {
gulp.src(' dist/ modules/Suspension/ style /*.css') //要压缩的css文件
.pipe(minifyCss()) //压缩CSS文件
.pipe(gulp.dest(' dist/ modules/Suspension/ style ')); //压缩后的文件路径(此处压缩的是all.css源文件)
});
4.5 图片压缩 gulp-imagemin
安装命令:npm install --save-dev gulp-imagemin
功能:用于压缩jpg、png、gif等图片。过了JS,CSS文件,轮到image了!
//加载方式:
var gulp = require('gulp');
var imagemin = require('gulp-imagemin');
var pngquant = require('imagemin-pngquant'); //png图片压缩插件
// 图片文件压缩任务创建
gulp.task('imageMin', function () {
return gulp.src('src/images/*')
.pipe(imagemin({
optimizationLevel: 5, //类型:Number 默认:3 取值范围:0-7(优化等级)
progressive: true, //类型:Boolean 默认:false 无损压缩jpg图片
interlaced: true, //类型:Boolean 默认:false 隔行扫描gif进行渲染
multipass: true //类型:Boolean 默认:false 多次优化svg直到完全优化
use: [pngquant()] //使用pngquant来压缩png图片
}))
.pipe(gulp.dest('dist'));
});
建议只压缩修改的图片,压缩图片比较耗时。一般图片修改比较小或者一次做好以后就很少修改,因此没有必要经常压缩图片,可以另外使用”gulp-cache”只压缩修改过的图片,没有修改的图片直接从缓存文件读取。 gulp-imagemin的使用复杂一点,它本身也有很多插件要详细理解,就只能去看它的文档了!
4.6 Html文件压缩 gulp-minify-html
安装命令:npm install --save-dev gulp-minify-html
功能:用于压缩html文件。
//加载方式:
var gulp = require('gulp'),
minifyHtml = require("gulp-minify-html");
//或者:
plugins. minifyHtml //驼峰命名方式
// Html文件压缩任务创建
gulp.task('minifyHtml', function () {
gulp.src('client/*.html') // 要压缩的html文件
.pipe(minifyHtml()) //压缩Html文件
.pipe(gulp.dest('dist/client'));
});
当然html压缩也就压缩一些空格而已,实际意义并不是很大!
4.7 JS代码检查 gulp-jshint
安装命令:npm install --save-dev gulp-jshint
功能:用来检查JS代码是否有变化。
//加载方式:
var gulp = require('gulp'),
jshint = require("gulp-jshint");
//或者:
plugins. jshint
//jshint文件压缩任务创建
gulp.task('jshint', function () {
gulp.src('/src/modules/Suspension/scripts/*.js ')
.pipe(jshint())
.pipe(jshint.reporter()); // 对代码进行报错提示
});
//可以定义一个自定义错误(引入map-stream模块)提示:
var mapstream = require( 'map-stream' );
/* file.jshint.success = true; // or false 代码检查是否成功
file.jshint.errorCount = 0; // 错误的数量
file.jshint.results = []; // 错误的结果集
file.jshint.data = []; // JSHint返回关于隐含的全局变量、圈复杂度等的详细信息 file.jshint.opt = {}; //将选择的选项传递给JSHint
*/
var myReporter = map(function (file, cb) {
if (!file.jshint.success) {
console.log('[ '+file.jshint.errorCount+' errors in ]'+file.path);
file.jshint.results.forEach(function (err) {
/*
err.line 错误所在的行号
err.col 错误所在的列号
err.message/err.reason 错误信息
*/
if (err) {
console.log(' '+file.path + ': line ' + err.line + ', col ' + err.character + ', code ' + err.code + ', ' + err.reason);
}
});
}
cb(null, file);
});
gulp.task('jshint', function() {
return gulp.src('dist/ modules/Suspension/scripts /*.js') // 指定目录下所有的js文件
.pipe(jshint()) // js代码检查
.pipe(myReporter); // 若有错误,则调用myReporter进行提示
});
也可以定一个执行函数,在代码检查完毕后,自动执行合并和压缩。
4.8 重命名 gulp-rename
安装命令:npm install --save-dev gulp-rename
功能:用于重命名文件流中的文件。在用gulp.dest()方法写入文件时,完成后的文件名是原文件名,如果要改变gulp.dest()后的文件名,就可以在之前用gulp-rename插件来改变文件流中的文件名。
//加载方式:
var gulp = require('gulp'),
rename = require('gulp-rename'),
uglify = require("gulp-uglify");
//或者:
plugins. rename
plugins. uglify
// rename插件使用任务
gulp.task('rename', function () {
gulp.src('dist/ modules/Suspension/scripts/all.js')
.pipe(uglify()) //JS文件压缩
.pipe(rename(‘all.min.js’)) //将all.js重命名为all.min.js,便于自己识别
.pipe(gulp.dest('dist/ modules/Suspension/scripts'));
});
这个很有用,便于修改压缩后的文件名,让工程文件和开发文件更容易区分。
4.9 自动刷新 gulp-livereload
安装命令:npm install --save-dev gulp-livereload。
功能:当代码发生变化时,gulp-livereload可以自动刷新页面。该插件最好配合谷歌浏览器使用,且要安装livereload chrome
extension扩展插件,不能下载的请跨过那道墙。
//加载方式:
var gulp = require('gulp'),
less = require('gulp-less'),
livereload = require('gulp-livereload');
//或者:
plugins. less
plugins. livereload
//自动刷新任务定义
gulp.task('less', function() {
gulp.src('less/*.less')
.pipe(less())
.pipe(gulp.dest('css'))
.pipe(livereload());
});
gulp.task('watch', function() {
livereload.listen(); //要在这里调用listen()方法
gulp.watch('less/*.less', ['less']);
});