Grunt--I/O操作: 读取A → A.a() → 写出A → 读取A → A.b() → 写出A;

gulp--数据流:读取A → A.a() → A.b() → 写出A.

Part① 构建gulp

安装

npm install --global gulp   //全局安装
npm install --save-dev //项目内安装

gulp官网

四个接口

gulp.task();    //自定义任务
gulp.src(); //引入文件
gulp.dest(); //导出文件
gulp.watch(); //监听文件变化,调用任务

配置文件gulpfile.js

//引入插件
var gulp = require('gulp');
var less = require('gulp-less'); gulp.task('build:css', function() {
gulp.src(['../css/less/*.less',
'../css/less/**/*.less',
'!../css/less/test.less' //排除文件
])
.pipe(less().on('error', function (e){
console.error(e.message);
this.emit('end');
}))
.pipe(gulp.dest('../css'))
}); gulp.watch(['../css/less/*.less','../css/less/**/*.less'], ['build:css']);
gulp.task('default', ['build:css', 'watch']);

glob文件路径匹配详细文档

运行:

//运行default任务
gulp
//单独运行某个任务
gulp built:css

Part② 常用插件

插件

npm install gulp-less --save-dev //插件安装,同步到拓展程序列表

插件库

package.json

{
"name": "budiuhuanxin",
"version": "1.0.0",
"description": "",
"main": "gulpfile.js",
"dependencies": {},
"devDependencies": {
"gulp-autoprefixer": "^3.1.0",
"gulp-concat": "^2.6.0",
"gulp-css-spriter": "^0.3.3",
"gulp-css-spritesmith": "0.0.5",
"gulp-header": "^1.7.1",
"gulp-jshint": "^2.0.0",
"gulp-less": "^3.0.5",
"gulp-minify-css": "^1.2.4",
"gulp-plumber": "^1.1.0",
"gulp-postcss": "^6.1.0",
"gulp-rename": "^1.2.2",
"gulp-uglify": "^1.5.3",
"jshint": "^2.9.2",
"jshint-stylish": "^2.1.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

常用插件(脑图)

gulp-plumber : 监测工作流,报错,防止遇到错误时直接退出gulp。
var gulp = require('gulp');
var less = require('gulp-less');
var plumber = require('gulp-plumber'); gulp.task('build:css', function() {
gulp.src(['../css/less/*.less',
'../css/less/**/*.less',
'!../css/less/test.less' //排除文件
])
.pipe(plumber())
.pipe(less().on('error', function (e){
console.error(e.message);
this.emit('end');
}))
.pipe(gulp.dest('../css'))
});
gulp-rev : 文件名添加版本号,html更新引用
var rev = require('gulp-rev'); //添加文件版本号
var revCollector = require("gulp-rev-collector");//修改html文件引用 gulp.task('build:js', function() {
gulp.src(['src/js/*.js'])
.pipe(plumber())
.pipe(uglify()) //压缩
.pipe(addMin('dest/js/record.json', '.min'))
.pipe(rev()) //set hash key
.pipe(gulp.dest('dest/js/')) //文件导出
.pipe(rev.manifest()) //set hash key json
.pipe(gulp.dest('dest/js')); //dest hash key json
}); gulp.task('rev', function () {
return gulp.src(['dest/js/rev-manifest.json','src/html/*.html'])
.pipe(revCollector({
replaceReved: true,
}))
.pipe(gulp.dest('dest/html'));
});
gulp-autoprefixer:css自动前缀
var gulp = require('gulp');
var autoprefixer = require('gulp-autoprefixer'); gulp.task('default', function(){
gulp.src('src/app.css')
.pipe(autoprefixer({
browsers: ['last 2 versions'], //浏览器版本
cascade: false //未压缩时是否不换行
}))
.pipe(gulp.dest('dest/style'))
});
gulp-css-spritesmith:根据css文件自动生成雪碧图
var cssSprite = require('gulp-css-spritesmith'); //雪碧图

//雪碧图生成
gulp.task('autoSprite', function() {
var file_data = [
//每个数组表示需要编译的文件和对应切片图所在位置
['../css/indexBody.css', 'index-body'],
[['../css/budiuNavbar.css','../css/budiuBottom.css'], 'index-layout'],
['../css/goods.css', 'goods'],
['../css/widget_chat.css', 'widget_chat']
]; file_data.forEach(function(item, index, array) {
gulp.src(item[0])
.pipe(plumber())
.pipe(cssSprite({
// sprite背景图源文件夹,只有匹配此路径才会处理,默认 images/slice/
imagepath: ('../images/' + item[1]),
// 雪碧图输出目录,注意,会覆盖之前文件!默认 images/
spritedest: '../images/sprite',
// 替换后的背景路径,默认 ../images/
spritepath: '../images/sprite',
padding: 5
}))
.pipe(gulp.dest('../css'));
})
});
gulp-jshint:js语法检查工具
var jshint = require('gulp-jshint');    //js语法检查工具
var stylish = require('jshint-stylish'); //后台提醒样式 gulp.task('build:js', function() {
gulp.src(['../js/src/*.js'])
.pipe(plumber())
.pipe(jshint()) //语法检查
.pipe(jshint.reporter(stylish))
.pipe(uglify()) //压缩
.pipe(rename({ suffix: '.min' }))
.pipe(gulp.dest('../js'))
.pipe(reload({stream: true})); //自动刷新
});

