Gulp-基于流的自动化构建工具
利用gulp,可以快速构建项目,并减少IO操作
gulp在项目开发过程中自动执行任务,方便对目标文件内容进行IO
官网使用指南https://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...'); });