Understanding Angular's deferrable views - Part. 2
Inside the magic
Matthieu Riegler -
I presented to you in a previous article the basics of deferrable views in Angular. Now that you know what you can do with them, let's in the technical details to extract the performance out of them !
How do they work
Under the hood, the deferrable views are a feature of the angular compiler.
When compiling the templates, the Angular compiler extracts all dependencies used within the @defer
block into a separate function and generates a number of dynamic imports to load corresponding JS chunks.
Template | compiled |
---|---|
|
|
Basically this @defer
block results in a single dynamic import that will be executed when the trigger fires.
Nesting blocks
When there are multiple dependencies in a @defer
block they end-up in the same import function (except dependencies located inside of nested @defer
blocks).
Template | compiled |
---|---|
|
|
In this scenario, we have 2 @defer
blocks resulting in 2 generated lazy-loading functions.
When the trigger for block BlockA is fired, both chunks would be loaded, but only one of the components would be rendered. The third chunk would only be loaded, once we make it into the last @else
block.
So, if all of the components are "heavy", you may want to consider wrapping those components into individual @defer
blocks (similar to what we have in the last @else
block). The same logic would apply if we replace the @if
block with a @switch
block.
@for
or @defer
first ?
Now that we know that nesting has implications, let's compare the differences when using an @for
block in combination with a @defer
block.
First we need to understand the runtime implications of a @defer
block.
At runtime, a @defer
block's content is represented by an embedded view (as if the content was in an <ng-template>
). Next look at 2 possibles combinations :
@defer inside of @for |
@for inside of @defer |
---|---|
|
|
In the left example, for each item there will be an embedded view created as a part of @for
loop and a nested embedded view created for each @defer
block. The number of embedded views would be items.length * 2
and the number of defer block instances would be items.length
.
The right example would produce items.length + 1
embedded views and a single defer block instance.
@defer inside of @for |
@for inside of @defer |
---|---|
|
|
So for the cases above, where the contents of the @for
loop doesn't have conditions with different "heavy" components, it would make sense to choose the right example where the @defer
is outside of the @for
loop.
However, if the contents of the @for
loop has some extra logic and involves showing different "heavy" components depending on certain conditions, you may want to choose the left example where @defer
is inside of the @for
loop to wrap a particular component or a group of components.
Now that you know the implications of the usage:
If you have any other questions on this great new feature, feel free to reach out to me on Twitter !