Minification safe Angular.js

17 / Feb / 2015 by Brij Kishor 0 comments

Recently, I wanted to upgrade my Grails application to 2.4.3 and also switched from resource plugin to assets-pipeline plugin. As everything was going good in the development, so I pushed it to QA after which I was bombarded with JavaScript errors and missing providers.

What has happened?? So here, Angular.js internal dependency injection was broken… :(

Since Angular infers the controller’s dependencies from the names of arguments to the controller’s constructor function, if you were to minify the JavaScript code for controller, all of its function arguments would be minified as well, and the dependency injector would not be able to identify services correctly.

Solution for the problem,  ‘annotations’ – an array that contains the names of the dependency a function needs, and the function itself.

By annotating the function with the names of the dependencies, provided as strings, which will not get minified.

There are two ways to provide these injection annotations:

1. Create a $inject property on the controller function which holds an array of strings. Each string in the array is the name of the service to inject for the corresponding parameter. we would write:

var myController = function ($scope, $http) {//your code}
myController.$inject = ['$scope', '$http'];

2. Use an inline annotation where, instead of just providing the function, you provide an array. This array contains a list of the service names, followed by the function itself.

function myController ($scope, $http) {//your code}
myApp.controller('myController', ['$scope', '$http', myController]);

Second method is a common one if you want to provide anonymous function like:

myApp.controller('myController', ['$scope', '$http', function ($scope, $http){
//your controller code

What about services, directives and factories. Let us see the examples below:

For modules:

var myModule = angular.module('myModule',
[ '$scope', '$http' /*Dependencies as an array of strings.*/])

For services:

myModule.service('serviceName', ['$scope', '$http', function($scope, $http) {
//your code

For directives:

myModule.directive('myDirective', ['$scope', '$http', function($scope, $http) {
//your code

For factories:

myModule.factory('myFactory', ['$scope', '$http', function($scope, $http) {
//your code

Using inline annotation is preferred and mentioned in angular dependency injection docs as well. By simply following above code convention you’ll never have to worry about minification surprises.


Leave a comment -