2

I have a webapp (emberjs) that I need to set env variables based on grunt task. So when I run grunt server it would choose development, and url will be set to localhost:5000. But when i do grunt build, it would choose production and url will be set to production.com.

The main issue for me is, how to read those variables from ember. Or how to make grunt look for a variable and change it based on the task

Is it possible to do something like that?

Seif Sallam
  • 821
  • 2
  • 10
  • 30

2 Answers2

2

Yes, it's possible. Using grunt-env to specify your environment in combination with something like grunt-usemin to expose your environment variables to your application code.

According to this SO thread you need to ensure that your environment variables are loaded prior to Ember.js.

Community
  • 1
  • 1
André Dion
  • 21,269
  • 7
  • 56
  • 60
  • I have a working ENV variables set before emberjs, and grunt-env seems great to define variables there. But how can match grunt-env variables to be set in a place of my choice. Is there a way like find and replace? How can I put the variables in a specific place before building or running server? – Seif Sallam Aug 21 '13 at 17:46
  • See the answers in [this SO thread](http://stackoverflow.com/questions/12401998/have-grunt-generate-index-html-for-different-setups). As per my answer, I've suggested you use something like [`grunt-usemin`](https://npmjs.org/package/grunt-usemin) to expose your environment variables to your app, but if you check out the [thread I linked](http://stackoverflow.com/questions/12401998/have-grunt-generate-index-html-for-different-setups) you can see there are more ways to skin this cat. – André Dion Aug 22 '13 at 11:08
1

After much googling and no good examples, here's what I did.

Assuming you're using yeoman with scaffolding by yo ember generator and using grunt build to build the dist.

Yo ember-generator v0.8 uses grunt-replace. Upgrade to that version. In short, I'm using grunt-replace to add global vars to index.html. Here's how.

Add this script tag to app/index.html before the combined-scripts.js block:

#app/index.html
<script>
  /*
    simplify grunt-replace strategy by placing env vars here.
  */
  window.MYCOMPANYCOM_ENV = {
    env: '@@env',
    apiHost: '@@apiHost'
  };
</script>

/* ADD THE ABOVE BEFORE THIS SECTION */
<!-- build:js(.tmp) scripts/main.js -->
<script src="scripts/combined-scripts.js"></script>
<!-- endbuild -->

And change the replace config in Gruntfile.js to this:

module.exports = function (grunt) {
  var appConfig = grunt.file.readJSON('app_config.json');

replace: {
  app: {
    options: {
      patterns: [
        {
          json: appConfig['app']
        }
      ]
    },
    files: [
      {src: '<%= yeoman.app %>/index.html', dest: '.tmp/index.html'}
    ]
  },
  dist: {
    options: {
      patterns: [
        {
          json: appConfig['dist']
        }
      ]
    },
    files: [
      {src: '<%= yeoman.dist %>/index.html', dest: '<%= yeoman.dist %>/index.html'}
    ]
  }
}

Create a new file at ./app_config.json

{
  "app": {
    "env": "development",
    "apiHost": "http://localhost:8080"
    },
  "dist": {
    "env": "dist",
    "apiHost": "/"
    }
}

Now your app scripts have access to a global vars defined in app_config.json.

I won't go into more detail but this works fine in development. For grunt build, I moved the replace:dist step to the end of the build steps, and replaced the @@ember variable in index.html with a path to the bower component.

Luke W
  • 8,276
  • 5
  • 44
  • 36