1、基础储备
- Node常用的三种流:Readable、Writable、Transform
- 流之间用pipe来传递,pipe是流的实例方法
- Transform流通常用第三方模块through2来创建
- 常用Node的fs模块中fs.createReadStream(路径)创建Readable流,fs.createWriteStream(路径)创建Writable流
- Buffer类数据buffer可通过buffer.toString('utf-8')转为字符串String类型
2、基本结构
// 1、引入模块
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;
}
// 2、编写插件主函数 (处理文件)
function gulpPrefixer(prefixText) {
if (!prefixText) {
throw new PluginError(PLUGIN_NAME, 'Missing prefix text!');
}
prefixText = new Buffer(prefixText); // 将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;
}
// 3、暴露(export)插件的主函数
module.exports = gulpPrefixer;
3、主函数编写
- 判断插件的输入类型:Buffer Or Stream
Buffer类一般指该插件接收的数据是Buffer;Stream类该插件接收的数据是Stream,在使用gulp时,由gulp.src读取的文件传递给后续插件时默认都是Buffer,若想支持Stream,需显示调用gulp.src(路径,{buffer:false})。从大部分gulp插件使用方式来看,处理Buffer的情形占大多数。
file.isStream()
- file对象
保存读取的文件信息,file.contents是主要内容,也是一个流对象
- through2
通过through或through.obj创建的transform对象起着承前启后的作用。
承前:通过file对象获取上一个pipe来的数据
启后:对file对象进行改造,并通过this.push(file)和cb()向后一个pipe传递数据
4、插件实例
var through = require('through2');
var gutil = require('gulp-util');
var applySourceMap = require('vinyl-sourcemaps-apply');
var path = require('path');
var merge = require('merge');
var PluginError = gutil.PluginError;
module.exports = function (opt) {
function replaceExtension(path) {
path = path.replace(/\.coffee\.md$/, '.litcoffee');
return gutil.replaceExtension(path, '.js');
}
function transform(file, enc, cb) {
if (file.isNull()) return cb(null, file);
if (file.isStream()) return cb(new PluginError('gulp-coffee', 'Streaming not supported'));
var data;
var str = file.contents.toString('utf8'); // 1、这里开始,str就都是字符串了,可以采用正则进行处理了!
var dest = replaceExtension(file.path);
var options = merge({ // 2、合并选项
bare: false,
coffee: require('coffeescript'),
header: false,
sourceMap: !!file.sourceMap,
sourceRoot: false,
literate: /\.(litcoffee|coffee\.md)$/.test(file.path),
filename: file.path,
sourceFiles: [file.relative],
generatedFile: replaceExtension(file.relative)
}, opt);
try {
data = options.coffee.compile(str, options);
} catch (err) {
return cb(new PluginError('gulp-coffee', err));
}
if (data && data.v3SourceMap && file.sourceMap) {
applySourceMap(file, data.v3SourceMap);
file.contents = new Buffer(data.js);
} else {
file.contents = new Buffer(data); // 3、将处理后的字符串再转回buffer类型
}
file.path = dest;
cb(null, file); // 4、将处理后的文件向下一级传输
}
return through.obj(transform);
};
网友评论