Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Global Variable to Set Build Output Path in Grunt

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?

like image 676
ThePuzzleMaster Avatar asked Mar 26 '13 21:03

ThePuzzleMaster


2 Answers

So, 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.

like image 159
ThePuzzleMaster Avatar answered Sep 28 '22 00:09

ThePuzzleMaster


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)
like image 28
SimplGy Avatar answered Sep 28 '22 00:09

SimplGy