title: Grunt Environment Variables Don't Get Set Until All Tasks Loaded
body: <p>I am using the <code>npm</code> modules <a href="https://github.com/jsoverson/grunt-env" rel="nofollow">grunt env</a> and <a href="https://www.npmjs.org/package/load-grunt-config" rel="nofollow">load-grunt-config</a> in my project. <code>grunt env</code> handles environment variables for you, while <code>load-grunt-config</code> handles, well, loads the <code>grunt</code> configuration for you. You can put your tasks into other files, then <code>load-grunt-config</code> will bundle them up and have <code>grunt</code> load &amp; consume them for you. You can also make an <code>aliases.js</code> file, with tasks you want to combine together into one task, running one after another. It's similar to the <a href="http://gruntjs.com/api/grunt.task" rel="nofollow">grunt.registerTask</a> task in the original <code>Gruntfile.js</code>. I put all my <code>grunt</code> tasks inside a separate <code>grunt/</code> folder under the root folder with the main <code>Gruntfile</code>, with no extra subfolders, as suggested by the <code>load-grunt-config</code> README.md on Github. Here is my slimmed-down <code>Gruntfile</code>:</p>
  
  <pre><code>module.exports = function(grunt) {
  
      'use strict';
  
      require('time-grunt')(grunt);
  
      // function &amp; property declarations
      grunt.initConfig({
  
          pkg: grunt.file.readJSON('package.json')
  
      });
  
      require('load-grunt-config')(grunt, {
          init: true,
          loadGruntConfig: {
              scope: 'devDependencies', 
              pattern: ['grunt-*', 'time-grunt']
          }
      });
  
  };
  </code></pre>
  
  <p>In theory, setting all these files up the correct way for <code>load-grunt-config</code> to load should be exactly the same as just having a <code>Gruntfile.js</code>. However, I seem to have run into a little snag. It seems the environment variables set under the <code>env</code> task do not get set for the subsequent <code>grunt</code> tasks, but are set by the time <code>node</code> processes its tasks, in this case an <code>express</code> server.</p>
  
  <p><code>grunt env</code> task:</p>
  
  <pre><code>module.exports = {
  
      // environment variable values for developers
      // creating/maintaining site
      dev: {
          options: {
              add: {
                  NODE_ENV: 'dev',
                  MONGO_PORT: 27017,
                  SERVER_PORT: 3000
              }
          }
      }
  };
  </code></pre>
  
  <p><a href="https://github.com/cri5ti/grunt-shell-spawn" rel="nofollow">grunt-shell-spawn</a> task: </p>
  
  <pre><code>// shell command tasks
  module.exports = {
  
      // starts up MongoDB server/daemon
      mongod: {
          command: 'mongod --bind_ip konneka.org --port ' + (process.env.MONGO_PORT || 27017) + ' --dbpath C:/MongoDB/data/db --ipv6',
          options: {
              async: true, // makes this command asynchronous
              stdout: false, // does not print to the console
              stderr: true, // prints errors to the console
              failOnError: true, // fails this task when it encounters errors
              execOptions: {
                  cwd: '.'
              }
          }
      }
  };
  </code></pre>
  
  <p><a href="https://github.com/blai/grunt-express" rel="nofollow">grunt express</a> task:</p>
  
  <pre><code>module.exports = {
  
      // default options
      options: {
          hostname: '127.0.0.1', // allow connections from localhost
          port: (process.env.SERVER_PORT || 3000), // default port
  
      },
  
      prod: {
          options: {
              livereload: true, // automatically reload server when express pages change
              // serverreload: true, // run forever-running server (do not close when finished)
              server: path.resolve(__dirname, '../backend/page.js'), // express server file
              bases: 'dist/' // watch files in app folder for changes
          }
      }
  };
  </code></pre>
  
  <p><code>aliases.js</code> file (<code>grunt-load-config</code>'s way of combining tasks so they run one after the other):</p>
  
  <pre><code>module.exports = {
      // starts forever-running server with "production" environment
      server: ['env:prod', 'shell:mongod', 'express:prod', 'express-keepalive']
  };
  </code></pre>
  
  <p>part of <code>backend/env/prod.js</code> (environment-specific Express configuration, loaded if <code>NODE_ENV</code> is set to "prod", modeled after <a href="https://github.com/meanjs/mean" rel="nofollow">MEAN.JS</a>):</p>
  
  <pre><code>'use strict';
  
  module.exports = {
      port: process.env.SERVER_PORT || 3001,
      dbUrl: process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || 'mongodb://konneka.org:' + (process.env.MONGO_PORT || 27018) + '/mean'
  };
  </code></pre>
  
  <p>part of <code>backend/env/dev.js</code> (environment-specific Express configuration for <code>dev</code> environment, loaded if the `NODE_ENV variable is not set or is set to "dev"):</p>
  
  <pre><code>module.exports = {
      port: process.env.SERVER_PORT || 3000,
      dbUrl: 'mongodb://konneka.org:' + (process.env.MONGO_PORT || 27017) + '/mean-dev'
  };
  </code></pre>
  
  <p>part of <code>backend/page.js</code> (my Express configuration page, also modeled after MEAN.JS):</p>
  
  <pre><code>'use strict';
  var session = require('express-session');
  var mongoStore = require('connect-mongo')(session);
  var express = require('express');
  var server = express();
  
  ...
  
  // create the database object
  var monServer = mongoose.connect(environ.dbUrl);
  
  // create a client-server session, using a MongoDB collection/table to store its info
  server.use(session({
      resave: true,
      saveUninitialized: true,
      secret: environ.sessionSecret,
      store: new mongoStore({
          db: monServer.connections[0].db, // specify the database these sessions will be saved into
          auto_reconnect: true
      })
  }));
  
  ...
  
  // listen on port related to environment variable
  server.listen(process.env.SERVER_PORT || 3000);
  
  module.exports = server;
  </code></pre>
  
  <p>When I run <code>grunt server</code>, I get:</p>
  
  <pre><code>$ cd /c/repos/konneka/ &amp;&amp; grunt server
  Running "env:prod" (env) task
  
  Running "shell:mongod" (shell) task
  
  Running "express:prod" (express) task
  
  Running "express-server:prod" (express-server) task
  Web server started on port:3000, hostname: 127.0.0.1 [pid: 3996]
  
  Running "express-keepalive" task
  Fatal error: failed to connect to [konneka.org:27018]
  
  
  Execution Time (2014-08-15 18:05:31 UTC)
  loading tasks        38.3s  █████████████████████████████████ 79%
  express-server:prod   8.7s  ████████ 18%
  express-keepalive     1.2s  ██ 2%
  Total 48.3s
  </code></pre>
  
  <p>Now, I can't seem to get the database connected in the first place, but ignore that for now.  Notice that the server is started on port 3000, meaning that during execution of the <code>grunt express:prod</code> task, <code>SERVER_PORT</code> is not set so the port gets set to 3000. There are numerous other examples like this, where an environment variable is not set so my app uses the default. However, notice that <code>session</code> tries to connect to the database on port 27018 (and fails), so <code>MONGO_PORT</code> does get set eventually.</p>
  
  <p>If I had just tried the <code>grunt server</code> task, I could chalk it up to <code>load-grunt-config</code> running the tasks in parallel instead of one after the other or some other error, but even when I try the tasks one-by-one, such as running <code>grunt env:prod shell:mongod express-server:prod express-keepalive</code>, I get similar (incorrect) results, so either <code>grunt</code> or <code>grunt env</code> run the tasks in parallel, as well, or something else is going on.</p>
  
  <p>What's going on here? Why are the environment variables not set correctly for later <code>grunt</code> tasks? When are they eventually set, and why then rather than some other time? How can I make them get set for <code>grunt</code> tasks themselves rather than after, assuming there even is a way?</p>