New Toronto Group
 - New Toronto Group

Using Your Angular App in Different Environments

| Posted on November 19th, 2015 by Andrew Smith


How to easily change your application constants based on your environment using NgConstant.

Here is a pretty common situation: you are working on your next change-the-world sweater tracking application and you realize that at some point you need to get it off of your development machine. Sure, you say, not a problem. You’re using the Yeoman Angular generator so after a simple grunt command you have your code all packaged up and ready to deploy.

 Or so you thought.

This is no small scale sweater tracking application. You’re trying to change the world, remember? You have written your own Node server as well. And while everything is working well on localhost, how do you change the API endpoint for your Angular app once your server is put into production? How do you change your Google Maps API key so that you can still find all of those wild and woolly sweaters that you have put GPS trackers in?

Enter NgConstant.

NgConstant is a grunt task that takes the work out of creating environment specific constants. It takes the keys and values that you define and creates an angular module with constant provider definitions that you can include in your main application. With a little grunt magic you can have that module file switched out whether you are running your local development server, running a test suite, building your code for production deployment, or any other scenario you may think of. Got multiple staging servers that all need some tweaks? No problem.

In order to get everything setup, there are a couple of steps that you are going to have to take. The first being to install the dependency using NPM.

$ npm install grunt-ng-constant --save-dev

Once that is downloaded we will do the meat of our setup work in our Gruntfile.js. If you are using the yeoman generator, it includes load-grunt-tasks so you don’t have to worry about including the task. If you aren’t using an automatic task loader include the following line: 

// Load the ng-constant grunt task
grunt.loadNpmTasks('grunt-ng-constant');

Next step is to get your environments setup in your grunt.initConfig block. The following creates a basic configuration for development and production.

grunt.initConfig({
  ...

  //Setup environment variables
  ngconstant: {
    // Options for all targets
    options: {
      space: '  ',
      // What your module gets wrapped in. It is helpful to include a                code comment for anyone that starts to edit the generated module file.
      wrap: '\'use strict\';\n// THIS FILE IS AUTO-GENERATED! EDITS               WILL NOT PERSIST!\n// Make edits in the appropriate JSON            file under ./config\n{%= __ngModule %}',
      // Name of your generated module
      name: 'config',
      // For the yeoman build process we will use the same destination     for both environments for the angular module file
      dest: '<%= yeoman.app %>/scripts/config.js'
    },
    // Environment targets
    development: {
      // Key-values created as Angular Constants
      constants: {
        // This JSON file will be available in the app under the ENV              variable
        ENV: grunt.file.readJSON('config/development.json')
      }
    },
    production: {
      constants: {
        ENV: grunt.file.readJSON('config/production.json')
      }
    }
  },
 
  ...
});

You will notice that we are reading in a couple of JSON files for our key/value definitions. While the task allows us to define these values inline in our Gruntfile, there are some key benefits for doing it this way. The first is that it allows us to get our configuration out of the Gruntfile and encapsulate the information in a more meaningful way. It is a lot easier to go and change the development.json file sitting in a config folder than to have to wade through our 500+ line Gruntfile.

The other benefit is that it gives us more flexibility in regards to source control. It is a huge faux pas to include your sensitive configuration information, like API keys, in your repo. Sharing your corporate account information on Github for all to see certainly isn’t a smart move. Just add these new JSON files to your .gitignore manifest and you are all set. You might also want to include a template file with just the keys so that the other developers on your team can get up and running quickly without having to dig through the code. 

The last step for our grunt configuration is to call the task.

// Grunt task to run your local development server
grunt.registerTask('serve', [
  ...
  // This will generate the module file for development
  'ngconstant:development',
  ...
]);
 
// Grunt task to build your source code for deployment to production
grunt.registerTask('build', [
  ...
  // This will generate the module file for production
  'ngconstant:production',
  ...
]);

Now with grunt all setup and our new module file being created, lets include that in our angular app. First thing is to include the newly generated file in our index.html. 

<script src="scripts/config.js"></script>

Then we add it as a dependency on our main application module

angular.module('sweaterTrackerApp', ['config']);

And that’s it! Now to access your constants, inject the ENV service (in this case) into whatever portion of the application you need it. All of your keys will be namespaced under this new service such as

var apiUrl = ENV.apiRootUrl;

As you can see, with just a little bit of setup, this is a pretty powerful way of working. It is pretty easy to take this pattern and expand it to other deployment environments. You could even use it to amalgamate all of your non-environment specific constants into one file for consistency across your application. 

Now go out there and change the world, one ugly Christmas sweater at a time.

Posted in AngularJS, NgConstant  | Comments (0)

Comments (0)


Add a Comment





To use reCAPTCHA you must get an API key from http://recaptcha.net/api/getkey

Allowed tags: <b><i><br>Add a new comment: