gulpプラグインを書くにはどうすればいいですか?

3881 ワード

1、基礎備蓄

  • Nodeでよく使用される3つのストリーム:Readable、Writable、Transform
  • ストリーム間はpipeによって伝達され、pipeはストリームの例示的な方法
  • である.
  • Transformフロー
  • を作成するために、サードパーティ製モジュールthrough 2が一般的に使用されます.
  • 常用ノードの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オブジェクトは、読み込むファイル情報を保存する.contentsは主なコンテンツであり、ストリームオブジェクト
  • でもある.
  • through 2は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);
    };