# 将 buffer 变为 stream (内存中的内容)
有时候,你会需要这样一个 stream,它们的内容保存在一个变量中,而不是在一个实际的文件中。换言之,怎么不使用 `gulp.src()` 而创建一个 'gulp' stream。
我们来举一个例子,我们拥有一个包含 js 库文件的目录,以及一个包含一些模块的不同版本文件的目录。编译的目标是为每个版本创建一个 js 文件,其中包含所有库文件以及相应版本的模块文件拼接后的结果。
逻辑上我们将把这个拆分为如下步骤:
* 载入库文件
* 拼接库文件的内容
* 载入不同版本的文件
* 对于每个版本的文件,将其和库文件的内容拼接
* 对于每个版本的文件,将结果输出到一个文件
想象如下的文件结构:
```
├── libs
│ ├── lib1.js
│ └── lib2.js
└── versions
├── version.1.js
└── version.2.js
```
你应该要得到这样的结果:
```
└── output
├── version.1.complete.js # lib1.js + lib2.js + version.1.js
└── version.2.complete.js # lib1.js + lib2.js + version.2.js
```
一个简单的模块化处理方式将会像下面这样:
```
var gulp = require('gulp');
var runSequence = require('run-sequence');
var source = require('vinyl-source-stream');
var vinylBuffer = require('vinyl-buffer');
var tap = require('gulp-tap');
var concat = require('gulp-concat');
var size = require('gulp-size');
var path = require('path');
var es = require('event-stream');
var memory = {}; // 我们会将 assets 保存到内存中
// 载入内存中文件内容的任务
gulp.task('load-lib-files', function() {
// 从磁盘中读取库文件
return gulp.src('src/libs/*.js')
// 将所有库文件拼接到一起
.pipe(concat('libs.concat.js'))
// 接入 stream 来获取每个文件的数据
.pipe(tap(function(file) {
// 保存文件的内容到内存
memory[path.basename(file.path)] = file.contents.toString();
}));
});
gulp.task('load-versions', function() {
memory.versions = {};
// 从磁盘中读取文件
return gulp.src('src/versions/version.*.js')
// 接入 stream 来获取每个文件的数据
.pipe( tap(function(file) {
// 在 assets 中保存文件的内容
memory.versions[path.basename(file.path)] = file.contents.toString();
}));
});
gulp.task('write-versions', function() {
// 我们将不容版本的文件的名字保存到一个数组中
var availableVersions = Object.keys(memory.versions);
// 我们创建一个数组来保存所有的 stream 的 promise
var streams = [];
availableVersions.forEach(function(v) {
// 以一个假文件名创建一个新的 stream
var stream = source('final.' + v);
// 从拼接后的文件中读取数据
var fileContents = memory['libs.concat.js'] +
// 增加版本文件的数据
'\n' + memory.versions[v];
streams.push(stream);
// 将文件的内容写入 stream
stream.write(fileContents);
process.nextTick(function() {
// 在下一次处理循环中结束 stream
stream.end();
});
stream
// 转换原始数据到 stream 中去,到一个 vinyl 对象/文件
.pipe(vinylBuffer())
//.pipe(tap(function(file) { /* 这里可以做一些对文件内容的处理操作 */ }))
.pipe(gulp.dest('output'));
});
return es.merge.apply(this, streams);
});
//============================================ 我们的主任务
gulp.task('default', function(taskDone) {
runSequence(
['load-lib-files', 'load-versions'], // 并行载入文件
'write-versions', // 一旦所有资源进入内存便可以做写入操作了
taskDone // 完成
);
});
//============================================ 我们的监控任务
// 只在运行完 'default' 任务后运行,
// 这样所有的资源都已经在内存中了
gulp.task('watch', ['default'], function() {
gulp.watch('./src/libs/*.js', function() {
runSequence(
'load-lib-files', // 我们只需要载入更改过的文件
'write-versions'
);
});
gulp.watch('./src/versions/*.js', function() {
runSequence(
'load-versions', // 我们只需要载入更改过的文件
'write-versions'
);
});
});
```
- gulp 中文文档
- 入门指南
- gulp API 文档
- 编写插件
- 指导
- 使用 buffer
- 使用 Stream 处理
- 测试
- FAQ
- gulp 技巧集
- 整合 streams 来处理错误
- 删除文件和文件夹
- 使用 watchify 加速 browserify 编译
- 增量编译打包,包括处理整所涉及的所有文件
- 将 buffer 变为 stream (内存中的内容)
- 在 gulp 中运行 Mocha 测试
- 仅仅传递更改过的文件
- 从命令行传递参数
- 只重新编译被更改过的文件
- 每个文件夹生成单独一个文件
- 串行方式运行任务,亦即,任务依赖
- 拥有实时重载(live-reloading)和 CSS 注入的服务器
- 通过 stream 工厂来共享 stream
- 指定一个新的 cwd (当前工作目录)
- 分离任务到多个文件中
- 使用外部配置文件
- 在一个任务中使用多个文件来源
- Browserify + Uglify2 和 sourcemaps
- Browserify + Globs
- 同时输出一个压缩过和一个未压缩版本的文件
- 改变版本号以及创建一个 git tag
- Swig 以及 YAML front-matter 模板