Part③ 插件开发

官方教程

基本原则:

  1. 你的插件不应该去做一些现有 node 模块已经能很容易做到的事情(删除文件~)
  2. 你的插件应该只做一件事,并且做好。(比如:一个 JS 压缩插件不应该有一个加头部的选项)
  3. 你的插件不能去做一些其他插件做的事:(不应该去拼接,用 gulp-concat 去做,不应该去增加尾部,用 gulp-footer 去做)
  4. file.contents 的类型需要总是在输入输出中保持一致

插件开发两种处理方式

buffer:专门存放二进制数据的缓冲区;

stream: 文件流式数据(实际上属于buffer的一个特殊封装),适合用于处理大文件。

through2

var through = require('through2');
module.exports = function (options) {
return through.obj(function (file, enc, cb) {
// 主体实现忽略若干行
});
};

File封装

var File = require('vinyl');

var coffeeFile = new File({
cwd: "/",
base: "/test/",
path: "/test/file.coffee",
relative: "file.coffee",
contents: new Buffer("test = 123")
});

案例

实现功能:为js文件名添加指定后缀,记录与源文件名的对应关系,并在html中更新引用文件名。

var gutil = require('gulp-util');
var through = require('through2');
var PluginError = gutil.PluginError;
var fs = require('fs');
var _ = require('underscore'); var PLUGIN_NAME = 'gulp-addSuffix'; function refreshRecord(recordPath, data) {
fs.open(recordPath, 'a+', function(err, fd){
if(err) throw err; var oldDataObj = null;
var oldData = fs.readFileSync(recordPath, 'utf-8'); if (oldData.length === 0) {
oldDataObj = {};
} else {
oldDataObj = JSON.parse(oldData);
}
var files = _.keys(data);
files.forEach(function(key, n, arr) {
oldDataObj[key] = data[key];
});
var buffer = new Buffer(JSON.stringify(oldDataObj));
fs.write(fd, buffer, 0, buffer.length, 0, function(err, written, buffer){
if (err) {throw err}
});
});
}; //js 文件添加后缀并输出记录
var plugin = function(recordPath, insertString) {
if (!recordPath) {
this.emit('error', new PluginError(PLUGIN_NAME, ' missing path of record file'));
} else if (!insertString) {
this.emit('error', new PluginError(PLUGIN_NAME, ' missing insert content'));
} return through.obj(function (file, enc, cb) {
if (file.isNull()) {
this.push(file);
return cb();
} if (file.isStream()) {
this.emit('error', new PluginError(PLUGIN_NAME, 'Streaming not supported'));
return cb();
}
var oldName = file.relative;
var arr = oldName.split('.');
var newName = arr[0] + insertString + '.' + arr[1];
file.path = file.base + newName;
var record = {};
record[oldName] = newName;
refreshRecord(recordPath, record); this.push(file);
cb();
});
}
//修改html引用路径
plugin.html = function(recordPath) {
return through.obj(function(file, enc, cb) {
if (file.isNull()) {
this.push(file);
return cb();
}
if (file.isStream()) {
this.emit('error', new PluginError(PLUGIN_NAME, 'Streaming not supported'));
return cb();
}
var fileData = file.contents.toString('utf-8');
var recordData = fs.readFileSync(recordPath,'utf-8'); if (recordData.length === 0) {
this.push(file);
cb();
} else {
var recordObj = JSON.parse(recordData);
var keys = _.keys(recordObj);
keys.forEach(function(item, n, arr) {
var reg = new RegExp(item, 'g');
fileData = fileData.replace(reg, recordObj[item]);
});
file.contents = new Buffer(fileData);
this.push(file);
cb();
}
});
} module.exports = plugin;

