node.jsgulpnode.js-stream

How to manipulate by relative output path of Vinyl file inside gulp pipeline?


In the below gulp task, targetFile.relative (property of Vinyl instance) will bee concatenated to dest path. For example if targetFile.relative is images/icons/HamburgerMenu__Icon.svg, output path will be <Project absolute path>/dest/images/icons/HamburgerMenu__Icon.svg

gulp.src('source/singletonComponents/**/*.+(png|jpg|gif|svg)')
    .pipe(gulp.dest( targetVinylFile => {          
      return 'dest'
    }));

What if we want to change targetFile.relative? For example, we want to output to dest/pictures/icons/HamburgerMenu__Icon.svg, but we don't want to rename source forlder images to pictures.

Because in this question we are considering the output path manipulation, please, not not touch source files/directories, and also 'source/singletonComponents/**/*.+(png|jpg|gif|svg)' in solutions.

And also: it you think that it's not possible, please answer such as.


Solution

  • With the specific example you gave, you can trivially get the effect you wan with:

    gulp.src('source/singletonComponents/images/icons/**/*.+(png|jpg|gif|svg)')
        .pipe(gulp.dest('dest/pictures/icons'));
    

    The pattern above changes what is stored in the relative field of the files. They are now all relative to source/singletonComponents/images/icons/, which allows you in gulp.dest to alter the path to get the result you want.

    If your real situation is more complicated you can manipulate the paths yourself through pipe:

    const gulp = require("gulp");
    const map = require("map-stream");
    const path = require("path");
    
    gulp.task("default", () =>
              gulp.src('source/singletonComponents/**/*.+(png|jpg|gif|svg)')
              .pipe(map((file, cb) => {
                file.path = path.join(file.base, file.relative.replace(/images/, "pictures"));
                cb(null, file);
              }))
              .pipe(gulp.dest('dest')));
    

    Note that Gulp 4 does not allow modifying file.relative directly. You get an error if you try to do it. That's because it is derived from file.base and file.path. So you have to modify one of these or both if you want to change file.relative. Remember that file.path is the absolute path of the file. That's why we joint file.base to the modified value of file.relative.