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

results matching ""

    No results matching ""