一、安装gulpcss
npm install --save-dev gulp
复制代码
二、建立gulpfile.js文件html
var gulp = require("gulp");
gulp.task("default", function() {
console.log("hello");
})
复制代码
三、gulp命令node
3.1 gulp.src(globs,[options])git
做用:将匹配的文件转化为数据流而后经过pipe方法,将数据流传递给对应的插件进行处理。github
globs为路径匹配模式,相似正则表达式,可是跟正则表达式是不一样的。能够直接写真实的页面路径。正则表达式
好比须要对a.txt这个文件进行某种处理,能够这样引入a.txt文件npm
gulp.src("a.txt")
复制代码
3.2 gulp.dest(path[,options])gulp
做用:将pipe进来的数据流转化为文件。注意文件名是不会变的。若是要改文件名就须要相应的gulp插件数组
gulp.task("default", function() {
gulp.src("aa.txt")
.pipe(gulp.dest("test"));
})
复制代码
path为文件将被写入的路径(输出目录)。也可传入一个函数,在函数中返回相应的路径。promise
3.3 gulp.task(name[, deps], fn)
做用:定义一个使用gulp任务
建立一个任务a,打印一个hello world。
gulp.task("a",function(){
console.log("hello world");
})
复制代码
3.4 gulp.watch(glob [, opts], tasks) 或 gulp.watch(glob [, opts, cb])
监视文件,而且在文件变更的时候执行某些任务。
3.4.1 gulp.watch(glob [, opts], tasks)
好比监视js文件,当js文件变更的时候,压缩js文件到dest文件夹。文件变更包括:一、新增文件,二、改变文件内容,三、删除文件,四、重命名文件
var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
var uglify = require("gulp-uglify");
gulp.task("compassJs", function() {
gulp.src("*.js")
.pipe(uglify())
.pipe(gulp.dest("test"));
})
gulp.task("default", function() {
gulp.watch("*.js", ["compassJs"]);
})
复制代码
3.4.2 gulp.watch(glob [, opts, cb])
好比监视js文件,当文件变更的时候,执行某些操做。一、新增文件,二、改变文件内容,三、删除文件,四、重命名文件
var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
var uglify = require("gulp-uglify");
gulp.task("default", function() {
gulp.watch("*.js", function(event) {
console.log(event.path, event.type);
});
})
复制代码
进阶篇
一、gulp.src(globs,[options])
gulp引入须要处理的文件,采用的方法是glob匹配文件路径。glob匹配具体规则以下
1.一、glob 模式匹配
点击在github上查看完整文档
glob的使用方法:
//其中pattern 为glob模式,options为glob配置选项,若是没有能够省略。function为匹配的回调函数,参数er为错误对象,files为匹配成功的文件名数组。
var glob = require("glob")
glob(pattern, options, function (er, files) {
// files is an array of filenames.
// If the `nonull` option is set, and nothing
// was found, then files is [pattern]
// er is an error object or null.
})
复制代码
glob的使用案例:
目录结构:
--glob.js
--a.txt
--b.txt
--node_modules
复制代码
假设有一个glob.js文件,代码以下,在glob同级目录下有a.txt,b.txt两个文件。命令行执行node glob.js。则能够匹配到a.txt,b.txt 两个文件:
glob("*.txt", {}, function(err, files) {
console.log("files:", files); // files:["a.txt","b.txt"]
});
复制代码
1.1.1 点的特殊处理
目录名或者文件名若是以 . 开头,只有模式中对应部分以 . 开头才能匹配。
若是在option中设置dot:true,glob就会把.当成普通的字符来处理,这时候就可使用*或者?来匹配.了。
1.1.2 matchBase匹配
若是option中设置了matchBase为true,则glob会遍历同级目录及其子目录下任意符合匹配模式的文件
1.1.3 空输出
若是没有文件或者目录符合模式,则返回一个空数组
1.2 完整的测试案例
目录结构
+--b
| +--b.txt
+--c
| +--c2
| | +--c.txt
+--..git
+--a.txt
+--a1.txt
+--aa.txt
+--ab.txt
+--ac.txt
+--b.txt
+--ba.txt
+--c.txt
+--glob.js
复制代码
glob.js代码及输入结果以下:
var glob = require("glob");
// *测试
glob("*.txt", {}, function(err, files) {
console.log("*符号测试", files);
});
//?测试
glob("?.txt", {}, function(err, files) {
console.log("?符号测试", files);
});
//[]测试
glob("a[a-z].txt", {}, function(err, files) {
console.log("[]符号测试", files);
});
// !()测试
glob("!(a|b).txt", {}, function(err, files) {
console.log("!()符号测试", files);
});
// ?()测试
glob("?(a|b).txt", {}, function(err, files) {
console.log("?()符号测试", files);
});
// +()测试
glob("+(a|b).txt", {}, function(err, files) {
console.log("+()符号测试", files);
});
// *()测试
glob("*(a|b).txt", {}, function(err, files) {
console.log("*()符号测试", files);
});
// @()测试
glob("@(a|b).txt", {}, function(err, files) {
console.log("@()符号测试", files);
});
// **测试
glob("**", {}, function(err, files) {
console.log("**符号测试", files);
});
// .测试
glob("?.git", {}, function(err, files) {
console.log(".符号测试", files);
});
// .测试
glob("?.git", { dot: true }, function(err, files) {
console.log(".符号测试dot为true", files);
});
// matchBase测试外部终端配置
glob("*.txt", { matchBase: true }, function(err, files) {
console.log("matchBase测试", files);
});
// 不匹配测试
glob("*.png", { matchBase: true }, function(err, files) {
console.log("不匹配测试", files);
});
如下为代码的输出结果:
/*
*符号测试 [ 'a.txt',
'a1.txt',
'aa.txt',
'ab.txt',
'ac.txt',
'b.txt',
'ba.txt',
'c.txt' ]
?符号测试 [ 'a.txt', 'b.txt', 'c.txt' ]
[]符号测试 [ 'aa.txt', 'ab.txt', 'ac.txt' ]
!()符号测试 [ 'a1.txt', 'aa.txt', 'ab.txt', 'ac.txt', 'ba.txt', 'c.txt' ]
?()符号测试 [ 'a.txt', 'b.txt' ]
+()符号测试 [ 'a.txt', 'aa.txt', 'ab.txt', 'b.txt', 'ba.txt' ]
*()符号测试 [ 'a.txt', 'aa.txt', 'ab.txt', 'b.txt', 'ba.txt' ]
@()符号测试 [ 'a.txt', 'b.txt' ]
.符号测试 []
.符号测试dot为true [ '..git' ]
**符号测试 [ 'a.txt',
'a1.txt',
'aa.txt',
'ab.txt',
'ac.txt',
'b',
'b.txt',
'b/b.txt',
'ba.txt',
'c',
'c.txt',
'c/c2',
'c/c2/c.txt',
'glob.js' ]
matchBase测试 [ 'a.txt',
'a1.txt',
'aa.txt',
'ab.txt',
'ac.txt',
'b.txt',
'b/b.txt',
'ba.txt',
'c.txt',
'c/c2/c.txt' ]
不匹配测试 []
*/
复制代码
1.3 options选项
glob的options是经过gulp.src(globs,[options])中的options传入的。gulp的option处理包含glob的全部配置选项外还扩展了一些本身的内容。
1.3.1 options.buffer
默认options.buffer为true。gulp.src将文件转为vinyl类型的数据流的时候,默认是以buffer存储数据内容的。gulp的插件默认也是处理buffer类型的数据。buffer类型的数据流有个缺点就是须要所有读取完文件才能处理。这样处理速度就会相对较慢。
能够将options.buffer设置为false,这样gulp.src将文件转为vinyl类型的数据流的时候,就会采用stream的形式存储数据内容。这样能够提升处理大文件的速度。缺点支持stream类型的插件较少。
1.3.2 options.read
默认options.read为true。若是设置为false。gulp.src就不会去读取文件
1.3.3 options.base
字符串类型,默认返回路径中glob模式以前的字符串或者路径中匹配成功以前的字符串
以上为glob经常使用的使用方法,完整的使用方法须要在github上查看。glob的options是经过gulp.src(globs,[options])的options传入的。
二、 vinyl-fs
gulp.src会将匹配的文件转化为vinyl类型的数据流,而后经过pipe方法将流传递给对应的插件进行处理。 gulp只支持vinyl类型的数据流,不支持常规的nodejs数据流。
2.1 vinyl是什么
vinyl是一个文件格式,经过它能够很方面的描述一个文件,包括文件的路径、文件名和内容,它也能够很方便的设置或者获取文件的内容。优势就是跨平台,能够将不一样操做系统的文件转化为统一的形式。
建立一个vinyl类型的文件
//建立vinyl方法 new Vinyl(options)
var Vinyl = require("vinyl");
var jsFile = new Vinyl({
cwd: "/",
base: "/test",
path: "/test/file.js",
contents: new Buffer("var x=123")
})
复制代码
其中各个选项的含义以下
页面目录结果以下
+--b
| +--aa.txt
+--aa.txt
复制代码
程序以下:
gulp.task("default", function() {
gulp.src("aa.txt", { cwd: "b" })
.pipe(gulp.dest("test"))
})
复制代码
若是没有给gulp.src传{cwd:"b"} gulp选择的文件为跟b文件夹同目录的aa.txt 。如今由于程序传了{cwd:"b"},因此如今选择的文件为b文件夹下的aa.txt
参考来源:
vinyl的npm地址
三、gulp.dest(path[,options])
3.1 options 选项
程序1:
gulp.task("default", function() {
gulp.src("aa.txt")
.pipe(gulp.dest("test"));
})
复制代码
程序2:
gulp.task("default", function() {
gulp.src("aa.txt")
.pipe(gulp.dest("test", { cwd: "hello" }));
})
复制代码
程序1的执行结果
+--test
| +--aa.txt
复制代码
程序2的执行结果
+--hello
| +--test
| | +--aa.txt
复制代码
程序2会先在目录中生成hello文件夹,而后再输出gulp.dest结果。
四、gulp.task(name[, deps], fn)
异步任务按顺序执行
gulp.task("a", function() {
console.log("a");
})
gulp.task("b", function() {
setTimeout(() => {
console.log("b");
}, 100);
})
gulp.task("default", ["a", "b"], function() {
console.log("default");
})
//执行结果控制台输出 a default b
复制代码
若是要确保依赖任务彻底执行完毕,再执行当前任务,也就是须要序列化的执行任务,须要作两件事情。
方法有3个:
4.1 使用回调函数
有两个任务a、b,b任务里有一个异步函数。若是不作特殊处理,输出结果以下。
var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
gulp.task("a", function() {
console.log("a");
})
gulp.task("b", function() {
setTimeout(() => {
console.log("b");
}, 100);
})
gulp.task("default", ["a", "b"], function() {
console.log("default");
})
//输出结果 a default b
复制代码
这并非咱们想要的,咱们但愿a、b执行完了再执行default。咱们能够在b任务中调用一个callback函数,来实现咱们的要求
var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
gulp.task("a", function() {
console.log("a");
})
gulp.task("b", function(cb) {
setTimeout(() => {
console.log("b");
cb()
}, 100);
})
gulp.task("default", ["a", "b"], function() {
console.log("default");
})
// 执行结果 a b default
复制代码
4.2 返回一个stream
有a、b两个任务,b任务须要去执行一个异步任务——读取一张图片。
var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
gulp.task("a", function() {
console.log("a");
})
gulp.task("b", function() {
gulp.src("b.png")
.pipe(map(function(data, callback) {
console.log("b");
callback(null, data)
}))
.pipe(gulp.dest("test"));
})
gulp.task("default", ["a", "b"], function() {
console.log("default");
})
// 执行结果 a default b
复制代码
default任务在b任务执行完成以前执行了,这不符合咱们的要求,咱们能够在b任务中返回一个stream,来达到序列化的要求。
var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
gulp.task("a", function() {
console.log("a");
})
gulp.task("b", function() {
return gulp.src("b.png")
.pipe(map(function(data, callback) {
console.log("b");
callback(null, data)
}))
.pipe(gulp.dest("test"));
})
gulp.task("default", ["a", "b"], function() {
console.log("default");
})
//执行结果 a b default
复制代码
4.3 返回一个promise
咱们修改4.1中第一个程序,把它由callback实现序列化改为经过promise来实现序列化
var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
gulp.task("a", function() {
console.log("a");
})
gulp.task("b", function() {
var p = new Promise(function(resolve, reject) {
setTimeout(() => {
console.log("b");
resolve();
}, 100);
})
return p;
})
gulp.task("default", ["a", "b"], function() {
console.log("default");
})
//输出结果 a、b、default
复制代码
五、gulp的报错处理
执行gulp任务的时候常常会遇到gulp报错的状况,gulp对于错误的处理很是糟糕,一旦报错gulp就会退出工做流,而gulp给出的错误信息,几乎没啥参考价值的。
好比有以下一个程序,监视a.js文件,当a.js文件发生改变的时候就压缩a.js。压缩后的文件放在dest文件夹下。
gulpfile.js代码以下
var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
var uglify = require("gulp-uglify");
var pump = require("pump");
gulp.task("compassJs", function() {
gulp.src("a.js")
.pipe(uglify())
.pipe(gulp.dest("dest"));
})
gulp.task("default", function() {
gulp.watch("a.js", ["compassJs"]);
})
复制代码
当咱们在a.js文件中不当心输入这么一段代码,gulp就会退出工做流。
import {} from "module";
复制代码
这不是咱们想要的,咱们但愿gulp能继续工做,这样当咱们删掉这段错误代码的时候,gulp能够继续压缩a.js文件,不须要咱们从新再命令行输入gulp命令
gulp有不少插件能够处理错误,这里抛砖引玉介绍两种,一种是用来处理js报错的,一种是用来处理sass报错的
5.1 js报错处理
推荐插件:pump
var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
var uglify = require("gulp-uglify");
var pump = require("pump");
gulp.task("compassJs", function() {
pump([
gulp.src("a.js"),
uglify(),
gulp.dest("test")
])
})
gulp.task("default", function() {
gulp.watch("a.js", ["compassJs"]);
})
复制代码
5.2 sass报错处理
推荐插件:plumber
咱们的任务是监视c.scss文件,当文件变更的时候就时时把它编译为css文件。
c.scss文件内容以下
html,
body {
width: 100px;
height: 100px;
}
复制代码
gulpfile.js代码以下
var gulp = require("gulp");
var sass = require("gulp-sass");
var plumber = require("gulp-plumber");
gulp.task("compilecss", function() {
gulp.src("c.scss")
.pipe(sass())
.pipe(gulp.dest("dest"));
})
gulp.task("default", function() {
gulp.watch("c.scss", ["compilecss"]);
})
复制代码
当咱们在c.scss文件中不当心输入一段错误代码,并保存的时候,gulp就会报错,并退出工做流
好比c.scss文件改为以下(多了一个img标签)。gulp就会退出工做流
html,
body {
width: 100px;
height: 100px;
}
img
复制代码
gulp报错:
[10:41:26] Using gulpfile ~\Desktop\博客内容\gulp的使用\gulp-test\gulpfile.js
[10:41:26] Starting 'default'...
[10:41:26] Finished 'default' after 11 ms
[10:41:33] Starting 'compilecss'...
[10:41:33] Finished 'compilecss' after 8.41 ms
events.js:160
throw er; // Unhandled 'error' event
^
Error: c.scss
Error: Invalid CSS after "img": expected "{", was ""
on line 7 of c.scss
>> img
---^
at options.error (C:\Users\寄居蟹黄粥\Desktop\博客内容\gulp的使用\gulp-test\node_modules\_node-sass@4.7.2@node-sass\lib\index.js:291:26)
复制代码
咱们可使用plumber来避免这种状况,修改后的gulpfile.js代码以下
var gulp = require("gulp");
var sass = require("gulp-sass");
var plumber = require("gulp-plumber");
gulp.task("compilecss", function() {
gulp.src("c.scss")
.pipe(plumber({
errorHandler: function(event) {
console.log(event.message);
this.emit('end');
}
}))
.pipe(sass())
.pipe(gulp.dest("dest"));
})
gulp.task("default", function() {
gulp.watch("c.scss", ["compilecss"]);
})
复制代码
这样当scss文件出错的时候,gulp只会在命令行打印错误,并不会退出工做流,监视工做还能够继续。
关于gulp网上还有其余插件和方法,刚兴趣能够自行google