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.

You might enjoy


I've been meaning to write a post about my thoughts, feelings and emotions I experience in my life as…

As a .NET Web developer, I'm always looking for better ways to get Angular and MVC.NET to play…

Tim Sommer

I'm a Web Developer with +7 years of experience in the .Net framework, with a focus on HTML5 and JavaScript.

Belgium, Antwerp
comments powered by Disqus
OWIC
Member of The Internet Defense League