node.jsgulpthrough2

Creating multiple files from Vinyl stream with Through2


I've been trying to figure this out by myself, but had no success yet. I don't even know how to start researching for this (though I've tried some Google searchs already, to no avail), so I decided to ask this question here.

Is it possible to return multiple Vinyl files from a Through2 Object Stream?

My use case is this: I receive an HTML file via stream. I want to isolate two different sections of the files (using jQuery) and return them in two separate HTML files. I can do it with a single section (and a single resulting HTML file), but I have absolutely no idea on how I would do generate two different files.

Can anyone give me a hand here? Thanks in advance.


Solution

  • The basic approach is something like this:

    1. Create as many output files from your input file as you need using the clone() function.

    2. Modify the .contents property of each file depending on what you want to do. Don't forget that this is a Buffer, not a String.

    3. Modify the .path property of each file so your files don't overwrite each other. This is an absolute path so use something like path.parse() and path.join() to make things easier.

    4. Call this.push() from within the through2 transform function for every file you have created.

    Here's a quick example that splits a file test.txt into two equally large files test1.txt and test2.txt:

    var gulp = require('gulp');
    var through = require('through2').obj;
    var path = require('path');
    
    gulp.task('default', function () {
      return gulp.src('test.txt')
        .pipe(through(function(file, enc, cb) {
           var c = file.contents.toString();
           var f = path.parse(file.path);
           var file1 = file.clone();
           var file2 = file.clone();
           file1.contents = new Buffer(c.substring(0, c.length / 2));
           file2.contents = new Buffer(c.substring(c.length / 2));
           file1.path = path.join(f.dir, f.name + '1' + f.ext);
           file2.path = path.join(f.dir, f.name + '2' + f.ext);
           this.push(file1);
           this.push(file2);
           cb();
        }))
        .pipe(gulp.dest('out'));
    });