javascript

AngularJS – being aware of environment

 

Single Page Apps can be awesome

Single Page app is not a myth, its real and its awesome.

But strong , fast tools are definitely something a developer should always use. Grunt and Gulp are extremely useful for running tasks that optimize web resources, run automatic tests , monitor changes and refresh your browser as you tinker with the next big thing but also run any custom task you desire.

I had a challenge with an AngularJS app that was strictly using an API from a another domain and we had several environments (local, stage, prod – typical right? ) . Clearly those environment use different settings, and have different urls.

AngularJS provides nice ways of settings variables available across your app through injection.

Here is an example that creates a module ‘app.config’ (or appname of your choice) and sets constant (using this string you can inject and use it)

Define constants within AngularJS app

angular.module("app.config", [])

.constant("ENV", {
  "name": "development",
  "apiEndpoint": "http://localhost:5000",
  "basePath": "http://app.dev"
});

 

Inject and use variables within the app (CoffeeScript)

 

angular.module('app.controllers', ['restangular', 'app.config'])
.config (RestangularProvider, ENV)->
    RestangularProvider.setBaseUrl(ENV.apiEndpoint)
    RestangularProvider.setDefaultHttpFields(withCredentials:true)

At this point i can inject and use ENV throughout controllers and as you can see above in config state of initializing an Angular app. Since i’m using Restangular to interact with an API i needed to set a base url.

What happens on automated deployments? Solution

I’ve had a chance to use codeship and jenkins for building codebase and running tests, etc. Deploying to Staging or production would require that you replace config module with variables dependent on the environment. You don’t have to do anything manually. Here is the solution if you’re using Grunt.

NPM you need to install:

grunt-ng-constant

This is your Gruntfile.coffee (just a portion that is of interest, loading and using ng-constant) :

#Gruntfile

grunt.loadNpmTasks('grunt-ng-constant')

ngconstantConfig = 
      # Options for all targets
      options:
        space: "  "
        wrap: ""use strict";nn {%= __ngModule %}"
        name: "app.config"

      # Environment targets
      development:
        options:
          dest: "<%= yeoman.app %>/scripts/shared/config.js"

        constants:
          ENV:
            name: "development"
            apiEndpoint: "http://localhost:5000"

      stage:
        options:
          dest: "<%= yeoman.app %>/scripts/shared/config.js"

        constants:
          ENV:
            name: "stage"
            apiEndpoint: "http://staging-api.someurl.com"

Set configuration for grunt :

 grunt.initConfig
     ngconstant: ngconstantConfig

In regular JavaScript this is simply :

 

grunt.initConfig({ ngconstant: ngconstantConfig });

 

One more simple step (setting up the task)

env = process.env.NODE_ENV || 'development'

grunt.registerTask "build", ["clean:dist","ngconstant:"+env, "copy:ngconfig"...

This will register a task in a development environment “ngconstant:development” which will trigger NPM grunt-ng-constant to generate a file config.js that would include all the variables you defined in ngconstantConfig object for a specific environment.

 

Possible issue and solution

At least in my project (coffeescript) config.js was generated but too late and wasn’t picked up by other task that packaged everything into one file. My solution was to write a small task named “copy:ngconfig” that simply copied the generated file explicitly

This is simply copying config.js into Temporary location which then available for other task to package.

        copy:
            ngconfig:
                files: [ 
                    
                    src: ["<%= yeoman.app %>/scripts/shared/config.js"]
                    dest: ".tmp/scripts/shared/config.js"
                ]

 

Voila , your application will environment specific values on any environment

Next time your code is pulled into stage or production , it can run> grunt build ¬† and code will be optimized, packaged into “dist” folder and deployed to optimally Amazon CDN

 

Share This: