buffer
什么是buffer
在stream那一节已经提到了buffer,但是并不能全面的表达buffer的概念。从我个人的理解角度讲,buffer的本质就是一个缓存区,这个缓存区用于交换数据。它不一定在stream中才使用,但是是使用最常见的。
大一个比方,有100000000000000吨水要从海洋运往沙漠,现在这个运输的过程中所有的水就是stream,水从大海流向了沙漠,但是是怎么流的呢?可不是直接整个砸进沙漠里,而是靠人们发明的一种神秘盒子进行运输,这个盒子在大海和沙漠之间以光速来回运动,把大海里的水按照每次200吨进行运输,但是由于一些情况,人们把盒子的容量调整到了1000吨,这个盒子就是buffer。
在读取一个大文件的时候,node不会一次性把所有的文件内容都读取到内存中,而是一点一点的读,读完的部分写入另外一个文件,这个过程就是stream的运动过程,那么这个“一点一点”的东西在哪里呢?就在buffer里,每次读一点,就放到buffer里,你可以对这个buffer进行改写,这样最终的文件跟原始文件就有非常大的区别。
使用buffer
如果你的插件依赖着一个基于 buffer 处理的库,你可能会选择让你的插件以 buffer 的形式来处理 file.contents
。让我们来实现一个在文件头部插入额外文本的插件:
var through = require('through2');
var gutil = require('gulp-util');
var PluginError = gutil.PluginError;
// 常量
const PLUGIN_NAME = 'gulp-prefixer';
// 插件级别的函数(处理文件)
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.isStream()) {
this.emit('error', new PluginError(PLUGIN_NAME, 'Streams are not supported!'));
return cb();
}
if (file.isBuffer()) {
file.contents = Buffer.concat([prefixText, file.contents]);
}
// 确保文件进入下一个 gulp 插件
this.push(file);
// 告诉 stream 引擎,我们已经处理完了这个文件
cb();
});
// 返回文件 stream
return stream;
};
// 导出插件主函数
module.exports = gulpPrefixer;
上述的插件可以这样使用:
var gulp = require('gulp');
var gulpPrefixer = require('gulp-prefixer');
gulp.src('files/**/*.js')
.pipe(gulpPrefixer('prepended string'))
.pipe(gulp.dest('modified-files'));
处理 stream
不幸的是,当 gulp.src 如果是以 stream 的形式,而不是 buffer,那么,上面的插件就会报错。如果可以,你也应该让他支持 stream 形式。请查看使用 Stream 处理 获取更多信息。
一些基于 buffer 的插件
- gulp-coffee
- gulp-svgmin
- gulp-marked
- gulp-svg2ttf