Loading AngularJS Components With RequireJS After Application Bootstrap
Posted November 5, 2013 at 9:40 AM by Ben Nadel
Yesterday, I looked at loading AngularJS components after your AngularJS application has been bootstrapped. In that experiment I simply waited until DOM-Ready before I registered said components. That didn't really make them lazy-loaded, it only demonstrated that the components could be registered post-bootstrap. Today, I wanted to play around with using RequireJS in order to make the components truly lazy-loaded.
When I think about a cohesive set of AngularJS components, I think about two things: the JavaScript parts and the HTML parts. In order for RequireJS to lazy-load some aspect of our AngularJS application, it will have to load both the JavaScript objects and the HTML templates. In this demo, I'm using the RequireJS plugin - text.js - to load said templates.
Because RequireJS is asynchronous in nature, the code that lazy-loads the AngularJS components must also be asynchronous. This means that it must operate within some callback-based workflow. Since AngularJS already has $q - a Deferred / Promise library - I decided to encapsulate the RequireJS behavior behind a $q promise. This has the added benefit that multiple sources can listen for the resolution of the lazy-loaded components.
Simply loading and executing the "lazy" JavaScript file will register the JavaScript components. The HTML templates, on the other hand, require a little bit more work; once they have been loaded by RequireJS, the Script tags (type="text/ng-template") have to be explicitly injected into the AngularJS template cache.
That said, the following demo is yesterday's demo, refactored to use RequireJS:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
|
ng-controller="AppController">
Loading AngularJS Components With RequireJS After Application Bootstrap
ng-switch="subview">
ng-switch-when="before">
Before app bootstrap.
ng-switch-when="after" ng-include=" 'after.htm' ">
As you can see, the controller that wants to make use of the lazy-loaded module must use the "withLazyModule()" function. This function returns a promise; however, it also accepts callbacks which will be automatically wired into the underlying deferred resolution. When the promise has been resolved, the lazy-loaded components have been injected into the AngularJS application and are ready to be consumed.
The two files that are loaded via RequireJS are the HTML templates:
1234567891011121314 |
... and the JavaScript components:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
|
As you can see, the lazy-loaded components are registered in the same way that any of your AngularJS components are registered. We didn't use a "module" here (as in angular.module()), since the new module wouldn't populate the correct dependency injection container.
There's so much more to think about here, but this is pretty exciting! I love the idea of being able to lazy-load parts of your AngularJS application. It definitely requires some more thinking and more organization; but, it could really be great for load-times.
No comments:
Post a Comment