最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to create a grunt task that references other grunt tasks - Stack Overflow

programmeradmin1浏览0评论

I have a grunt file that I am using to build my web app.

This grunt file uses several grunt contrib plugins like clean, copy, compass, cssmin, etc. to properly build the web app.

This grunt file is also supposed to handle generating the CSS and copying files for creating themed CSS files. Currently, I am adding targets to my clean, copy and compass (etc.) tasks for each theme.

This is becoming unwieldy in the grunt file and will make it difficult and error prone when new themes are added.

To make things easier, I'd really like to create my own custom "theme" grunt task that would internally use the other grunt contrib tasks (clean, copy, compass, etc.) to perform all of the necessary tasks for a specified theme.

With just a tiny amount of config data for a theme (mainly its source folder) I would have enough info to call the other tasks (since the theme source and destination files are very convention driven).

I can't seem to find a way to call a task from within my custom task where I can do it and specify all of the config options, files, etc. programmatically.

Does anyone have any idea how I can do this?

Thanks, Ed

I have a grunt file that I am using to build my web app.

This grunt file uses several grunt contrib plugins like clean, copy, compass, cssmin, etc. to properly build the web app.

This grunt file is also supposed to handle generating the CSS and copying files for creating themed CSS files. Currently, I am adding targets to my clean, copy and compass (etc.) tasks for each theme.

This is becoming unwieldy in the grunt file and will make it difficult and error prone when new themes are added.

To make things easier, I'd really like to create my own custom "theme" grunt task that would internally use the other grunt contrib tasks (clean, copy, compass, etc.) to perform all of the necessary tasks for a specified theme.

With just a tiny amount of config data for a theme (mainly its source folder) I would have enough info to call the other tasks (since the theme source and destination files are very convention driven).

I can't seem to find a way to call a task from within my custom task where I can do it and specify all of the config options, files, etc. programmatically.

Does anyone have any idea how I can do this?

Thanks, Ed

Share Improve this question edited Aug 27, 2013 at 3:25 Diosney 10.6k15 gold badges68 silver badges113 bronze badges asked Aug 27, 2013 at 3:07 emcpaddenemcpadden 1,4712 gold badges14 silver badges15 bronze badges 1
  • I'm not sure what you want to accomplish. Could you perhaps supply a small code example that demonstrates your problem? – Andreas Hultgren Commented Aug 27, 2013 at 8:21
Add a comment  | 

4 Answers 4

Reset to default 9

I can't seem to find a way to call a task from within my custom task where I can do it and specify all of the config options, files, etc. programmatically.

I don't think you can run a grunt multitask with specific config, as multitask config is read from the targets specified in the task config.

So one way to do this, is to modify the task config before running it.

Here's a very basic example:

grunt.registerMultiTask('theme', function() {
    var themeName = this.options().name;
    grunt.config.set('yourOtherTask.dist.options.name', themeName);
    grunt.task.run('yourOtherTask');
});

As easy as this:

concat: {
  web: {
    src: ['web/**/*.js'],
    dest: 'dist/main.js'
  }
},

uglify: {
  server: {
    src: '<%= concat.web.dest %>',
    dest: '<%= concat.web.dest %>.min.js'
  }
},
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);
    });
});

I had the same problem and solved it.

Keep in mind: grunt is all JavaScript thats run in node, so you can do any thing what JavaScript and node supports.

My solution work like this:

First, put all stuff for grunt of your core app in a separate JavaScript file for instance "grunt-my-app-core.js". In that export two functions, init(grunt) and 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) is to load and register tasks. Could be like this:

/**
 * 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) will build and return the config object:

/**
 * 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 ...
    };
}

and than, the Gruntfile.js in your theme project can be very short and don't need all the things of your core app. It could be like this:

/**
 * 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']);
};

Now, if you change something on your core app, all themes will get this. The only thing you need to update manual are the devDependencies in the package.json file.

发布评论

评论列表(0)

  1. 暂无评论