From ba9bbd07bfb68fca745cd70d426bb972e139b488 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Mon, 16 Dec 2024 15:05:18 +0000 Subject: [PATCH] refactor(core): add `ENABLE_ROOT_COMPONENT_BOOTSTRAP` token (#59205) Introduced the `ENABLE_ROOT_COMPONENT_BOOTSTRAP` token to control the bootstrapping of components during application initialization. This token is utilized by the Angular CLI in the `@angular/ssr` package, particularly during server-side rendering (SSR) when extracting routes. When set to `false`, this token prevents the root component from being bootstrapped during SSR's route extraction phase, which is crucial for efficiently extracting routes without triggering component initialization. This mechanism separates the concerns of route extraction and component bootstrapping during SSR rendering, optimizing performance. If not provided or set to `true`, the default behavior of bootstrapping the root component(s) during initialization is maintained. Context: https://github.com/angular/angular-cli/issues/29085 PR Close #59205 --- packages/core/src/core_private_export.ts | 1 + packages/core/src/platform/bootstrap.ts | 39 ++++++++++++++++++- .../bundle.golden_symbols.json | 3 ++ .../animations/bundle.golden_symbols.json | 3 ++ .../cyclic_import/bundle.golden_symbols.json | 3 ++ .../bundling/defer/bundle.golden_symbols.json | 3 ++ .../forms_reactive/bundle.golden_symbols.json | 3 ++ .../bundle.golden_symbols.json | 3 ++ .../hello_world/bundle.golden_symbols.json | 3 ++ .../hydration/bundle.golden_symbols.json | 3 ++ .../router/bundle.golden_symbols.json | 3 ++ .../bundle.golden_symbols.json | 3 ++ .../bundling/todo/bundle.golden_symbols.json | 3 ++ 13 files changed, 71 insertions(+), 2 deletions(-) diff --git a/packages/core/src/core_private_export.ts b/packages/core/src/core_private_export.ts index 76e14ab5c3a..ed2f1869c03 100644 --- a/packages/core/src/core_private_export.ts +++ b/packages/core/src/core_private_export.ts @@ -105,6 +105,7 @@ export { } from './metadata/resource_loading'; export {PendingTasksInternal as ɵPendingTasksInternal} from './pending_tasks'; export {ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS} from './platform/platform'; +export {ENABLE_ROOT_COMPONENT_BOOTSTRAP as ɵENABLE_ROOT_COMPONENT_BOOTSTRAP} from './platform/bootstrap'; export {ReflectionCapabilities as ɵReflectionCapabilities} from './reflection/reflection_capabilities'; export {AnimationRendererType as ɵAnimationRendererType} from './render/api'; export { diff --git a/packages/core/src/platform/bootstrap.ts b/packages/core/src/platform/bootstrap.ts index c9d80275477..3fdce7155df 100644 --- a/packages/core/src/platform/bootstrap.ts +++ b/packages/core/src/platform/bootstrap.ts @@ -8,7 +8,7 @@ import {Subscription} from 'rxjs'; import {PROVIDED_NG_ZONE} from '../change_detection/scheduling/ng_zone_scheduling'; -import {EnvironmentInjector, R3Injector} from '../di/r3_injector'; +import {R3Injector} from '../di/r3_injector'; import {ErrorHandler} from '../error_handler'; import {RuntimeError, RuntimeErrorCode} from '../errors'; import {DEFAULT_LOCALE_ID} from '../i18n/localization'; @@ -22,10 +22,34 @@ import {NgZone} from '../zone/ng_zone'; import {ApplicationInitStatus} from '../application/application_init'; import {_callAndReportToErrorHandler, ApplicationRef, remove} from '../application/application_ref'; import {PROVIDED_ZONELESS} from '../change_detection/scheduling/zoneless_scheduling'; -import {Injector} from '../di'; +import {InjectionToken, Injector} from '../di'; import {InternalNgModuleRef, NgModuleRef} from '../linker/ng_module_factory'; import {stringify} from '../util/stringify'; +/** + * InjectionToken to control root component bootstrap behavior. + * + * This token is primarily used in Angular's server-side rendering (SSR) scenarios, + * particularly by the `@angular/ssr` package, to manage whether the root component + * should be bootstrapped during the application initialization process. + * + * ## Purpose: + * During SSR route extraction, setting this token to `false` prevents Angular from + * bootstrapping the root component. This avoids unnecessary component rendering, + * enabling route extraction without requiring additional APIs or triggering + * component logic. + * + * ## Behavior: + * - **`false`**: Prevents the root component from being bootstrapped. + * - **`true`** (default): Proceeds with the normal root component bootstrap process. + * + * This mechanism ensures SSR can efficiently separate route extraction logic + * from component rendering. + */ +export const ENABLE_ROOT_COMPONENT_BOOTSTRAP = new InjectionToken( + ngDevMode ? 'ENABLE_ROOT_COMPONENT_BOOTSTRAP' : '', +); + export interface BootstrapConfig { platformInjector: Injector; } @@ -125,6 +149,17 @@ export function bootstrap( // If the `LOCALE_ID` provider is defined at bootstrap then we set the value for ivy const localeId = envInjector.get(LOCALE_ID, DEFAULT_LOCALE_ID); setLocaleId(localeId || DEFAULT_LOCALE_ID); + + const enableRootComponentBoostrap = envInjector.get(ENABLE_ROOT_COMPONENT_BOOTSTRAP, true); + if (!enableRootComponentBoostrap) { + if (isApplicationBootstrapConfig(config)) { + return envInjector.get(ApplicationRef); + } + + config.allPlatformModules.push(config.moduleRef); + return config.moduleRef; + } + if (typeof ngDevMode === 'undefined' || ngDevMode) { const imagePerformanceService = envInjector.get(ImagePerformanceWarning); imagePerformanceService.start(); diff --git a/packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json b/packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json index f64ab6e4d4f..a8716ce50b8 100644 --- a/packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json +++ b/packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json @@ -191,6 +191,9 @@ { "name": "EMPTY_SUBSCRIPTION" }, + { + "name": "ENABLE_ROOT_COMPONENT_BOOTSTRAP" + }, { "name": "ENTER_TOKEN_REGEX" }, diff --git a/packages/core/test/bundling/animations/bundle.golden_symbols.json b/packages/core/test/bundling/animations/bundle.golden_symbols.json index 9e1fee21f58..11aff6ade55 100644 --- a/packages/core/test/bundling/animations/bundle.golden_symbols.json +++ b/packages/core/test/bundling/animations/bundle.golden_symbols.json @@ -218,6 +218,9 @@ { "name": "EMPTY_SUBSCRIPTION" }, + { + "name": "ENABLE_ROOT_COMPONENT_BOOTSTRAP" + }, { "name": "ENTER_TOKEN_REGEX" }, diff --git a/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json b/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json index bee79d36895..36acd8ea667 100644 --- a/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json +++ b/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json @@ -134,6 +134,9 @@ { "name": "EMPTY_SUBSCRIPTION" }, + { + "name": "ENABLE_ROOT_COMPONENT_BOOTSTRAP" + }, { "name": "ENVIRONMENT_INITIALIZER" }, diff --git a/packages/core/test/bundling/defer/bundle.golden_symbols.json b/packages/core/test/bundling/defer/bundle.golden_symbols.json index 921050b67c3..2daaa765882 100644 --- a/packages/core/test/bundling/defer/bundle.golden_symbols.json +++ b/packages/core/test/bundling/defer/bundle.golden_symbols.json @@ -182,6 +182,9 @@ { "name": "EMPTY_SUBSCRIPTION" }, + { + "name": "ENABLE_ROOT_COMPONENT_BOOTSTRAP" + }, { "name": "ENVIRONMENT_INITIALIZER" }, diff --git a/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json b/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json index 0f4181a8a92..69441fd5f94 100644 --- a/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json +++ b/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json @@ -188,6 +188,9 @@ { "name": "EMPTY_SUBSCRIPTION" }, + { + "name": "ENABLE_ROOT_COMPONENT_BOOTSTRAP" + }, { "name": "ENVIRONMENT_INITIALIZER" }, diff --git a/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json b/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json index 090ce6805ab..0ce6f1be273 100644 --- a/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json +++ b/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json @@ -191,6 +191,9 @@ { "name": "EMPTY_SUBSCRIPTION" }, + { + "name": "ENABLE_ROOT_COMPONENT_BOOTSTRAP" + }, { "name": "ENVIRONMENT_INITIALIZER" }, diff --git a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json index e7957fed712..82f502394d5 100644 --- a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json @@ -86,6 +86,9 @@ { "name": "EMPTY_SUBSCRIPTION" }, + { + "name": "ENABLE_ROOT_COMPONENT_BOOTSTRAP" + }, { "name": "ENVIRONMENT_INITIALIZER" }, diff --git a/packages/core/test/bundling/hydration/bundle.golden_symbols.json b/packages/core/test/bundling/hydration/bundle.golden_symbols.json index a87abb1d3dd..6b5403c5e22 100644 --- a/packages/core/test/bundling/hydration/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hydration/bundle.golden_symbols.json @@ -122,6 +122,9 @@ { "name": "EMPTY_SUBSCRIPTION" }, + { + "name": "ENABLE_ROOT_COMPONENT_BOOTSTRAP" + }, { "name": "ENVIRONMENT_INITIALIZER" }, diff --git a/packages/core/test/bundling/router/bundle.golden_symbols.json b/packages/core/test/bundling/router/bundle.golden_symbols.json index 726dd0c3db0..afef52d0eb9 100644 --- a/packages/core/test/bundling/router/bundle.golden_symbols.json +++ b/packages/core/test/bundling/router/bundle.golden_symbols.json @@ -197,6 +197,9 @@ { "name": "EMPTY_SUBSCRIPTION" }, + { + "name": "ENABLE_ROOT_COMPONENT_BOOTSTRAP" + }, { "name": "ENVIRONMENT_INITIALIZER" }, diff --git a/packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json b/packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json index d454dd92ce7..4ff733e7bc3 100644 --- a/packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json +++ b/packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json @@ -113,6 +113,9 @@ { "name": "EMPTY_SUBSCRIPTION" }, + { + "name": "ENABLE_ROOT_COMPONENT_BOOTSTRAP" + }, { "name": "ENVIRONMENT_INITIALIZER" }, diff --git a/packages/core/test/bundling/todo/bundle.golden_symbols.json b/packages/core/test/bundling/todo/bundle.golden_symbols.json index dd37518a768..9f9e72a5ece 100644 --- a/packages/core/test/bundling/todo/bundle.golden_symbols.json +++ b/packages/core/test/bundling/todo/bundle.golden_symbols.json @@ -137,6 +137,9 @@ { "name": "EMPTY_SUBSCRIPTION" }, + { + "name": "ENABLE_ROOT_COMPONENT_BOOTSTRAP" + }, { "name": "ENVIRONMENT_INITIALIZER" },