Configuring Multiple Environments for Angular.js using grunt-ng-constant

Hi there! Today I’d like to talk about the useful tool for Angular developers – grunt-ng-constant. But first, let me say a couple of words about Angular development and environments in general.

I like to create SPAs (Single Page Application) using Angular because they are incredibly powerful and beautiful. Besides it is quite simple to start your first application in this way. All you need to do is just copy CDN link from official website, add it to your HTML document and … and that’s all. So now you can start your work.

BUT this is just the easiest way. Angular lovers always have a set of useful tools e.g. package and task managers, scaffolding tools which make their lives simpler and development process more pleasant. So here I want to tell about how to have multiple environments on your frontend. I’m using Grunt as task manager, Yeoman as scaffolding tool, and npm and bower as package managers. You can welcome them =)

OK, now we need to understand what is “environments” and why do we need them? Let’s imagine that we have two different servers: #1 for development and #2 for production. We want our Angular app to have two different setting files to store data on both servers. What does Angular already have to store this kind of settings? It gives us two cool things: Angular service called ‘constant’ and dependency injection. In our sample application, we have fixed object called ‘ENV’ which has ‘APIEndpoint’ string like this:

And after this, we can inject this constant where we need it. Let’s say we need it in the main controller, in this case, it will look like this:

That’s nice, but if we want to use this endpoint for development and another endpoint for the production we need to change this constant each time. It is quite simple if we have one or two constant like this one. But we can have a lot of such constants, and it becomes really boring to change them each time, and the chance to make a mistake increases. In this case grunt-ng-constant can help.

Great! Enough words, let’s scaffold our application and make some initial steps to start using grunt-ng-constant in it.

I hope you have Node, npm, and bower installed on your machine. Lets use yeoman/generator-angular to scaffold our application.

Install dependencies:

Scaffold our sample application:

This creates skeleton for our application. We need to build it using ‘grunt build’ command and run server using ‘grunt serve’. If we go to http://localhost:9000 we see our application running.

Amazing! Now when we have our initial setup done, the next step is to take a closer look at grunt-ng-constant. First of all, let’s install it using npm:

Open our Gruntfile.js that was generated for us by generator-angular and add grunt-ng-constant, to required grunt tasks, like those:

Now we need to create ‘config’ folder inside root directory and add 3 json files inside it:

1) default.json — to store default configuration values and also values that are common for both environments.

2) development.json — to store configuration values specific for development environment.

3) production.json — to store configuration values specific to production environment.

When we have this config files created, let’s create another file in config folder and call it constant-template.ejs:

Everything we do here is just creating Angular module and connecting all constants that are returned by grunt-ng-constant to this module.

Now we need to edit our Gruntfile one more time to configure new task inside grunt.initConfig:

At this moment we have our task configured, let’s change build task to support environment param. So when we run build command with target === ‘production’, we get our config module with production values in other cases we have our config module configured for development. It looks like this:

It’s high time to run our build command and check our autogenerated config.js files! Production config:

Development config:

I’ve cheated a little bit here because I formatted config.js file directly to show all content of it. However, now we can run a simple command to build our dynamic config file. Splendid!

The last thing to do is to connect our config.js file to index.html and add config module as a dependency to our ‘sampleApp’ module:

Now we can inject our ‘ENV’ constant everywhere we need in our application like this:

Finally, this is it! I use the above described approach in my Angular projects, and I really think it is very helpful if you need to have different environments while developing your applications using this JS framework.