feat(ivy): emit module scope metadata using pure function call (#29598)
Prior to this change, all module metadata would be included in the `defineNgModule` call that is set as the `ngModuleDef` field of module types. Part of the metadata is scope information like declarations, imports and exports that is used for computing the transitive module scope in JIT environments, preventing those references from being tree-shaken for production builds. This change moves the metadata for scope computations to a pure function call that patches the scope references onto the module type. Because the function is marked pure, it may be tree-shaken out during production builds such that references to declarations and exports are dropped, which in turn allows for tree-shaken any declaration that is not otherwise referenced. Fixes #28077, FW-1035 PR Close #29598
This commit is contained in:
@ -26,6 +26,7 @@ export {
|
||||
getFactoryOf as ɵgetFactoryOf,
|
||||
getInheritedFactory as ɵgetInheritedFactory,
|
||||
setComponentScope as ɵsetComponentScope,
|
||||
setNgModuleScope as ɵsetNgModuleScope,
|
||||
templateRefExtractor as ɵtemplateRefExtractor,
|
||||
ProvidersFeature as ɵProvidersFeature,
|
||||
InheritDefinitionFeature as ɵInheritDefinitionFeature,
|
||||
|
@ -327,7 +327,28 @@ export function extractPipeDef(type: PipeType<any>): PipeDef<any> {
|
||||
return def !;
|
||||
}
|
||||
|
||||
export function defineNgModule<T>(def: {type: T} & Partial<NgModuleDef<T>>): never {
|
||||
export function defineNgModule<T>(def: {
|
||||
/** Token representing the module. Used by DI. */
|
||||
type: T;
|
||||
|
||||
/** List of components to bootstrap. */
|
||||
bootstrap?: Type<any>[] | (() => Type<any>[]);
|
||||
|
||||
/** List of components, directives, and pipes declared by this module. */
|
||||
declarations?: Type<any>[] | (() => Type<any>[]);
|
||||
|
||||
/** List of modules or `ModuleWithProviders` imported by this module. */
|
||||
imports?: Type<any>[] | (() => Type<any>[]);
|
||||
|
||||
/**
|
||||
* List of modules, `ModuleWithProviders`, components, directives, or pipes exported by this
|
||||
* module.
|
||||
*/
|
||||
exports?: Type<any>[] | (() => Type<any>[]);
|
||||
|
||||
/** The set of schemas that declare elements to be allowed in the NgModule. */
|
||||
schemas?: SchemaMetadata[] | null;
|
||||
}): never {
|
||||
const res: NgModuleDef<T> = {
|
||||
type: def.type,
|
||||
bootstrap: def.bootstrap || EMPTY_ARRAY,
|
||||
@ -340,6 +361,33 @@ export function defineNgModule<T>(def: {type: T} & Partial<NgModuleDef<T>>): nev
|
||||
return res as never;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the module metadata that is necessary to compute the module's transitive scope to an
|
||||
* existing module definition.
|
||||
*
|
||||
* Scope metadata of modules is not used in production builds, so calls to this function can be
|
||||
* marked pure to tree-shake it from the bundle, allowing for all referenced declarations
|
||||
* to become eligible for tree-shaking as well.
|
||||
*/
|
||||
export function setNgModuleScope(type: any, scope: {
|
||||
/** List of components, directives, and pipes declared by this module. */
|
||||
declarations?: Type<any>[] | (() => Type<any>[]);
|
||||
|
||||
/** List of modules or `ModuleWithProviders` imported by this module. */
|
||||
imports?: Type<any>[] | (() => Type<any>[]);
|
||||
|
||||
/**
|
||||
* List of modules, `ModuleWithProviders`, components, directives, or pipes exported by this
|
||||
* module.
|
||||
*/
|
||||
exports?: Type<any>[] | (() => Type<any>[]);
|
||||
}): void {
|
||||
const ngModuleDef = getNgModuleDef(type, true);
|
||||
ngModuleDef.declarations = scope.declarations || EMPTY_ARRAY;
|
||||
ngModuleDef.imports = scope.imports || EMPTY_ARRAY;
|
||||
ngModuleDef.exports = scope.exports || EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverts an inputs or outputs lookup such that the keys, which were the
|
||||
* minified keys, are part of the values, and the values are parsed so that
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {LifecycleHooksFeature, renderComponent, whenRendered} from './component';
|
||||
import {defineBase, defineComponent, defineDirective, defineNgModule, definePipe, setComponentScope} from './definition';
|
||||
import {defineBase, defineComponent, defineDirective, defineNgModule, definePipe, setComponentScope, setNgModuleScope} from './definition';
|
||||
import {InheritDefinitionFeature} from './features/inherit_definition_feature';
|
||||
import {NgOnChangesFeature} from './features/ng_onchanges_feature';
|
||||
import {ProvidersFeature} from './features/providers_feature';
|
||||
@ -186,6 +186,7 @@ export {
|
||||
getRenderedText,
|
||||
renderComponent,
|
||||
setComponentScope,
|
||||
setNgModuleScope,
|
||||
whenRendered,
|
||||
};
|
||||
|
||||
|
@ -121,6 +121,7 @@ export const angularCoreEnv: {[name: string]: Function} = {
|
||||
'ɵresolveDocument': r3.resolveDocument,
|
||||
'ɵresolveBody': r3.resolveBody,
|
||||
'ɵsetComponentScope': r3.setComponentScope,
|
||||
'ɵsetNgModuleScope': r3.setNgModuleScope,
|
||||
|
||||
'ɵsanitizeHtml': sanitization.sanitizeHtml,
|
||||
'ɵsanitizeStyle': sanitization.sanitizeStyle,
|
||||
|
Reference in New Issue
Block a user