I have a couple grunt tasks and I am trying to share global variables across those tasks and I am running into issues.
I have written a some custom tasks which set the proper output path depending on the build type. This seems to be setting things correctly.
// Set Mode (local or build)
grunt.registerTask("setBuildType", "Set the build type. Either build or local", function (val) {
// grunt.log.writeln(val + " :setBuildType val");
global.buildType = val;
});
// SetOutput location
grunt.registerTask("setOutput", "Set the output folder for the build.", function () {
if (global.buildType === "tfs") {
global.outputPath = MACHINE_PATH;
}
if (global.buildType === "local") {
global.outputPath = LOCAL_PATH;
}
if (global.buildType === "release") {
global.outputPath = RELEASE_PATH;
}
if (grunt.option("target")) {
global.outputPath = grunt.option("target");
}
grunt.log.writeln("Output folder: " + global.outputPath);
});
grunt.registerTask("globalReadout", function () {
grunt.log.writeln(global.outputPath);
});
So, I'm trying to then reference global.outputPath in a subsequent task, and running into errors.
If I call grunt test
from the command line, it outputs the correct path no problem.
However, if I have a task like this: clean: { release: { src: global.outputPath } }
It throws the following error:
Warning: Cannot call method 'indexOf' of undefined Use --force to continue.
Also, my constants in the setOutput task are set at the top of my Gruntfile.js
Any thoughts? Am I doing something wrong here?
I have a couple grunt tasks and I am trying to share global variables across those tasks and I am running into issues.
I have written a some custom tasks which set the proper output path depending on the build type. This seems to be setting things correctly.
// Set Mode (local or build)
grunt.registerTask("setBuildType", "Set the build type. Either build or local", function (val) {
// grunt.log.writeln(val + " :setBuildType val");
global.buildType = val;
});
// SetOutput location
grunt.registerTask("setOutput", "Set the output folder for the build.", function () {
if (global.buildType === "tfs") {
global.outputPath = MACHINE_PATH;
}
if (global.buildType === "local") {
global.outputPath = LOCAL_PATH;
}
if (global.buildType === "release") {
global.outputPath = RELEASE_PATH;
}
if (grunt.option("target")) {
global.outputPath = grunt.option("target");
}
grunt.log.writeln("Output folder: " + global.outputPath);
});
grunt.registerTask("globalReadout", function () {
grunt.log.writeln(global.outputPath);
});
So, I'm trying to then reference global.outputPath in a subsequent task, and running into errors.
If I call grunt test
from the command line, it outputs the correct path no problem.
However, if I have a task like this: clean: { release: { src: global.outputPath } }
It throws the following error:
Warning: Cannot call method 'indexOf' of undefined Use --force to continue.
Also, my constants in the setOutput task are set at the top of my Gruntfile.js
Any thoughts? Am I doing something wrong here?
Share Improve this question edited Aug 23, 2013 at 16:54 SimplGy 20.4k15 gold badges111 silver badges150 bronze badges asked Mar 26, 2013 at 21:10 ThePuzzleMasterThePuzzleMaster 9912 gold badges11 silver badges18 bronze badges 1- I'm thinking it might be related to the global.outputPath being set outside of grunt.initConfig({}), while, I'm trying to access the variable inside grunt.initConfig({}) – ThePuzzleMaster Commented Mar 26, 2013 at 21:19
3 Answers
Reset to default 13So, I was on the right path. The issue is that the module exports before those global variables get set, so they are all undefined in subsequent tasks defined within the initConfig() task.
The solution I came up with, although, there may be better, is to overwrite a grunt.option value.
I have an optional option for my task --target
working solution looks like this:
grunt.registerTask("setOutput", "Set the output folder for the build.", function () {
if (global.buildType === "tfs") {
global.outputPath = MACHINE_PATH;
}
if (global.buildType === "local") {
global.outputPath = LOCAL_PATH;
}
if (global.buildType === "release") {
global.outputPath = RELEASE_PATH;
}
if (grunt.option("target")) {
global.outputPath = grunt.option("target");
}
grunt.option("target", global.outputPath);
grunt.log.writeln("Output path: " + grunt.option("target"));
});
And the task defined in initConfig() looked like this:
clean: {
build: {
src: ["<%= grunt.option(\"target\") %>"]
}
}
Feel free to chime in if you have a better solution. Otherwise, perhaps this may help someone else.
I have a way to do this that allows you to specify the output path using values like --dev
. So far it's working very well, I quite like it. Thought I'd share it, as someone else may like it, too.
# Enum for target switching behavior
TARGETS =
dev: 'dev'
dist: 'dist'
# Configurable paths and globs
buildConfig =
dist: "dist"
dev: '.devServer'
timestamp: grunt.template.today('mm-dd_HHMM')
grunt.initConfig
cfg: buildConfig
cssmin:
crunch:
options: report: 'min'
files: "<%= grunt.option('target') %>/all-min.css": "/**/*.css"
# Set the output path for built files.
# Most tasks will key off this so it is a prerequisite
setPath = ->
if grunt.option 'dev'
grunt.option 'target', buildConfig.dev
else if grunt.option 'dist'
grunt.option 'target', "#{buildConfig.dist}/#{buildConfig.timestamp}"
else # Default path
grunt.option 'target', buildConfig.dev
grunt.log.writeln "Output path set to: `#{grunt.option 'target'}`"
grunt.log.writeln "Possible targets:"
grunt.log.writeln target for target of TARGETS
setPath()
With this setup, you can run commands like:
grunt cssmin --dist #sent to dist target
grunt cssmin --dev #sent to dev target
grunt cssmin --dev #sent to default target (dev)
This is an older question, I just thought to throw in my 5 cents.
If you need config variable to be accessible from any task, just define it in your main (the one that you'll always load) config file like this:
module.exports = function(grunt)
{
//
// Common project configuration
//
var config =
{
pkg: grunt.file.readJSON('package.json'),
options: // for 'project'
{
dist:
{
outputPath: '<%= process.cwd() %>/lib',
},
dev:
{
outputPath: '<%= process.cwd() %>/build',
},
},
}
grunt.config.merge( config )
}
Then you can simply access value like this:
- in config file(s)
...
my_thingie:
[
ends_up_here: '<%= options.dev.outputPath %>/bundle',
],
...
- in tasks
// as raw value
grunt.config.data.options.dist.outputPath
// after (eventual) templates have been processed
grunt.config('options.dist.outputPath')
I used key options
here just to be in line with convention, but you can use anything as long as you remember not to register a task named 'options'
or whatever you used for the key :)