You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Because `<lib-header>` is optional, the element can appear in the template in its minimal form, `<lib-card />`.
53
53
In this case, `<lib-header>` is not used and you would expect it to be tree-shaken, but that is not what happens.
54
-
This is because `LibCardComponent` actually contains two references to the `LibHeaderComponent`:
54
+
This is because `LibCard` actually contains two references to the `LibHeader`:
55
55
56
56
```ts
57
-
readonlyheader=contentChild(LibHeaderComponent);
57
+
readonlyheader=contentChild(LibHeader);
58
58
```
59
59
60
-
- One of these reference is in the _type position_-- that is, it specifies `LibHeaderComponent` as a type: `readonly header: Signal<LibHeaderComponent|undefined>`.
61
-
- The other reference is in the _value position_-- that is, `LibHeaderComponent` is the value passed into the `contentChild` function: `contentChild(LibHeaderComponent)`.
60
+
- One of these reference is in the _type position_-- that is, it specifies `LibHeader` as a type: `readonly header: Signal<LibHeader|undefined>`.
61
+
- The other reference is in the _value position_-- that is, `LibHeader` is the value passed into the `contentChild` function: `contentChild(LibHeader)`.
62
62
63
63
The compiler handles token references in these positions differently:
64
64
65
65
- The compiler erases _type position_ references after conversion from TypeScript, so they have no impact on tree-shaking.
66
66
- The compiler must keep _value position_ references at runtime, which **prevents** the component from being tree-shaken.
67
67
68
-
In the example, the compiler retains the `LibHeaderComponent` token that occurs in the value position.
68
+
In the example, the compiler retains the `LibHeader` token that occurs in the value position.
69
69
This prevents the referenced component from being tree-shaken, even if the application does not actually use `<lib-header>` anywhere.
70
-
If `LibHeaderComponent` 's code, template, and styles combine to become too large, including it unnecessarily can significantly increase the size of the client application.
70
+
If `LibHeader` 's code, template, and styles combine to become too large, including it unnecessarily can significantly increase the size of the client application.
71
71
72
72
## When to use the lightweight injection token pattern
73
73
@@ -77,18 +77,18 @@ There are two cases when that can happen:
77
77
- The token is used in the value position of a [content query](guide/components/queries#content-queries).
78
78
- The token is used with the `inject` function.
79
79
80
-
In the following example, both uses of the `OtherComponent` token cause retention of `OtherComponent`, preventing it from being tree-shaken when it is not used:
80
+
In the following example, both uses of the `CustomOther` token cause retention of `CustomOther`, preventing it from being tree-shaken when it is not used:
81
81
82
82
```ts {highlight: [[2],[4]]}
83
-
classMyComponent {
84
-
privatereadonly other =inject(OtherComponent, {optional: true});
83
+
classApp {
84
+
privatereadonly other =inject(CustomOther, {optional: true});
85
85
86
-
readonly header =contentChild(OtherComponent);
86
+
readonly header =contentChild(CustomOther);
87
87
}
88
88
```
89
89
90
90
Although tokens used only as type specifiers are removed when converted to JavaScript, all tokens used for dependency injection are needed at runtime.
91
-
When using `inject(OtherComponent)`, `OtherComponent` is passed as a value argument.
91
+
When using `inject(CustomOther)`, `CustomOther` is passed as a value argument.
92
92
The token is now in a value position, which causes the tree-shaker to keep the reference.
93
93
94
94
HELPFUL: Libraries should use [tree-shakable providers](guide/di/dependency-injection#providing-dependency) for all services, providing dependencies at the root level rather than in components or modules.
@@ -98,33 +98,33 @@ HELPFUL: Libraries should use [tree-shakable providers](guide/di/dependency-inje
98
98
The lightweight injection token design pattern consists of using a small abstract class as an injection token, and providing the actual implementation at a later stage.
99
99
The abstract class is retained, not tree-shaken, but it is small and has no material impact on the application size.
100
100
101
-
The following example shows how this works for the `LibHeaderComponent`:
101
+
The following example shows how this works for the `LibHeader`:
In this example, the `LibCardComponent` implementation no longer refers to `LibHeaderComponent` in either the type position or the value position.
123
-
This lets full tree-shaking of `LibHeaderComponent` take place.
122
+
In this example, the `LibCard` implementation no longer refers to `LibHeader` in either the type position or the value position.
123
+
This lets full tree-shaking of `LibHeader` take place.
124
124
The `LibHeaderToken` is retained, but it is only a class declaration, with no concrete implementation.
125
125
It is small and does not materially impact the application size when retained after compilation.
126
126
127
-
Instead, `LibHeaderComponent` itself implements the abstract `LibHeaderToken` class.
127
+
Instead, `LibHeader` itself implements the abstract `LibHeaderToken` class.
128
128
You can safely use that token as the provider in the component definition, allowing Angular to correctly inject the concrete type.
129
129
130
130
To summarize, the lightweight injection token pattern consists of the following:
@@ -141,8 +141,8 @@ The token is now an abstract class. Since the injectable component implements th
141
141
The implementation of the method, with all its code overhead, resides in the injectable component that can be tree-shaken.
142
142
This lets the parent communicate with the child, if it is present, in a type-safe manner.
143
143
144
-
For example, the `LibCardComponent` now queries `LibHeaderToken` rather than `LibHeaderComponent`.
145
-
The following example shows how the pattern lets `LibCardComponent` communicate with the `LibHeaderComponent` without actually referring to `LibHeaderComponent`:
144
+
For example, the `LibCard` now queries `LibHeaderToken` rather than `LibHeader`.
145
+
The following example shows how the pattern lets `LibCard` communicate with the `LibHeader` without actually referring to `LibHeader`:
146
146
147
147
```ts {highlight: [[2],[9],[11],[19]]}
148
148
abstractclassLibHeaderToken {
@@ -151,9 +151,9 @@ abstract class LibHeaderToken {
0 commit comments