Reputation: 3952
Thanks to the great article from Dan Wahlin, I managed to implement lazy loading of Angular's controllers and services. However, there does not seem to be a clean way to lazy load independent modules.
To better explain my question, assume that I have an app would be structure as below without RequireJS:
// Create independent module 'dataServices' module with 'Pictures' object
angular.module("dataServices", []).factory("Pictures", function (...) {...});
// Create 'webapp' ng-app, with dependency to 'dataServices', defining controllers
angular.module("webapp", ['dataServices'])
.controller("View1Controller", function (...) {...})
.controller("View2Controller", function (...) {...});
Here is the sample app with RequireJS in Plunker:
http://plnkr.co/aiarzVpMJchYPjFRrkwn
The core of the problem is that Angular does not allow adding dependency to ng-app
post instantiation. As result, my solution is to use angular.injector
to retrieve the instance of Picture
object to be used in my View2Controller
. See js/scripts/controllers/ctrl2.js
file.
This creates 2 problems for me:
Have any of you figured out how to lazy load independent module using RequireJS and somehow hook this module in angular so normal angular dependency injection syntax can be used?
Note:
The question is on lazy loading of independent module. One simple solution to this specific example is to create "Pictures" object using cached $providers during ng-app.config
but that is not what I am looking for. I am looking for solution that works with 3rd party module such as angular-resource
.
Upvotes: 22
Views: 26158
Reputation: 40298
Take a look at my project in GitHub: angular-require-lazy
This project is intended to demonstrate an idea and motivate discussions. But is does what you want (check expenses-view.js, it loads ng-grid lazily).
I am very interested in comments, ideas etc.
(EDIT) The ng-grid Angular module is lazy loaded as follows:
expenses-view.js
is loaded lazily, when the /expenses
route is activatedexpenses-view.js
specifies ng-grid as a dependency, so RequireJs loads ng-grid firstangular.module(...)
In order to accomplish this, I replaced (proxied actually) the real angular.module
method with my own, that supports laziness. See bootstrap.js and route-config.js (the functions initLazyModules()
and callRunBlocks()
).
This implementation has its drawbacks that you should be aware of:
Upvotes: 10
Reputation: 8416
It looks like the Node.js module ocLazyLoad
defines a way of doing this lazy-loading, though I'm not sure how it fares, performance-wise, compared to the methods in the other answers or hard-coding the dependencies. Any info on this would be appreciated. One interesting thing is that the other answers need RequireJS
to operate, while ocLazyLoad
doesn't.
It looks like ocLazyLoad
defines another provider that injects the dependency after the containing module has already been instantiated. It seems to do this by essentially replicating some low-level Angular behavior, like module loading and providing, hence why it looks so complicated. It looks like it adds just about every core Angular module as a dependency: $compileProvider
, $q
, $injector
, ng
, and so many more.
Upvotes: 1
Reputation: 3952
I finalized my own implementation called angularAMD
and here is the sample site that uses it:
http://marcoslin.github.io/angularAMD/
It handles config functions and out of order module definitions.
Hopefully this can help other looking for something to help them with RequireJS and AngularJS integration.
Upvotes: 17