Gulp-基于流的自动化构建工具
利用gulp,可以快速构建项目,并减少IO操作
gulp在项目开发过程中自动执行任务,方便对目标文件内容进行IO
官网使用指南http://www.gulpjs.com.cn/docs/getting-started/
Stream流
node.js
安装
- 安装node, node -v 检测安装成功
- (推荐cnmp) npm install cnpm -g –registry=https://registry.npm.taobao.org, cnmp -v显示版本号
- cnpm install gulp -g, gulp -v显示版本号
- 项目文件根目录新建package.json,
package.json是基于nodejs项目必不可少的配置文件,它是存放在项目根目录的普通json文件重点内容 - 进入项目文件夹
d:
cd cperson - cnpm init, 新建package.json,也可以自己手动新建
- 本地安装gulp插件,全局安装gulp是为了执行gulp任务,本地安装gulp则是为了调用gulp插件的功能
- 新建gulpfile.js,gulpfile.js是gulp的配置文件,放于根目录
- 运行gulp,执行认为
常用插件
sass的编译(gulp-sass)
less编译 (gulp-less)
重命名(gulp-rename)
自动添加css前缀(gulp-autoprefixer)
压缩css(gulp-clean-css)
js代码校验(gulp-jshint)
合并js文件(gulp-concat)
压缩js代码(gulp-uglify)
压缩图片(gulp-imagemin)
自动刷新页面(gulp-livereload,谷歌浏览器亲测,谷歌浏览器需安装livereload插件)
图片缓存,只有图片替换了才压缩(gulp-cache)
更改提醒(gulp-notify)
gulp是基于任务的
var gulp = require("gulp");
gulp.task("sync", function() {
console.log("同步");
});
gulp.task("async", function() {
setTimeout(function () {
console.log("异步");
done();
}, 2000);
});
运行gulp sync, gulp async
D:\Cperson\front-end\gulp>gulp sync1
[18:32:50] Using gulpfile D:\Cperson\front-end\gulp\gulpfile.js
[18:32:50] Starting 'sync1'...
同步
[18:32:50] Finished 'sync1' after 394 μs
D:\Cperson\front-end\gulp>gulp async
[18:35:01] Using gulpfile D:\Cperson\front-end\gulp\gulpfile.js
[18:35:01] Starting 'async'...
[18:35:01] Finished 'async' after 838 μs
异步
D:\Cperson\front-end\gulp\gulpfile.js:10
done();
^
gulp.task可以有依赖,第二个参数传入数组,数组里会*并行处理* gulp.task(“sync”, [“async”, “sync1”, “sync2”], function() { console.log(“done”); });
处理文件内容
从源src到目的dest,将文件内容和内联样式、脚本进行压缩,完成.html的优化优化
- 页面 js 存放在 ./static/js 下,公共的库放在 ./static/js/lib 下,公共库只压缩不合并,页面 js 压缩并合并。
- 页面 css 存放在 ./static/css 下,公共的css放在 ./static/css/common 下,公共 css 只压缩不合并,页面 css 压缩并合并。
- 图片资源中小于3kb的图片以 base64 方式内联,图片放在 ./static/img 下。
压缩 js
function minifyAndComboJS(name, encode, files){
var fs = require("fs");
var UglifyJS = require("uglify-js");
var content = "";
files.forEach(function(js){
var minified = UglifyJS.minify(js).code;
content += minified;
});
if(content){
var combo = "static/js/" + name;
}
fs.writeFileSync(combo, content);
gulp.src(combo)
.pipe(gulp.dest("./dist/static/js"));
}
压缩
js gulp.task("build-js-lib", function(){
gulp.src("./static/js/lib/**/*.js")
.pipe(through.obj(function(file, encode, cb) {
var UglifyJS = require("uglify-js");
var contents = file.contents.toString(encode);
var minified = UglifyJS.minify(contents,
{fromString:true}).code;
file.contents = new Buffer(minified, encode);
cb(null, file, encode);
}))
.pipe(gulp.dest("./dist/static/js/lib"));
});
css
function minifyAndComboCSS(name, encode, files){
var fs = require("fs");
var CleanCSS = require("clean-css");
var content = "";
files.forEach(function(css){
var contents = fs.readFileSync(css, encode);
var minified = new CleanCSS().minify(contents).styles;
content += minified;
});
if(content){
var combo = "static/css/" + name;
}
fs.writeFileSync(combo, content);
gulp.src(combo)
.pipe(gulp.dest("./dist/static/css"));
}
压缩公共 css
gulp.task("build-common-css", function(){
gulp.src("./static/css/common/**/*.css")
.pipe(through.obj(function(file, encode, cb) {
var CleanCSS = require("clean-css");
var contents = file.contents.toString(encode);
var minified = new CleanCSS().minify(contents).styles;
file.contents = new Buffer(minified, encode);
cb(null, file, encode);
}))
.pipe(gulp.dest("./dist/static/css/common"));
});
处理图片
//内联小图片
var imgs = $("img");
for(var i = 0; i < imgs.length; i++){
var img = $(imgs[i]);
var src = img.attr("src");
if(/^static\/img/.test(src)){
var stat = fs.statSync(src);
var ext = require("path").parse(src).ext;
if(stat.size <= 3000){
var head = ext === ".png" ? "data:image/png;base64," : "data:image/jpeg;base64,";
var datauri = fs.readFileSync(src).toString("base64");
img.attr("src", head + datauri);
}
}
}
压缩 HTML
contents = $.html();
//压缩 HTML
var HTMLMinifier = require("html-minifier").minify;
var minified = HTMLMinifier(contents, {
minifyCSS: true,
minifyJS: true,
collapseWhitespace: true,
removeAttributeQuotes: true
});
然后,在处理 index.html 的时候,我们可以使用 cheerio 来解析文件,将要处理的外链从文档中提取出来。
提取 js 和 css 外链处理
var $ = require("cheerio").load(contents, {decodeEntities: false});
//处理外链 css
var links = $("link");
var cssToCombo = [];
for(var i = 0; i < links.length; i++){
var link = $(links[i]);
if(link.attr("rel") === "stylesheet"){
var href = link.attr("href");
if(/^static\/css\/(?!common)/.test(href)){
cssToCombo.push(href);
if(cssToCombo.length == 1){
link.attr("href", "static/css/index.min.css");
}else{
link.remove();
}
}
}
}
minifyAndComboCSS("index.min.css", encode, cssToCombo);
//处理外链 js
var scripts = $("script");
var jsToCombo = [];
for(var i = 0; i < scripts.length; i++){
var s = $(scripts[i]);
//判断script标签确实是js
if(s.attr("type") == null
|| s.attr("type") === "text/javascript"){
var src = s.attr("src");
if(src){
//外链的js,默认只处理以/static/开头的资源
if(/^static\/js\/(?!lib)/.test(src)){
jsToCombo.push(src);
if(jsToCombo.length == 1){
s.attr("src", "static/js/index.min.js");
}else{
s.remove();
}
}
}
}
}
minifyAndComboJS("index.min.js", encode, jsToCombo);
API
gulp.src(glob[,options])输出匹配模式的文件
gulp.src(‘client/templates/*.jade’)
.pipe(jade())
.pipe(minify())
.pipe(gulp.dest(‘build/minified_templates’));glob语法规则
*匹配任意 0 或多个任意字符
? 匹配任意一个字符
[…] 若字符在中括号中,则匹配。若以 ! 或 ^ 开头,若字符不在中括号中,则匹配
!(pattern|pattern|pattern) 不满足括号中的所有模式则匹配
?(pattern|pattern|pattern) 满足 0 或 1 括号中的模式则匹配
+(pattern|pattern|pattern) 满足 1 或 更多括号中的模式则匹配
*(a|b|c) 满足 0 或 更多括号中的模式则匹配
@(pattern|pat*|pat?erN) 满足 1 个括号中的模式则匹配
** 跨路径匹配任意字符gulp.dest(path[,options])
gulp.src('./client/templates/*.jade')
.pipe(jade())
.pipe(gulp.dest('./build/templates'))
.pipe(minify())
.pipe(gulp.dest('./build/minified_templates'));
能被 pipe 进来,并且将会写文件。并且重新输出(emits)所有数据,因此你可以将它 pipe 到多个文件夹。如果某文件夹不存在,将会自动创建它
- gulp.task(name[, deps], fn)
gulp.task('something',function(){
})
task 将以最大的并发数执行,你可以添加依赖
var gulp = require('gulp');
// 返回一个 callback,因此系统可以知道它什么时候完成
gulp.task('one', function(cb) {
// 做一些事 -- 异步的或者其他的
cb(err); // 如果 err 不是 null 或 undefined,则会停止执行,且注意,这样代表执行失败了
});
// 定义一个所依赖的 task 必须在这个 task 执行之前完成
gulp.task('two', ['one'], function() {
// 'one' 完成后
});
gulp.task('default', ['one', 'two']);
- 监视文件,并且可以在文件发生改动时候做一些事情
gulp.watch(glob[,opts], tasks)
var watcher = gulp.watch('js/**/*.js', ['uglify','reload']);
watcher.on('change', function(event) {
console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
});
gulp.watch(glob[,opts, cb])
gulp.watch('js/**/*.js', function(event) {
console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
});