如何创建一个Grunt任务来引用其他的Grunt任务

8
我有一个grunt文件,用于构建我的Web应用程序。
这个grunt文件使用了几个grunt的插件,如clean、copy、compass、cssmin等等来正确地构建Web应用程序。
这个grunt文件还应该处理生成CSS和复制文件以创建主题CSS文件。目前,我在我的clean、copy和compass(等等)任务中为每个主题都添加了目标。
这使得grunt文件变得笨重,当添加新主题时会变得难以维护和容易出错。
为了让事情更容易,我真的想创建自己的定制化“主题”grunt任务,它将在内部使用其他grunt contrib任务(clean、copy、compass等)来执行指定主题的所有必要任务。
只需少量配置数据(主要是源文件夹),我就有足够的信息来调用其他任务(因为主题源和目标文件非常遵循约定)。
我无法找到一种可以从我的自定义任务中调用任务并以编程方式指定所有配置选项、文件等的方法。
有人知道我怎么做吗?
谢谢,Ed

我不确定你想要实现什么。你可以提供一个小的代码例子来演示一下你的问题吗? - Andreas Hultgren
4个回答

8
我似乎找不到一种方法来从我的自定义任务中调用一个任务,在其中我可以以编程方式指定所有配置选项、文件等。
我认为您无法使用特定配置运行grunt多任务,因为多任务配置是从任务配置中指定的目标读取的。
因此,要做到这一点,就需要在运行任务之前修改任务配置。
以下是一个非常基本的示例:
grunt.registerMultiTask('theme', function() {
    var themeName = this.options().name;
    grunt.config.set('yourOtherTask.dist.options.name', themeName);
    grunt.task.run('yourOtherTask');
});

1
我爱你 - 这就是我需要的! - Spock

5
像这样简单:
concat: {
  web: {
    src: ['web/**/*.js'],
    dest: 'dist/main.js'
  }
},

uglify: {
  server: {
    src: '<%= concat.web.dest %>',
    dest: '<%= concat.web.dest %>.min.js'
  }
},

1

我曾经遇到过同样的问题并解决了它。

请记住:grunt是在node中运行的所有JavaScript,因此您可以做任何JavaScript和node支持的事情。

我的解决方案如下:

首先,将核心应用程序的所有grunt内容放入一个单独的JavaScript文件中,例如“grunt-my-app-core.js”。 在其中导出两个函数:init(grunt)getConfig(grunt,options)

(function() {
    "use strict"; //enable ECMAScript 5 Strict Mode

    function init(grunt) {
    }

    function getConfig(grunt, options) {
        return {};
    }


    ///////////////////////////
    //   Exports
    exports = module.exports = {
        init: init,
        getConfig: getConfig
    };
})();

init(grunt) 的作用是加载和注册任务。可以像这样:

/**
 * public API
 *
 * add all required settings to grunt
 * 
 * register task "dist" and task "doc"
 *
 * @param  {object} grunt   the grunt instance
 * @return {void}
 */
function init(grunt) {
    // overwrite platform specific setting get always unix like line feed char
    grunt.util.linefeed = '\n';

    // Load plugins provide necessary task.
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-less');

    grunt.registerTask('dist', ['clean:build', 'copy:build', 'copy:dist', 'uglify', 'less']);
    grunt.registerTask('doc', ['clean:doc', 'copy:doc']);
}

getConfig(grunt, options)将构建并返回配置对象:

/**
 * public API
 *
 * will return a config object that have to be given as argument to "grunt.initConfig"
 *
 * @param  {object} grunt   the grunt instance
 * @param  {object|undefined} options to change some pathes
 * @return {object}         the configuration object for initConfig
 */
function getConfig(grunt, options) {

    options = options || {};

    var buildDir = options.buildDir || "build/";
    var distDir = options.distDir || "dist/";
    var docDir = options.docDir || "doc/";

    // ... doing some stuff to collect files or what ever ...

    return {
        clean: {
            build: {
                src: [buildDir]
            },
            doc: {
                src: [docDir]
            }
        },
        copy: {
            // ...
        }   
        // ... add here all the stuff you like to config ...
    };
}

然后,您主题项目中的Gruntfile.js可以非常简短,不需要您核心应用程序的所有内容。它可能是这样的:
/**
 * Module dependencies.
 */
var gruntMyApp = require("../my-app/grunt-my-app-core.js");

/*global module:false*/
module.exports = function(grunt) {

    var config = gruntMyApp.getConfig(grunt);

    // ... extend config, if you need it

    grunt.initConfig(config);

    // will register Task "dist" and "doc"
    gruntMyApp.init(grunt);

    // Default task.
    grunt.registerTask('default', ['dist', 'doc']);
};

现在,如果您在核心应用程序上进行更改,所有主题都将得到这些更改。您唯一需要手动更新的是package.json文件中的devDependencies

你如何在项目之间共享这样一个“元任务”(npm 依赖似乎在这种情况下不起作用..)? - phtrivier
我通过Git子模块将核心应用程序包含到主题项目中。 - TLindig
@Downvoter:请告诉我,你下投票的原因是什么! - TLindig
没问题,我的赞同已经中和了那个踩我的人。 - Fagner Brack

1
grunt.initConfig({
    clean: {/!* clean task configuration *!/},
    copy: {/!* copy task configuration *!/},
    compass: {/!* compass task configuration *!/},
    cssmin: {/!* cssmin task configuration *!/}
});

grunt.registerTask('theme', function () {
    var tasks = [
            'clean',
            'copy',
            'compass',
            'cssmin'
    ];

    tasks.forEach(function (task) {
        grunt.task.run(task);
    });
});

3
或者更简单地说,grunt.task.run(tasks)表示运行指定的任务。 - Kjir

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