stream
极力推荐让你所写的插件支持 stream。这里有一些关于让插件支持 stream 的一些有用信息。
请确保使用处理错误的最佳实践,并且加入一行代码,使得 gulp 能在转换内容的期间在捕获到第一个错误时候正确报出错误。
什么是stream
概念比较复杂,简单的说,它就是我们经常说的“流”,比如“流媒体”“流式文件”。这种文件的特征就是可以“流”式传输,这里用双引号引起来的“流”,就是stream。
那么什么是流式传输呢?就是一个文件不是一次性传输,而是像流水一样,慢慢传,可以分成一段一段的,而这一段一段的东西,我们就可以成为buffer,但是buffer不是stream,buffer只是stream附带了一种东西。
比较典型的是视频,我们看网络视频的时候,不会等到整个视频都缓存到浏览器了才开始观看,而是打开浏览器的时候,视频就已经流式下载,下载到一定的量的时候就可以开始播放。
而在node的体系里,读取文件可以以stream的形式进行读取,读取过程中会产生buffer。除了读,stream还可以被写入。但是stream不是文件本身,而是文件的内容的某种形式,所以只要文件的内容还是以stream的形式存在,那这个文件相当于只有灵魂没有肉体。
使用stream
让我们来实现一个用于在文件头部插入一些文本的插件,这个插件支持 file.contents
所有可能的形式。
var through = require('through2');
var gutil = require('gulp-util');
var PluginError = gutil.PluginError;
// 常量
const PLUGIN_NAME = 'gulp-prefixer';
function prefixStream(prefixText) {
var stream = through();
stream.write(prefixText);
return stream;
}
// 插件级别函数 (处理文件)
function gulpPrefixer(prefixText) {
if (!prefixText) {
throw new PluginError(PLUGIN_NAME, 'Missing prefix text!');
}
prefixText = new Buffer(prefixText); // 预先分配
// 创建一个让每个文件通过的 stream 通道
var stream = through.obj(function(file, enc, cb) {
if (file.isBuffer()) {
this.emit('error', new PluginError(PLUGIN_NAME, 'Buffers not supported!'));
return cb();
}
if (file.isStream()) {
// 定义转换内容的 streamer
var streamer = prefixStream(prefixText);
// 从 streamer 中捕获错误,并发出一个 gulp的错误
streamer.on('error', this.emit.bind(this, 'error'));
// 开始转换
file.contents = file.contents.pipe(streamer);
}
// 确保文件进去下一个插件
this.push(file);
// 告诉 stream 转换工作完成
cb();
});
// 返回文件 stream
return stream;
}
// 暴露(export)插件的主函数
module.exports = gulpPrefixer;
上面的插件可以像这样使用:
var gulp = require('gulp');
var gulpPrefixer = require('gulp-prefixer');
gulp.src('files/**/*.js', { buffer: false })
.pipe(gulpPrefixer('prepended string'))
.pipe(gulp.dest('modified-files'));
一些使用 stream 的插件
- gulp-svgicons2svgfont