parent
47b7898697
commit
1ccc3242f1
73
packages/core/src/render3/TREE_SHAKING.md
Normal file
73
packages/core/src/render3/TREE_SHAKING.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# Tree Shaking Principles
|
||||||
|
|
||||||
|
When designing code please keep these principles in mind
|
||||||
|
|
||||||
|
## Enums for features are not-tree-shakable
|
||||||
|
|
||||||
|
Here is an example of code which is not tree shakable.
|
||||||
|
|
||||||
|
```
|
||||||
|
export function query<T>(
|
||||||
|
predicate: Type<any>| string[], descend?: boolean,
|
||||||
|
read?: QueryReadType | Type<T>): QueryList<T> {
|
||||||
|
ngDevMode && assertPreviousIsParent();
|
||||||
|
const queryList = new QueryList<T>();
|
||||||
|
const query = currentQuery || (currentQuery = new LQuery_());
|
||||||
|
query.track(queryList, predicate, descend, read);
|
||||||
|
return queryList;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Notice that `query()` takes the `QueryReadType` as enumeration.
|
||||||
|
|
||||||
|
```
|
||||||
|
function readFromNodeInjector(
|
||||||
|
nodeInjector: LInjector, node: LNode, read: QueryReadType | Type<any>): any {
|
||||||
|
if (read === QueryReadType.ElementRef) {
|
||||||
|
return getOrCreateElementRef(nodeInjector);
|
||||||
|
}
|
||||||
|
if (read === QueryReadType.ViewContainerRef) {
|
||||||
|
return getOrCreateContainerRef(nodeInjector);
|
||||||
|
}
|
||||||
|
if (read === QueryReadType.TemplateRef) {
|
||||||
|
return getOrCreateTemplateRef(nodeInjector);
|
||||||
|
}
|
||||||
|
const matchingIdx = geIdxOfMatchingDirective(node, read);
|
||||||
|
if (matchingIdx !== null) {
|
||||||
|
return node.view.data[matchingIdx];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Sometimes later in the above code the `readFromNodeInjector` takes the `QueryReadType` enumeration and performs specific behavior.
|
||||||
|
|
||||||
|
The issue is that once the `query` instruction is pulled in it will pull in `ElementRef`, `ContainerRef`, and `TemplateRef` regardless if the `query` instruction queries for them.
|
||||||
|
|
||||||
|
A better way to do this is to encapsulate the work into an object or function which will then be passed into the `query` instead of the enumeration.
|
||||||
|
|
||||||
|
```
|
||||||
|
function queryElementRefFeature() {...}
|
||||||
|
function queryContainerRefFeature() {...}
|
||||||
|
function queryTemplateRefFeature() {...}
|
||||||
|
|
||||||
|
query(predicate, descend, queryElementRefFeature) {...}
|
||||||
|
```
|
||||||
|
|
||||||
|
this would allow the `readFromNodeInjector` to simply call the `read` function (or object) like so.
|
||||||
|
|
||||||
|
```
|
||||||
|
function readFromNodeInjector(
|
||||||
|
nodeInjector: LInjector, node: LNode, readFn: (injector: Injector) => any) | Type<any>): any {
|
||||||
|
if (isFeature(readFn)) {
|
||||||
|
return readFn(nodeInjector);
|
||||||
|
}
|
||||||
|
const matchingIdx = geIdxOfMatchingDirective(node, readFn);
|
||||||
|
if (matchingIdx !== null) {
|
||||||
|
return node.view.data[matchingIdx];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This approach allows us to preserve the tree-shaking. In essence the if statement has moved from runtime (non-tree-shakable) to compile time (tree-shakable) position.
|
Loading…
x
Reference in New Issue
Block a user