如何循环遍历数组并运行 Grunt 任务,将数组中的每个值作为 Grunt 选项传递

ESR*_*ESR 2 javascript frontend gruntjs

我有一个类似于以下内容的数组:

var themes = grunt.option('themes') || [
    'theme1',
    'theme2',
    'theme3'
];
Run Code Online (Sandbox Code Playgroud)

还有另一个变量:

var theme = grunt.option('theme') || 'theme1';
Run Code Online (Sandbox Code Playgroud)

该值用于我的 grunt 文件中的各个位置,例如确定某些资产的路径等。

长话短说,我运行以下命令来编译单个主题的资源:

grunt compile --theme=theme2
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种方法来循环主题数组并compile使用适当的 grunt.option 运行 grunt 任务。本质上,我想要实现的目标相当于:

grunt compile --theme=theme1 && grunt compile --theme=theme2 && grunt compile --theme=theme3
Run Code Online (Sandbox Code Playgroud)

我已经尝试过以下方法:

grunt.registerTask('compile:all', function() {
    themes.forEach(function(currentTheme) {
        grunt.option('theme', currentTheme);
        grunt.task.run('compile');
    });
});
Run Code Online (Sandbox Code Playgroud)

这会运行compile任务适当的次数,但该theme选项似乎没有设置。所以我的 Scss 文件已生成,但它们是空的。

我也尝试过这个:

grunt.registerTask('compile:all', function() {
    themes.forEach(function(currentTheme) {
        grunt.util.spawn({
            grunt : true,
            args  : ['compile', '--theme=' + currentTheme]
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

该任务几乎立即完成并显示“成功”消息,但它似乎没有执行任何操作。

我尝试的最后一件事与上面类似,但我尝试使用异步:

grunt.registerTask('compile:all', function() {
    themes.forEach(function(currentTheme) {
        var done = grunt.task.current.async();
        grunt.util.spawn({
            grunt : true,
            args  : ['compile', '--theme=' + currentTheme]
        }, done);
    });
});
Run Code Online (Sandbox Code Playgroud)

但这个任务失败了。我真的不确定我哪里错了

谢谢你的帮助

764*_*484 5

我认为你的问题是你的各个编译任务正在排队grunt.task.run('compile');,但是,当它们执行时,你的themes.forEach循环已经完成,并且你的theme选项设置为 中的最后一个值themes

我认为您需要注册一个单独的任务来负责设置选项theme运行编译任务。

grunt.registerTask('compile_theme', function (theme) {
    grunt.option('theme', theme);
    grunt.task.run('compile');
});
Run Code Online (Sandbox Code Playgroud)

您可以将此任务放入compile:all每个主题的任务中:

themes.forEach(function(currentTheme) {
    grunt.task.run('compile_theme:' + currentTheme);
});
Run Code Online (Sandbox Code Playgroud)

如果您希望能够在命令行指定要编译的主题,则需要更新任务compile:all以读取所有--theme=参数并强制该值是一个数组:

grunt.registerTask('compile:all', function () {
    var compileThemes = grunt.option('theme') || 'theme1';

    if (grunt.util.kindOf(compileThemes) === 'string') {
        compileThemes = [compileThemes];
    }

    compileThemes.forEach(function(currentTheme) {
        grunt.task.run('compile_theme:' + currentTheme);
    });
});
Run Code Online (Sandbox Code Playgroud)

您可以按如下方式调用该命令:

grunt compile:all // compiles 'theme1'
grunt compile:all --theme=theme2 // compiles 'theme2'
grunt compile:all --theme=theme2 --theme=theme3 // compiles 'theme2' and 'theme3'
Run Code Online (Sandbox Code Playgroud)

compile:all注意:此时您可能需要重命名您的任务,因为它不再需要编译所有主题。

编辑

它不起作用,因为我们对这个theme选项期待太多。我们试图使用它来获取在命令行输入的主题,并在我们的配置中动态地组合值(例如,dest: theme + '/app.js'。按照我构建答案的方式,theme不能在配置中使用。

theme我会使用将在配置中使用的配置变量。这意味着更新compile_theme任务:

grunt.registerTask('compile_theme', function (theme) {
    grunt.config('theme', theme);
    grunt.task.run('compile');
});
Run Code Online (Sandbox Code Playgroud)

我们需要通过将模板字符串替换为 来更新我们的配置theme。例如:

dest: '<%= theme %>/app.js'
Run Code Online (Sandbox Code Playgroud)