关于 gulp .pipe() 中节点路径的解释

8
我的问题源自另一个问题,它在这里提出:Gulp: How to set dest folder relative to processed file (when using wildcards)?
我有一个类似的情况,我需要按模块生成压缩版本。也就是说,我有一些模块。
ui/test/one/script1.js
ui/test/two/script2.js

我需要让gulp将文件复制到相对目录中,以便得到如下结果。
ui/test/one/compressed/script1.js
ui/test/two/compressed/script2.js

我有以下的gulp任务

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

然而,当我运行它时,最终得到的是:
ui/test/one/compressed/one/script1.js
ui/test/two/compressed/two/script2.js

我在文档中看到以下内容:

cwd - 指定相对于工作目录的文件夹。 base - 指定相对于 cwd 的文件夹。默认值是 glob 开始的位置。这用于确定保存在 .dest() 中的文件名。

我有几个问题,特别是关于 .src().dest() 和路径和文件对象。(也就是说,虽然我确信有其他方法可以实现我的最终目标,但这个问题是关于上面的示例 gulp 代码和提到的函数的行为,以便我更好地理解它们的行为和 API。)

问题

  • 当文档中说“工作目录与文件夹相关”,这个文件夹是什么?
  • 同样,在this comment和文档中提到的“base-指定相对于当前工作目录的文件夹。默认值为glob开头的位置”,“glob开头的位置”是什么意思?我理解的“glob”是整个字符串,但它是否真的意味着该字符串内的*字符?因此,对于存在文件的“some/folder/a/b/c/foo.js”的“some/folder/**/*.js”,我不确定基础是some/folder/some/folder/a/还是some/folder/a/b/c/
  • 有没有一种方法可以说<where the glob begins> + '..'
  • 在我说path.join(path.dirname(file.path),'compressed')时,我假设这会生成C:\blah\ui\test\one\compressed。那么,无论实际文件名是什么,如one\script1.js,它都遵循这个规则。如何改变它的想法,使它只考虑script1.js
注意:我尝试了以下操作(使用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');
        }));
});

这个版本的任务在控制台上的输出如下:
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

所以看起来重命名对路径没有影响。我还尝试在重命名管道中修改path.dirname,但找不到任何可以从最终输出路径中简单删除错误目录名称的期望效果的内容。
那么,我的最后一个问题是,传递给重命名函数的路径对象中的path.basename和path.dirname确切包含什么?
编辑:我在this上找到了有关如何调试gulp任务的信息。在重命名函数中放置一个debugger;语句进行调试,允许我检查路径对象,它看起来像这样:
{
  basename: "script1",
  dirname: "one",
  extname: ".js"
}

将路径的 dirname 设置为 '' 会导致重命名结果中出现。
ui/test/compressed/script1.js
ui/test/compressed/script2.js

因此,对于我所需的内容,rename()本身可能并不有用。看起来像是.src()的基本选项可能是关键所在,但文档非常简洁。

看起来你已经找到了在最后一个.pipe中修改路径的方法,那么问题是什么呢?为什么gulp不允许非标准方案默认支持呢? - Kirill Slatin
@KirillSlatin 我最终得到了 ui/test/one/compressed/one/script1.js,但我需要的是 ui/test/one/compressed/script1.js。第二个 /one 是我想避免的。我修改了这个配方 https://github.com/gulpjs/gulp/blob/master/docs/recipes/running-task-steps-per-folder.md 并且成功得到了我需要的结果。所以如果悬赏过期并且没有其他人回答来领取它,那么我将发布一个答案,告诉大家我最终使用了什么方法。我最终在重命名中使用了哈希,这正是我所需要的。 - jinglesthula
我应该注意到,我之前的评论与最终结果有关,而不是实际关于.src()和.dest()的问题,以及如何处理路径,这实际上是我在这里提出的问题。因此,我将发布我在其他问题中发现的答案,这才是真正的答案 :) - jinglesthula
1个回答

5

问题1:

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

这行代码将'/ui/test/'设置为您的根目录(“工作文件目录”),因为它是您的全局模式的基础。这就是为什么提供给dest的'relative paths'是'one/script1.js'和'two/script2.js'。

问题2:

文档中的glob是指您的'** / *.js'模式。因此,您的glob的基础与用作根目录的'/ui/test/'相同,在这种情况下,意味着与“相对于cwd的文件夹”相同。

问题3:

每个路径的“base”属性都类似于glob2base模块,用于来自gulp.src流的每个文件的设置。

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

是相同的

file.base + '..';

我假设你在第二段代码中使用了gulp-rename,所以这应该可以解决你的问题。 如果你觉得有道理。
gulp.src('ui/test/**/*.js')
    .pipe(rename(function(path){
        path.basename = 'compressed/' + path.basename;
    })
    .pipe(gulp.dest(function(file) {
        return file.base;
    }));

可以传递给gulp.src的其他选项可以在这里找到,但我认为它们中没有任何一个直接解决你试图做的事情。gulp.src似乎不希望你在每个路径中间插入新目录,因此重命名是最简单的解决方案。

我不怪你对文档有困惑。我不得不在三四个不同的github页面之间跳转,才能拼凑出所有的内容。希望你从中学到了我所学到的知识。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接