Problem Overview
When minifying JavaScript code, AngularJS loses track of function parameter names, causing dependency injection (DI) to fail. This results in errors like:
Error: [$injector:unpr] Unknown provider: myServiceProvider <- myService
1. Why Does Minification Break Dependency Injection?
Understanding Minification
- Minification shortens variable and function names to reduce file size.
- Example: jsCopyEdit
function MyController($scope, myService) { $scope.message = myService.getMessage(); }
gets minified to: jsCopyEditfunction MyController(a, b) { a.message = b.getMessage(); }
- AngularJS relies on function parameter names to identify dependencies.
- Since
$scope
andmyService
were renamed toa
andb
, AngularJS can’t recognize them.
2. Fixing DI Issues with Explicit Annotation
There are three ways to explicitly define dependencies to prevent minification issues.
1. Using $inject
Array Annotation (Best Practice)
Correct Code:
angular.module('myApp', [])
.controller('MyController', ['$scope', 'myService', function($scope, myService) {
$scope.message = myService.getMessage();
}]);
Why This Works?
- The
$inject
array explicitly defines dependencies before minification. - During minification, even if
$scope
andmyService
are renamed, AngularJS still knows their original names.
2. Defining $inject
Property (For Class-Based Services)
Correct Code:
function MyService($http) {
this.getData = function() {
return $http.get('/api/data');
};
}
MyService.$inject = ['$http'];
angular.module('myApp', [])
.service('MyService', MyService);
Why This Works?
$inject
tells AngularJS explicitly which services to inject, even after minification.
3. Using Inline Annotation with $inject
Correct Code:
angular.module('myApp', [])
.factory('myFactory', myFactory);
myFactory.$inject = ['$http'];
function myFactory($http) {
return {
getData: function() {
return $http.get('/api/data');
}
};
}
Why This Works?
- The
$inject
annotation explicitly provides the dependency names, ensuring safe minification.
3. Common Mistakes That Break DI After Minification
1. Implicit Dependency Injection
Incorrect Code (Fails After Minification)
angular.module('myApp', [])
.controller('MyController', function($scope, myService) {
$scope.message = myService.getMessage();
});
Problem:
- The function parameters (
$scope
,myService
) will be renamed when minified. - AngularJS will not recognize them.
2. Using Arrow Functions for Controllers
Incorrect Code (Fails After Minification)
angular.module('myApp', [])
.controller('MyController', ($scope, myService) => {
$scope.message = myService.getMessage();
});
Problem:
- Arrow functions do not have their own
this
context, breaking AngularJS’s DI system. - Even with
$inject
, it won’t work.
Fix: Use Regular Functions
angular.module('myApp', [])
.controller('MyController', ['$scope', 'myService', function($scope, myService) {
$scope.message = myService.getMessage();
}]);
3. Forgetting $inject
in Factory Services
Incorrect Code (Fails After Minification)
angular.module('myApp', [])
.factory('myFactory', function($http) {
return {
getData: function() {
return $http.get('/api/data');
}
};
});
Fix: Add $inject
angular.module('myApp', [])
.factory('myFactory', ['$http', function($http) {
return {
getData: function() {
return $http.get('/api/data');
}
};
}]);
4. Debugging DI Errors in AngularJS
If you still get dependency injection errors, use these methods:
1. Enable ng-strict-di
to Detect DI Issues
Add this to your HTML file:
<html ng-app="myApp" ng-strict-di>
- This forces AngularJS to throw errors immediately for missing DI annotations.
2. Use AngularJS Dependency Annotation Check
Run this in the Chrome DevTools Console:
angular.injector(['myApp']).annotate(function(myService) {});
- If it does not return
['myService']
, explicit annotation is missing.
3. Enable Strict DI Mode in JavaScript
angular.bootstrap(document, ['myApp'], { strictDi: true });
- Forces strict dependency checking at runtime.
5. Summary
Why Does DI Fail After Minification?
- Minification renames function parameters, making AngularJS lose track of dependencies.
- This causes unknown provider (
[$injector:unpr]
) and missing dependency errors.
How to Fix It?
Use $inject
array annotation
Define $inject
property for class-based components
Never use arrow functions (=>
) for controllers/services
Enable ng-strict-di
to catch issues early