Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explanation of node paths with respect to gulp .pipe()

My question begins with another one, asked here: Gulp: How to set dest folder relative to processed file (when using wildcards)?

I have a similar situation, where I need to make compressed versions on a per-module basis. That is, I have

ui/test/one/script1.js
ui/test/two/script2.js

and I need to have gulp copy the files into relative directories so I end up with

ui/test/one/compressed/script1.js
ui/test/two/compressed/script2.js

I have the following gulp task

gulp.task('test', function() {
    return gulp.src('ui/test/**/*.js')
        .pipe(gulp.dest(function(file) {
            return path.join(path.dirname(file.path), 'compressed');
        }));
});

However, when I run it, I end up with

ui/test/one/compressed/one/script1.js
ui/test/two/compressed/two/script2.js

I see in the docs where it says

cwd - Specify the working directory the folder is relative to. base - Specify the folder relative to the cwd. Default is where the glob begins. This is used to determine the file names when saving in .dest()

I have several questions, specifically about .src(), .dest() and the path and file objects. (That is, although I'm sure there are other ways to achieve my end goal, this question is specifically about the behavior of the sample gulp code above and the functions mentioned so I can understand their behavior and API better.)

Questions

  • When the docs say "the working directory the folder is relative to", what folder is this?
  • on that same note, in relation to this comment and the spot in the docs where it says "base - Specify the folder relative to the cwd. Default is where the glob begins" what does "where the glob begins" mean? My understanding of 'glob' is that it's the whole string, but does it really mean a * character within that string? So for 'some/folder/**/*.js' with a file existing at some/folder/a/b/c/foo.js I'm not sure if the base is some/folder/, some/folder/a/, or some/folder/a/b/c/?
  • is there a way to say <where the glob begins> + '..'?
  • where I'm saying path.join(path.dirname(file.path), 'compressed') I'm assuming that's producing C:\blah\ui\test\one\compressed. It follows then that whatever's decided the actual name of the file has one\script1.js in mind. How do I change its mind so that it's only thinking of script1.js?

Note: I tried doing the following (using gulp-debug)

gulp.task('test', function() {
    return gulp.src('ui/test/**/*.js', {cwd: './'})
        .pipe(debug({minimal: false}))
        .pipe(rename(function(path) {
            path.basename =     path.basename.substring(path.basename.lastIndexOf('\\') + 1);
        }))
        .pipe(debug({minimal: false}))
        .pipe(gulp.dest(function(file) {
            return path.join(path.dirname(file.path), 'compressed');
        }));
});

The console has the following output for this version of the task:

cwd: ./
base: C:\blah\ui\test
path: C:\blah\ui\test\one\script1.js

cwd: ./
base: C:\blah\ui\test
path: C:\blah\ui\test\one\script1.js

cwd: ./
base: C:\blah\ui\test
path: C:\blah\ui\test\two\script2.js

cwd: ./
base: C:\blah\ui\test
path: C:\blah\ui\test\two\script2.js

So it appears that the rename has no effect on the path. I also tried modifying path.dirname in the rename pipe, but couldn't find anything that would have the desired effect of simply removing the spurious directory name from the final output path.

My last question, then, is what exactly do path.basename and path.dirname contain for the path object passed to the rename function?

edit: I found this on how to debug gulp tasks. Doing so with a debugger; statement placed in the rename function allowed me to inspect the path object, which looks like this:

{
  basename: "script1",
  dirname: "one",
  extname: ".js"
}

Setting path.dirname to '' in the rename results in

ui/test/compressed/script1.js
ui/test/compressed/script2.js

so it may be that rename() itself is not useful for what I need. It's looking more like the base option to .src() may be where the key lies, but the docs are rather terse.

like image 337
jinglesthula Avatar asked Jul 09 '15 17:07

jinglesthula


1 Answers

Question 1:

gulp.src('ui/test/**/*.js')

This line is setting '/ui/test/' as your root directory ('working file directory'), as it is the base of your glob pattern. That's why the 'relative paths' fed to dest were 'one/script1.js' and 'two/script2.js'.

Question 2:

By glob, the docs are referring to your '**/*.js' pattern. So the base of your glob is the same thing that it's using as your root directory, '/ui/test/', which in this case means the same things as "folder relative to the cwd".

Question 3:

The 'base' property for each path is being set similar to the glob2base module for each file coming from the gulp.src stream.

glob2base(new glob.Glob('/ui/test/**/*.js')) + '..';

is the same as

file.base + '..';

if that makes sense to you.

Question 4:

I assume you're using gulp-rename in your second section of code. So this should solve your problem.

gulp.src('ui/test/**/*.js')
    .pipe(rename(function(path){
        path.basename = 'compressed/' + path.basename;
    })
    .pipe(gulp.dest(function(file) {
        return file.base;
    }));

The other options that can be passed to gulp.src can be found here, but I don't think any of them directly solve what you're trying to do. gulp.src doesn't seem to expect you to hack in a new directory in the middle of each path, so renaming is the simplest solution.

I don't blame you for having issues figuring out the docs. I had to jump between three or four different github pages to piece together everything going on. Hope you learned as much as I did from this.

like image 117
pokkanome Avatar answered Sep 30 '22 00:09

pokkanome