Rails 3 + angularjs + minification does not work in production: Unknown provider: eProvider
Asked Answered
W

3

21

I've followed all the instructions I can find for fixing minification, e.g.

var MyController = function(renamed$scope, renamedGreeter) {
...
}
MyController.$inject = ['$scope', 'greeter'];

and

someModule.factory('greeter', ['$window', function(renamed$window) {
...;
}]);

yet angular refuses to work still. It always throws the error "Unknown provider: eProvider"

Here are my two attempts to get it working... can anyone help?

https://github.com/jemminger/angular-test1

https://github.com/jemminger/angular-test2

They've already had the assets precompiled and development mode is configured to work as production, so you should just be able to "rails s" to see it (not) work.

Westsouthwest answered 19/11, 2012 at 17:59 Comment(1)
Depending on one's goals, a possible solution is to scale back the minifier to less-desctructive optimizations. In the case of uglify you can use the mangle: false configuration and still save quite a few kilobytes with whitespace removal.Ivories
W
60

Found it! They never said to apply the injection fixes to services too... The solution is to change this:

angular.module('itemServices', ['ngResource']).
    factory('Item', function($resource){
      return $resource('items/:item_id.json', {}, {
        query: {method:'GET', params:{ item_id: 'all' }, isArray:true}
      });
    });

to this:

angular.module('itemServices', ['ngResource']).
    factory('Item', ['$resource', function($resource){
      return $resource('items/:item_id.json', {}, {
        query: {method:'GET', params:{ item_id: 'all' }, isArray:true}
      });
    }]);
Westsouthwest answered 19/11, 2012 at 18:19 Comment(2)
@Josiah, it works because the dependency injection allows the function to survive js minification.Westsouthwest
I suggest using ng-strict-di (docs.angularjs.org/api/ng/directive/ngApp) to detect the issue also in development envHuba
S
14

Remember, to also use DI on controllers within directives. Took me hours... CS example:

wrong:

controller: ($scope) ->
  $scope.closeModal = ->
    ModalService.close()

right:

controller: ["$scope"
  ($scope) ->
    $scope.closeModal = ->
      ModalService.close()
]
Strunk answered 4/9, 2013 at 16:52 Comment(1)
This would be more helpful if it didn't rely on the reader using your choice of scripting solutions.Greathouse
O
6

Make sure to apply the DI pattern to ALL function definitions that require injection within your module. It can be easy to miss one. If you're using a routeProvider, factory, services, etc., they all need to have the DI pattern applied. I ended up deploying multiple times before I caught them all :P

Orangeism answered 13/6, 2013 at 20:50 Comment(1)
'It can be easy to miss one.' Exactly. You must apply the pattern even to the controllers defined in directives! I wasted one wonderful hour searching for this bug.Recce

© 2022 - 2024 — McMap. All rights reserved.