Annoyed by this error?
Error: [$injector:unpr] Unknown provider: cProvider <- c
This will help find non-annotated Angular things that will break when minified. Can also be used with ngmin/ng-annotate and ng-strict-di
to find instances where they didn't apply a fix or throw an informative error.
To do this, we must edit angular.js
.
In the following code blocks, the expression assigned to fnArgs
is taken from the annotate
function. The variables should be available within the angular.js
IIFE.
We will find Angular things declared without an array of string dependencies around the definition (Inline Array Annotation) or on an $inject
property ($inject
Property Annotation) and log them to the console. Without declared dependency names, the "magic" method (Implicit Annotation) is used to determine them, which breaks on minified code.
ngmin/ng-annotate solve this issue by finding such things with undeclared dependencies and annotating them before they're minified. However, if you're having a problem with ngmin/ng-annotate (see example) or not using them at all, this can help you.
Make sure your minifier does not remove console logs: they are used to notify of unannotated things.
Find the instantiate
function in the $injector
definition and add the following before invoke
is called, where Type
is the first argument to instantiate
.
if (isFunction(Type) && (!Type.$inject || !Type.$inject.length)) {
var fnArgs = Type.toString().replace(STRIP_COMMENTS, '').match(FN_ARGS)[1].split(FN_ARG_SPLIT);
if (fnArgs && fnArgs.length && fnArgs[0].length) {
console.log('provider needs inline deps', fnArgs, Type);
}
}
You can search for @name $injector
and scroll down, or search directly for the instantiate
function definition if your editor allows.
Find the $ControllerProvider()
function and add the following before $injector.instantiate
is called, where expression
and locals
are the first and second arguments to the returned function in this.$get
.
if (isFunction(expression) && (!expression.$inject || !expression.$inject.length)) {
var fnArgs = expression.toString().replace(STRIP_COMMENTS, '').match(FN_ARGS)[1].split(FN_ARG_SPLIT);
if (fnArgs && fnArgs.length) {
console.log('$controller needs inline deps', fnArgs, expression, locals);
}
}
- angular@1.2.15
- grunt-ngmin@0.0.3
The following directive controller is found by ngmin and annotated correctly.
myModule.directive('myDirective', function () {
return {
controller: function ($scope) {
$scope.name = 'foo';
},
template: '<div>My name is {{name}}</div>'
};
});
However, when the directive is directly annotated, ngmin fails to annotate the controller within.
myModule.directive('myDirective', [
'myService',
function (myService) {
return {
controller: function ($scope) {
$scope.name = 'foo';
},
template: '<div>My name is {{name}}</div>'
};
}
]);
The same occurs with using ng-strict-di
on the same element as ng-app
(see the AngularJS guide).
ng-annotate has no problem with the above example: it finds and annotates the controller correctly.