Angular
DI with Lazy loading
What is DI?
Dependency injection, or DI, is a design pattern in which a class requests dependencies from external sources rather than creating them.
How DI works?
When Angular creates a new instance of a component class, it determines which services or other dependencies that component needs by looking at the constructor parameter types.
How DI works?
When Angular discovers that a component depends on a service, it first checks if the injector has any existing instances of that service
DI tree
Angular Creates two injector trees. Module Injector tree and Element Injector tree.
Module Injector tree: root module and for every lazy loaded module.
Element Injector tree is for DOM elements like Components & Directives.
Module DI tree
Elements DI tree
What is lazy loading?
Lazy Loading - a design pattern that loads NgModules as needed. Lazy loading helps keep initial bundle sizes smaller, which in turn helps decrease load times.
How is lazy loading related to DI?
For every lazy-loaded module Angular creates an injector which is inherited from parent injector.
What can go wrong?
Example project
We have a project with 3 modules:
* Core module
* Lazy module
* Lazy module 2
Core module
Core module contains CoreService and CoreInterceptor
Lazy module
Lazy Module contains a base router with a single router and component for that route and its own LazyInterceptor (just empty interceptor like Core one)
Lazy 2 module
Lazy 2 Module is very similar to Lazy Module but with 1 key difference - lazy 2 doesn't provide any providers.
Lazy 2 logs
In the console, we can see that in lazy 2 module injected array of 1 single interceptor - CoreInterceptor. The same array we can see in coreService. Nothing special, seems like expected behaviour
Lazy logs
From this part things became unexpected. As we can see Lazy module injected an array of interceptors with the LazyInterceptor, but the coreService has a different array of interceptors. Also why LazyModule contain only LazyInterceptor and not LazyInterceptor and CoreInterceptor ?
Lazy logs explanation
So why does this happen? All because of DI, and if we track the DI tree from previous slides we can understand what is going on.
First of all, we need to remind ourselves that each module has its own injector. So if we provide an interceptor in the lazy module it will create an array of interceptors in a lazy module injector and next time our lazy module component or service tries to get this array of interceptors it will look for it in their module, in our case - lazy module injector. Because our lazy module injector has overridden interceptors array with new interceptor we see only [LazyInterceptor] array
Lazy logs explanation
The second question that why coreService does not have the same array of overridden interceptors as LazyModule does?
The second thing about DI is when a lazy module injector doesn't find a provider he will ask about it in the parent injector (root or another lazy module).
So in our lazy module, we don't have CoreService so the lazy module injector asks about service in his parent injector (root). Parent injector has service but he will resolve this dependency with its own scope and will provide interceptors array from itself, not lazy module.
More info
Test project
Thanks for your attention
Angular. DI and Lazy loading
By TenantCloud
Angular. DI and Lazy loading
Describe general information about DI and Lazy Loading and deeply investigate some features and explain potential confusing behavior
- 153