gulp分享文档的更多相关文章

  1. 2019年最新总结,从程序员到CTO,从专业走向卓越,大牛分享文档pdf与PPT整理

    整理大牛分享文档如下,持续更新一线开发架构,技术文档 github链接 网易蜂巢公有容器云架构之路 新浪微博redis优化历程 微博Cache架构设计实践 Go在大数据开发中的经验总结 基于Go构建滴 ...

  2. gulp API 文档

    gulp.src(globs[, options]) 输出(Emits)符合所提供的匹配模式(glob)或者匹配模式的数组(array of globs)的文件. 将返回一个 Vinyl files  ...

  3. gulp使用文档

    gulp的优势 易于使用:通过代码优于配置的策略,Gulp让简单的任务简单,复杂的任务可管理. 构建快速:利用 Node.js 流的威力,你可以快速构建项目并减少频繁的 IO 操作. 插件高质:Gul ...

  4. iDoc「文档」功能强势升级!一键分享,即刻预览!(201903-1版本更新)

    小摹很想知道小伙伴们在面对众多杂乱的文档时,都是如何管理起来的呢?iDoc的「文档」功能,很多小伙伴还没有用起来,甚至都没有注意到iDoc还有这样一个功能.今天小摹就给大家介绍一下iDoc的「文档」功 ...

  5. 怎么保护PDF文档和扫描文件里的机密信息

    从事商务工作的人,必然要处理带有机密信息的文档,需要分享这些文档的时候,如何谨慎小心地对待那些机密信息,说到底还是取决于自己.分享文档的目的不同,对文档的保护类型和级别也不一样.例如,只有授权的读者才 ...

  6. 软件工程第4次作业------石墨文档Android客户端案例分析

    作业要求的博客链接:https://edu.cnblogs.com/campus/nenu/2016CS/homework/2505 分析产品:石墨文档Android客户端 第一部分 调研和评测 1. ...

  7. hadoop2.2.0_hbase0.96_zookeeper3.4.5全分布式安装文档下载

    本文档主要内容有: 1.hadoop 2.2.0 集群安装与部署 2.HBase 0.96 集群安装与部署 3.Zookeeper 3.4.5集群安装部署 备注:安装文档可能有所遗漏,后续将持续更新. ...

  8. Markdown文档使用

    Markdown使用 一.markdown标题:1级-6级 一级 #空格 二级 ##空格 三级 ###空格 ... 六级 ######空格 二.代码块 print("hello world! ...

  9. 作为Java开发工程师,如何高效优雅地编写接口文档

    作为一名优秀的Java开发工程师,编写接口文档向来是一件很头疼的事情.本来就被bug纠缠的很累了,你还让我干这? 其实,你可以试试ApiPost. ApiPost的定位是Postman+Swagger ...

随机推荐

  1. 用SQL描述树

    /*40条(1层) SELECT COUNT(*) FROM t01_mwfl WHERE AZFSDM=01 AND LEVEL=1 START WITH PID=0 CONNECT BY PRIO ...

  2. wojilu中的路由

    要看2个地方,一个是route.config,另一个是wojilu.Members.Sites.Domain.SiteMenu.config,这2部分综合起作用.

  3. JavaScript---网络编程(10)--DHTML技术演示(3)-多选框

    这节讲述多选框的使用,当然,肯定是结合css和Javascript一起的. checkbox的使用1: 演示代码: <html> <head> <meta http-eq ...

  4. nyoj 37回文串

    述所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如"aba".当然,我们给你的问题不会再简单到判断一个字符串是不是回文字符串.现在要求你,给你一个字符串,可 ...

  5. Bzoj 1726: [Usaco2006 Nov]Roadblocks第二短路 dijkstra,堆,A*,次短路

    1726: [Usaco2006 Nov]Roadblocks第二短路 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 969  Solved: 468[S ...

  6. GPU 的硬件基本概念,Cuda和Opencl名词关系对应

    GPU 的硬件基本概念 Nvidia的版本: 实际上在 nVidia 的 GPU 里,最基本的处理单元是所谓的 SP(Streaming Processor),而一颗 nVidia 的 GPU 里,会 ...

  7. ios UI 之间的切换方法,using prepareForSegue and not

    1, use prepareForSegue: - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { RWTDe ...

  8. .jar是什么文件?(转载)

    JAR(Java ARchive,Java 归档)是一种与平台无关的文件格式,可将多个文件合成一个文件.用户可将多个 Java applet 及其所需组件(.class 文件.图像和声音)绑定到 JA ...

  9. malloc()与calloc差别

    Both the malloc() and the calloc() functions are used to allocate dynamic memory. Each operates slig ...

  10. SSH框架总结(框架分析+环境搭建+实例源代码下载)

    首先,SSH不是一个框架,而是多个框架(struts+spring+hibernate)的集成,是眼下较流行的一种Web应用程序开源集成框架,用于构建灵活.易于扩展的多层Web应用程序. 集成SSH框 ...