Reputation: 1471
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
Upvotes: 9
Views: 5718
Reputation: 587
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);
});
});
Upvotes: 2
Reputation: 50080
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.
Upvotes: 1
Reputation: 1266
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'
}
},
Upvotes: 5
Reputation: 9650
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');
});
Upvotes: 9