整理一些网上查到的资料(已注明出处、侵删),再对gulp相关进行补充。

use-gulp
gulp插件网
awesome-gulp
gulp中文入门教程

1. 为静态文件添加 MD5 指纹^foot1

使用 Gulp 自动对 HTML 中引用的静态文件添加MD5 指纹戳,有效解决旧文件缓存,新文件无法更新的问题。

MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被”压缩”成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。

gulp-rev

Static asset revisioning by appending content hash to filenames: unicorn.css → unicorn-d41d8cd98f.css

完美规避更新时短时间内客户端请求结果不一致的问题,但易造成文件冗余。

gulp-rev-append

转换后变为<script src='BearD01001.min.js?rev=366dc531e1'></script>

每次更新不会产生新文件,有效避免文件冗余,但更新时短时间内,客户端请求到的静态文件可能不一致。

$ npm install --save-dev gulp-rev --save-dev
$ npm install --save-dev gulp-rev-append --save-dev
1
2
3
4
5
6
7
8
9
10
const gulp = require('gulp');
const rev = require('gulp-rev');
// const revAppend = require('gulp-rev-append');

gulp.task('default', () =>
gulp.src('src/*.css')
.pipe(rev())
// .pipe(revAppend())
.pipe(gulp.dest('dist'))
);

2. JS / CSS 合并

gulp-concat

合并javascript文件,减少网络请求,减少冗余

$ npm install gulp-concat --save-dev 
1
2
3
4
5
6
7
8
var concat = require('gulp-concat');

gulp.task('scripts', function() {
//return gulp.src('./lib/*.js')
return gulp.src(['./lib/file3.js', './lib/file1.js', './lib/file2.js'])
.pipe(concat('all.js')) //合并后的文件名
.pipe(gulp.dest('./dist/'));
});

3. CSS小图标转码为 base64 编码

Base64

Base64是一种基于64个可打印字符来表示二进制数据的表示方法。
Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据。包括MIME的email、在XML中存储复杂数据。例如迅雷的“专用地址”也是用 Base64 加密的。

图片的 base64 编码就是可以将一副图片数据编码成一串字符串,使用该字符串代替图像地址。
如果图片足够小且因为用处的特殊性无法被制作成雪碧图(CssSprites),在整个网站的复用性很高且基本不会被更新,此时使用 base64 编码传输图片。(例如平铺图作为background-image)

图片的下载始终都要向服务器发出请求,将 CSS 中引用的小图标转码为 base64 编码的 data URI 字符串,减少额外的 http 请求数。

显示图片的 base64 编码
在 chrome 下新建一个窗口,然后把要转化的图片直接拖入浏览器,打开控制台,点 Source,如下图所示,点击图片,右侧就会显示该图片的 base64 编码。^foot2

使用 Base64 不代表性能优化
使用 Base64 的好处是能够减少一个图片的 HTTP 请求,代价则是 CSS 文件体积的增大,引起CRP 的阻塞。页面解析 CSS 生成的 CSSOM 时间增加。

CRP(Critical Rendering Path,关键渲染路径):当浏览器从服务器接收到一个HTML页面的请求时,到屏幕上渲染出来要经过很多个步骤。浏览器完成这一系列的运行,或者说渲染出来我们常常称之为“关键渲染路径”。

CSS 对象模型 (CSSOM):CSSOM是一个建立在web页面上的 CSS 样式的映射,它和DOM类似,但是只针对CSS而不是HTML。

gulp-base64

$ npm install gulp-base64 --save-dev
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var gulp = require('gulp');
var base64 = require('./build/gulp-base64');

//basic example
gulp.task('build', function () {
return gulp.src('./css/*.css')
.pipe(base64())
.pipe(concat('main.css'))
.pipe(gulp.dest('./public/css'));
});
...
//example with options
gulp.task('build', function () {
return gulp.src('./css/*.css')
.pipe(base64({
baseDir: 'public',
extensions: ['svg', 'png', /\.jpg#datauri$/i],
exclude: [/\.server\.(com|net)\/dynamic\//, '--live.jpg'],
maxImageSize: 8*1024, // bytes,
deleteAfterEncoding: false,
debug: true
}))
.pipe(concat('main.css'))
.pipe(gulp.dest('./public/css'));
});

在 extensions 参数中可以使用正则(例如:/\.jpg#datauri$/i)匹配带有指定 hash 的引用文件,这样在开发过程中就可以通过在文件末尾加上对应的 hash (例如: background-image: url(./images/icon.jpg#datauri); )手动指定哪些文件转码成 data URI。^foot3

4. gulp-plumber构建异常捕获^foot3

gulp-plumber

$ npm install gulp-plumber --save-dev
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var gulp    = require('gulp'),
gutil = require('gulp-util'),
babel = require('gulp-babel'),
concat = require('gulp-concat'),
plumber = require('gulp-plumber');

gulp.task('build', () => {
gulp.src('./_src/js/*.js')
// 最先 pipe 到 plumber 中,以便出现异常前准备捕获
.pipe(plumber({ errHandler: e => {
gutil.beep(); // 哔~ 的响一声
gutil.log(e); // 抛出异常
}}))
.pipe(babel())
.pipe(concat('all.js'))
.pipe(gulp.dest('./public/js'));
});

5. grunt&gulp

1.插件很难遵守单一责任原则。

2.用插件做一些本来不需要插件来做的事情。

3.试图用配置文件完成所有事,结果混乱不堪。

4.落后的流程控制产生临时文件(夹),导致性能滞后。

相比之下gulp特点
1.构建脚本是代码而不是配置文件。

2.使用标准库(node.js standard library)来编写。

3.插件简单且只负责完成一件事

4.任务都以最大的并发数来执行。

5.输入/输出(I/O)基于“流式”。

6. npm scripts

我为何放弃Gulp与Grunt,转投npm scripts(上)
我为何放弃Gulp与Grunt,转投npm scripts(下)
npm in action