mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
refactor(core): tree-shake HOST_TAG_NAME in prod (#63861)
Previously, HOST_TAG_NAME had its __NG_ELEMENT_ID__ set at the top level. This prevented tree-shaking, since the bundler had to keep the assignment as a potential side effect even when the token was never used. This change moves the token creation and __NG_ELEMENT_ID__ assignment into a @__PURE__ IIFE. If HOST_TAG_NAME is not injected anywhere, the IIFE result is unused and can be dropped entirely by the optimizer. If it is used, the token still behaves the same at runtime. PR Close #63861
This commit is contained in:
parent
36b542d365
commit
dee6ef89c7
8 changed files with 37 additions and 35 deletions
|
|
@ -34,36 +34,45 @@ import {InternalInjectFlags} from './interface/injector';
|
|||
* ```
|
||||
* @publicApi
|
||||
*/
|
||||
export const HOST_TAG_NAME = new InjectionToken<string>(ngDevMode ? 'HOST_TAG_NAME' : '');
|
||||
export const HOST_TAG_NAME: InjectionToken<string> = /* @__PURE__ */ (() => {
|
||||
// Wrapped in a `@__PURE__` IIFE so this token stays tree-shakable.
|
||||
// If nothing ever injects `HOST_TAG_NAME`, the IIFE result is unused and
|
||||
// the bundler can drop the whole block. If we set `__NG_ELEMENT_ID__` at
|
||||
// the top level instead, the mutation would look like a side effect,
|
||||
// forcing the bundler to keep it even when unused.
|
||||
const HOST_TAG_NAME_TOKEN = new InjectionToken<string>(ngDevMode ? 'HOST_TAG_NAME' : '');
|
||||
|
||||
// HOST_TAG_NAME should be resolved at the current node, similar to e.g. ElementRef,
|
||||
// so we manually specify __NG_ELEMENT_ID__ here, instead of using a factory.
|
||||
// tslint:disable-next-line:no-toplevel-property-access
|
||||
(HOST_TAG_NAME as any).__NG_ELEMENT_ID__ = (flags: InternalInjectFlags) => {
|
||||
const tNode = getCurrentTNode();
|
||||
if (tNode === null) {
|
||||
// HOST_TAG_NAME should be resolved at the current node, similar to e.g. ElementRef,
|
||||
// so we manually specify __NG_ELEMENT_ID__ here, instead of using a factory.
|
||||
// tslint:disable-next-line:no-toplevel-property-access
|
||||
(HOST_TAG_NAME_TOKEN as any).__NG_ELEMENT_ID__ = (flags: InternalInjectFlags) => {
|
||||
const tNode = getCurrentTNode();
|
||||
if (tNode === null) {
|
||||
throw new RuntimeError(
|
||||
RuntimeErrorCode.INVALID_INJECTION_TOKEN,
|
||||
ngDevMode &&
|
||||
'HOST_TAG_NAME can only be injected in directives and components ' +
|
||||
'during construction time (in a class constructor or as a class field initializer)',
|
||||
);
|
||||
}
|
||||
if (tNode.type & TNodeType.Element) {
|
||||
return tNode.value;
|
||||
}
|
||||
if (flags & InternalInjectFlags.Optional) {
|
||||
return null;
|
||||
}
|
||||
throw new RuntimeError(
|
||||
RuntimeErrorCode.INVALID_INJECTION_TOKEN,
|
||||
ngDevMode &&
|
||||
'HOST_TAG_NAME can only be injected in directives and components ' +
|
||||
'during construction time (in a class constructor or as a class field initializer)',
|
||||
`HOST_TAG_NAME was used on ${getDevModeNodeName(
|
||||
tNode,
|
||||
)} which doesn't have an underlying element in the DOM. ` +
|
||||
`This is invalid, and so the dependency should be marked as optional.`,
|
||||
);
|
||||
}
|
||||
if (tNode.type & TNodeType.Element) {
|
||||
return tNode.value;
|
||||
}
|
||||
if (flags & InternalInjectFlags.Optional) {
|
||||
return null;
|
||||
}
|
||||
throw new RuntimeError(
|
||||
RuntimeErrorCode.INVALID_INJECTION_TOKEN,
|
||||
ngDevMode &&
|
||||
`HOST_TAG_NAME was used on ${getDevModeNodeName(
|
||||
tNode,
|
||||
)} which doesn't have an underlying element in the DOM. ` +
|
||||
`This is invalid, and so the dependency should be marked as optional.`,
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
return HOST_TAG_NAME_TOKEN;
|
||||
})();
|
||||
|
||||
function getDevModeNodeName(tNode: TNode) {
|
||||
if (tNode.type & TNodeType.ElementContainer) {
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@
|
|||
"HEADER_OFFSET",
|
||||
"HOST",
|
||||
"HOST_ATTR",
|
||||
"HOST_TAG_NAME",
|
||||
"HYDRATION",
|
||||
"ID",
|
||||
"INJECTOR",
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@
|
|||
"shimStylesContent"
|
||||
],
|
||||
"lazy": [
|
||||
"DeferComponent",
|
||||
"_DeferComponent",
|
||||
"AFTER_RENDER_SEQUENCES_TO_ADD",
|
||||
"ANIMATIONS",
|
||||
"APP_BOOTSTRAP_LISTENER",
|
||||
|
|
@ -141,7 +143,6 @@
|
|||
"FLAGS",
|
||||
"HEADER_OFFSET",
|
||||
"HOST",
|
||||
"HOST_TAG_NAME",
|
||||
"HYDRATE_TRIGGER_CLEANUP_FNS",
|
||||
"HYDRATION",
|
||||
"ID",
|
||||
|
|
@ -792,9 +793,7 @@
|
|||
"wasLastNodeCreated",
|
||||
"writeDirectClass",
|
||||
"writeDirectStyle",
|
||||
"writeToDirectiveInput",
|
||||
"DeferComponent",
|
||||
"_DeferComponent"
|
||||
"writeToDirectiveInput"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -120,7 +120,6 @@
|
|||
"HEADER_OFFSET",
|
||||
"HOST",
|
||||
"HOST_ATTR",
|
||||
"HOST_TAG_NAME",
|
||||
"HYDRATION",
|
||||
"ID",
|
||||
"INJECTOR",
|
||||
|
|
|
|||
|
|
@ -114,7 +114,6 @@
|
|||
"HEADER_OFFSET",
|
||||
"HOST",
|
||||
"HOST_ATTR",
|
||||
"HOST_TAG_NAME",
|
||||
"HYDRATION",
|
||||
"ID",
|
||||
"INJECTOR",
|
||||
|
|
|
|||
|
|
@ -93,7 +93,6 @@
|
|||
"HEADER_OFFSET",
|
||||
"HOST",
|
||||
"HOST_ATTR",
|
||||
"HOST_TAG_NAME",
|
||||
"HTTP_ROOT_INTERCEPTOR_FNS",
|
||||
"HTTP_TRANSFER_CACHE_ORIGIN_MAP",
|
||||
"HYDRATION",
|
||||
|
|
|
|||
|
|
@ -113,7 +113,6 @@
|
|||
"HEADER_OFFSET",
|
||||
"HOST",
|
||||
"HOST_ATTR",
|
||||
"HOST_TAG_NAME",
|
||||
"HYDRATION",
|
||||
"HistoryStateManager",
|
||||
"HostAttributeToken",
|
||||
|
|
|
|||
|
|
@ -80,7 +80,6 @@
|
|||
"HEADER_OFFSET",
|
||||
"HOST",
|
||||
"HOST_ATTR",
|
||||
"HOST_TAG_NAME",
|
||||
"HYDRATION",
|
||||
"HelloWorld",
|
||||
"ID",
|
||||
|
|
|
|||
Loading…
Reference in a new issue