The Common Way
After doing a bit of a search online I came pass a method that appears to be pretty popular but IMHO it felt a little clunky. It’s been well documented at the following links and appears to have originated from a post by Ifeanyi Isitor.
- http://ify.io/lazy-loading-in-angularjs/ (appears to be the original post)
This is entirely an opinion – but to me this method feels like it breaks the conceptual integrity of AngularJS by maintaining a reference to the service providers beyond the initial config. I don’t have any real proof that this opinion is anything more than a feeling (I would need to go deep into the AngularJS source to find out for certain), but nonetheless it just didn’t appear correct to me.
Additionally I didn’t really like the idea of changing the methods I use to declare my controllers, directives, and services. Other than it being a slight pain if I want to remove lazy loading (and I can’t imagine a reason why I would need to) there isn’t really anything specific I can point to that makes this method wrong, it just doesn’t feel right to me. For me it’s like saying, “The rat the cat the dog chased killed ate the malt.”, rather than just saying, “The rat ate the malt.”. Although the first sentence is grammatically fine, it just doesn’t feel right.
So with this in mind I decided to come up with a better way. I think I have – but I’ll leave that to you to decide.
The Less Awkward Method (IMHO)
I’ve created a sample project (I use WebStorm for web development which may explain why I have referenced files as I have) which you can download from my personal GitHub account at https://github.com/chris-tomich/mymemorysucks/tree/master/LazyLoadingAngularJS. For this example I use RequireJS (http://requirejs.org/) to do the actual loading for me so feel free to use whatever you feel most comfortable with.
So the critical problem in lazy loading AngularJS controllers, directives, and services is that the declarations for those components need to be done before AngularJS begins it’s “bootstrapping” phase. If you attempt to do the declarations after bootstrapping the application you’ll get errors about your AngularJS components being undefined etc. and none of it will work (I’m simplifying this but hopefully you get the point / experienced the error messages).
As a result of this separation, the bulk of the code for your controller, directive, or service will now reside in separate file/s. The only thing left to do now is to make sure these are marked as a dependency and loaded when they are requested by the routeProvider. You do the loading of the dependency the same way used in other posts which is through the “resolve” attribute during configuration of your routes. Below is an example of how I’ve done it in my sample project.
I’ve tested this method both in 1.2.28 and 1.3.15 and it seems to work fine. Although the samples I’ve shown here are for controllers, it is exactly the same for directives and services in that you separate out the meat of your code into a different file and then call that object/function from within the declaration. To see those types of components in action download my sample project at https://github.com/chris-tomich/mymemorysucks/tree/master/LazyLoadingAngularJS.
One other benefit of using this method is that in a scenario where you want to get rid of the lazy loading, it doesn’t require much re-coding. It’s just a matter of changing the routeProvider declarations and adding the <script> tag declarations for all your scripts.