【问题标题】:Pass parameter to Gulp task in gulpfile.js (not command-line)将参数传递给 gulpfile.js 中的 Gulp 任务(不是命令行)
【发布时间】:2025-12-05 05:55:01
【问题描述】:

EDIT: 正如我在标题和开头所写的,这与命令行参数无关,因此不是重复的。 //EDIT

我有一个 Sass 设置,其中包含无限数量的独特设计页面(page_1、page_2 等),每个都有自己的 sass/pages/page_1/page_1.scss 文件。

页面都属于同一个网站,每个页面的sass文件@imports来自sass/includes文件夹的同一组文件。

通过观看sass/**/* 的基本 gulp 任务,每当我更改任何页面的样式时,每个页面的样式都会被编译。显然这不能很好地扩展。

我尝试使用gulp-watch,但如果对包含的.scss 文件之一进行了更改,它不会捕获。它只捕获对实际编译为等效.css 的文件所做的更改。

为了让我的 gulpfile 尽可能 DRY,我能想出的最佳解决方案是在 gulpfile.js 中维护一个基本的文件夹名称数组,并循环遍历并分别查看它们中的每一个,使用每个文件夹都执行相同的 sass 编译任务。

var pageFolderNames = [
    'page_1',
    'page_2'
    // etc
];

那么对于 gulp 任务,我有:

gulp.task('watch_pages', function()
{    
  // Get array length
  var numPages = pageFolderNames.length;

  // Add a new watch task for each individual page
  for (var i = 0; i < numPages; i++)
  {
    gulp.watch('sass/pages/' + pageFolderNames[i] + '/**/*.scss', ['sass_page']);
  }
});

编译 sass 的(简化的)任务:

// Task: Compile page-specific Sass
gulp.task('sass_page', function()
{
  return gulp.src('sass/pages/' + pageFolderNames[i] +'/**/*.scss')
    .pipe(plumber(plumberErrorHandler))
    .pipe(sass(...))
    .pipe(gulp.dest('css/pages/' + pageFolderNames[i]));
});

这种方法(我知道我的 JS-fu 很弱)导致错误:

'sass_page' errored after 71 μs
ReferenceError: i is not defined

有没有办法将参数(例如i)传递给 gulp 任务以使其正常工作?或者,有没有更好的方法来完成我想要做的事情?我有一个偷偷摸摸的怀疑。 :-/

【问题讨论】:

  • 我删除了我的答案。据我了解,您想查看特定文件夹并在该特定文件夹上运行任务 sass_page 。我说的对吗?
  • @PaulSwetz 不一样。我发现的所有“传递参数”帖子都与通过命令行这样做有关。我特别想通过内部逻辑而不是通过命令行来这样做。
  • @Brian 是的,没错...每个特定文件夹都单独监视并由单个监视任务编译。
  • @Sandwich 我之前重新打开了我的答案,希望对您有所帮助。

标签: javascript sass gulp


【解决方案1】:

我发现 gulp watch 有一个 on change 事件。所以这可能是您正在寻找的:

var pagesDir = 'sass/pages/';

gulp.task('watch_pages', function() {
    gulp.watch(pagesDir + '**/*')
        .on("change", function(file) {
            // absolute path to folder that needs watching
            var changedDest = path.join(__dirname, pagesDir);
            // relative path to changed file
            var changedFile = path.relative(changedDest, file.path);
            // split the relative path, get the specific folder with changes
            var pageFolder  = changedFile.split('\\')[0];

            gulp.src(path.join(pagesDir, pageFolder) +'/**/*.scss')
              .pipe(plumber(plumberErrorHandler))
              .pipe(sass(...))
              .pipe(gulp.dest('css/pages/' + pageFolder));

            console.log(changedDest);
            console.log(changedFile);
            console.log(pageFolder);
        });
});

此外,这样您就不需要声明文件夹变量。如果您在被监视的路径中添加目录,它应该会选择它并相应地命名目标文件夹。

理论上,编译 sass 的 gulp 任务应该在 watch 任务中工作。我玩弄了这些路径,它似乎把它们吐出来了。让我知道发生了什么,我可以根据需要进行修改。

所需的包:

var gulp = require("gulp"),
    path = require("path"),
    rimraf = require("rimraf");

顺便说一句,由于您已经可以访问文件路径,因此您也许可以针对特定的 scss 文件而不是整个目录。

【讨论】:

    【解决方案2】:

    正如 Brian 回答的那样,最好的方法是拥有一名观察者。与 dom 事件监听器的委托原理相同。更好的是,即使在我们的情况下它也无关紧要。我们需要完成我们的事情。如果消耗的资源和性能不打扰我们。没关系。但按照布赖恩的回答留下来。一个观察者是最好的方法。那么你必须得到被改变的文件。从那里你得到你的页面文件夹。所以为此我不会添加任何东西。除了您不一定需要使用.on("change"。您可以直接为您的函数设置与此示例相同的参数:

      watch('./app/tempGulp/json/**/*.json', function (evt) {
        jsonCommentWatchEvt = evt
        gulp.start('jsonComment')
    })
    

    evt 这是 Brian 设置的 file

    我想补充的是如何将参数从观察者传递给任务。例如关于你最初工作中的i一种方法,我看到并使用,是设置一个全局变量来保存要传递的数据。所以它在两个块中都可以访问。 您在开始任务之前在 watcher 中设置了值。然后在任务中使用它。一个好的做法是,在开始时将它保存在任务局部变量中。这样你就避免了它可以被另一个手表处理触发改变的问题。

    举个生动的例子。在这里查看我的答案:https://*.com/a/49733123/7668448

    【讨论】: