We have a working AngularJS single page application (SPA),
but the moment we minimized the JS files, the app breaks with an Unknown
Provider error.
When facing this problem, we need to look at how we are
injecting dependencies into our modules because when minimizing the files, the
parameters name will be changed and Angular would not be able to resolve the
dependency.
Implicit (bad)
Injection Approach
We start by looking at a common way of injecting
dependencies which can lead into a problem.
var app = angular.module('app', []);
app.config(appConfig);
app.run(initApp);
app.controller('appCtrl', appCtrl);
function appConfig($myProvider) {
$myProvider.appConfig();
}
function initApp(myService) {
myService.initApp();
}
function appCtrl($scope) {
$scope.appCtrl = 'hi ozkary';
}
In this example, we are defining a module that has a
configuration, app initialization and controller functions. When we define those
functions, we are only setting the function names, but the function implementation
has a parameter which indicates what needs to be injected. The problem with
this approach is that when this code is minimized, it looks as follows:
function i(n){n.appConfig()}
function r(n){n.initApp()}
function u(n){n.appCtrl="hi
ozkary"}
var t=n.module("app",[]);
t.config(i);
t.run(r);
t.controller("appCtrl",u)
As we can see, the parameters are renamed to “n” at which
point there is probably no dependency with such name, and Angular is not able
to find it. This is why we get the ugly Unknown Provider error.
Explicit Injection Declaration
To address this problem, we need to change the way we
declare the dependencies using an array as parameter. With this approach, our
code changes to this:
var app = angular.module('app', []);
app.config(['$myProvider', appConfig]);
app.run(['myService', initApp]);
app.controller('appCtrl', ['$scope', appCtrl]);
function appConfig($myProvider) {
$myProvider.appConfig();
}
function initApp(myService) {
myService.initApp();
}
function appCtrl($scope) {
$scope.appCtrl = 'hi ozkary';
}
The advantage of this approach that is that the array values
are not mangled by the minimization process, and this allows Angular to find
and inject the dependency. The minimized version of our code now looks like this:
function i(n){n.appConfig()}
function r(n){n.initApp()}
function u(n){n.appCtrl="hi
ozkary"}
var t=n.module("app",[]);
t.config(["$myProvider",i]);
t.run(["myService",r]);
t.controller("appCtrl",["$scope",u])
Yes, the dependency name is kept, and Angular should be able
to resolve it. We can also notice that the parameter “n” is still used in the
function, but what is important is the name declared on the array.
Moving forward, we should explicitly define our dependencies
as minimization of resources is now a must standard.
Hope it helps.
0 comments :
Post a Comment
What do you think?