gulpgulp-rename

Triggering separate gulp tasks for subfolders in different paths


I am using Gulp to store multiple SVG files into SVG storages which are later reused in order to maximize performance. However, I am now using a rather interesting folder structure where the paths contain interchangeable fixed and dynamic parts.

Let me illustrate. Here is the folder structure I am using. The app/images/products folder contains folders named productA, productB etc. which again contain a subfolder called color-sprites full of SVG files ready to get combined into a single file and stored in build/images/products/{product name}/color-sprites.svg.

root/
    |_ gulpfile.js
    |_ app 
        |_ images
            |_ products
                |_ **productA**
                    |_ color-sprites
                        |_ sprite1.svg
                        |_ sprite2.svg
                        |_ ...
    |_ build
        |_ images
            |_ products
                |_ **productA**
                    |_ color-sprites.svg

Here is a simplified version of the code I am trying to use to accomplish what I need (take note that rename is an instance of gulp-rename).

gulp.task('svg-color-sprites', function () {
    return gulp.src('app/images/products/**/color-sprites/*.+(svg)')
        .pipe(svgMin())
        .pipe(svgStore())
        .pipe(rename(...))
        .pipe(gulp.dest('build/images/'));
});

The problem is that I am not exactly sure how to access current stream parameters in order to construct a target with gulp-rename because running the gulpfile.js like this results in taking the first parent element of the path before * or ** which again results in creating a file called products.svg in build/images/. I've seen a couple of examples which use path to access the basename, relative path etc. but I am not sure how to use it in the context of gulp streams.


Solution

  • The way you're doing things now will create one combined SVG for all of your SVGs, not one combined SVG per product. In fact if you have two files like this:

    productA/color-sprites/sprite1.png
    productB/color-sprites/sprite1.png
    

    the whole thing will fail because gulp-svgstore expects file names to be unique.

    What you need to do is have one gulp stream per product that each generates one combined SVG.

    That means you need to iterate over all the directories in your products folder, initialize one stream per directory, then merge them so you can return one single stream from your task.

    The easiest way to get all the directories in your products folder is to use glob and merging streams is made really simple with merge-stream.

    var glob = require('glob');
    var merge = require('merge-stream');
    var path = require('path');
    
    gulp.task('svg-color-sprites', function () {
      return merge(glob.sync('app/images/products/*').map(function(productDir) {
        var product = path.basename(productDir);
        return gulp.src(productDir + '/color-sprites/*.+(svg)')
          .pipe(svgMin())
          .pipe(svgStore())
          .pipe(gulp.dest('build/images/products/' + product));
      }));
    });
    

    Since gulp-svgstore automatically names the resulting combined SVG after the base folder you don't even need to use gulp-rename at all. The combined SVG file will automatically be named color-sprites.svg.