Vincent Durmont

« Back

August 2, 2015

Environment configuration with Angular and Grunt

When I write an Angular application, I usually create a constant module to store my environment variables:

angular.module("myApp").constant("Config", {
API_URL: "http://localhost:8080/",
GITHUB_CLIENT_ID: "xxxxxxxxxxxxxxx",
...
});

I can then inject my config anywhere in the application and use those variables.

These variables can change based on where the app is deployed and I needed a simple way to define several environments. Since I use Grunt to build, test and deploy my javascript apps, I wanted to find something that would be seamlessly integrated in my build process.

In this post I will give you an easy way to achieve this, using grunt-replace.

Angular constant module

Modify the values by putting @@ followed by the key name.

angular.module("myApp").constant("Config", {
API_URL: "@@API_URL",
GITHUB_CLIENT_ID: "@@GITHUB_CLIENT_ID",
...
});

Create a config file for each environment

For example, if I have a development and a production environment:

./src/config/development.json

{
API_URL: "http://localhost:8080/",
GITHUB_CLIENT_ID: "xxxxxxxxxxxxxxx",
...
}

./src/config/production.json

{
API_URL: "http://api.myapp.com/",
GITHUB_CLIENT_ID: "yyyyyyyyyyyyyyy",
...
}

Add grunt-replace to your Gruntfile

Here are the interesting parts of the Gruntfile.js:

module.exports = function (grunt) {
// Method used to generate a config environment
var getConfig = function (configName) {
return {
options: {
patterns: [{
json: grunt.file.readJSON("./src/config/" + configName + ".json")
}]
},
files: [{
expand: true,
flatten: true,
// Here "dist/js/app.min.js" is a minified script with my whole application
src: ["dist/js/app.min.js"],
dest: "dist/js/"
}]
};
};

grunt.initConfig({
// Config...

// Replace the configuration according to the profile
replace: {
development: getConfig("development"),
production: getConfig("production")
},

// Config...
});

// Load the NPM tasks
grunt.loadNpmTasks("grunt-replace");
// ...

// Register your tasks
grunt.registerTask("default", [..., "replace:development", ...]);
grunt.registerTask("production", [..., "replace:production", ...]);
};

Run!

When you will run grunt, the replace:development task will be used and all your keys will be replaced by the values in development.json. The same will happen for replace:production or any other profile you will have defined.