Angular's 'Unkown Provider' problem after deployment

We've all been there at some point. Your app works great on your machine, all features are ready to be pushed to dev/acc, and when you do, all hell breaks loose.

Specific to Angular apps, the following error gets thrown a lot after you minify your JavaScript:

Unknown provider: eProvider <- e

And you'll be like 'What eProvider, who put it there, where did that come from?' :). Don't worry, we've all been there at one point.

This problem will occur when the injector service is not able to retrieve an implementation that you requested in your module. In this case, the eProvider.

Take a look at this controller:

angular
    .module('controllers')
    .controller('SomeController', function SomeController($scope, $http) {
	    $http.get('/somedata').success(function(data) {
			$scope.somedata = data;
		});
	});

This is completely valid code, it will work just as you'd expect it to.
But when this gets minified, the '$scope' and '$http' parameters will be renamed to something else. Something like this:

.controller('SomeController', function SomeController(e, a) {

Notice the 'e' parameter, this explains the eProvider error. The inject service of angular is looking to inject the eProvider, and it is complaining that it can't find it.

There are two correct ways to fix this:

Using the $inject service:

angular.module('controllers').controller('SomeController', SomeController);

function SomeController($scope, $http) {
    $http.get('/somedata').success(function(data) {
		$scope.somedata = data;
	});
}

SomeController.$inject = ['$scope', '$http'];

This will work after minification. Regardless of the variable name provided as parameters in the SomeController function, the injector service will always inject the '$scope' and '$http' implementations.

By using string value representations while injecting your implementations:

angular
    .module('controllers')
    .controller('SomeController', ['$scope', '$http', function SomeController($scope, $http) {
	    $http.get('/somedata').success(function(data) {
			$scope.somedata = data;
		});
	}]);

In this code sample renaming the parameters won't have any effect either, because '$scope' and '$http' can always be identified using the string values.

Newer Articles
Older Articles