diff --git a/packages/core/src/core_private_export.ts b/packages/core/src/core_private_export.ts index 9ef6d446bb7269..0734acee89d8b1 100644 --- a/packages/core/src/core_private_export.ts +++ b/packages/core/src/core_private_export.ts @@ -107,6 +107,7 @@ export { PendingTasksInternal as ɵPendingTasks, // TODO(atscott): remove once there is a release with PendingTasksInternal so adev can be updated PendingTasksInternal as ɵPendingTasksInternal, } from './pending_tasks'; +export {DISABLE_COMPONENT_BOOTSTRAP as ɵDISABLE_COMPONENT_BOOTSTRAP} from './platform/bootstrap'; export {ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS} from './platform/platform'; export {ReflectionCapabilities as ɵReflectionCapabilities} from './reflection/reflection_capabilities'; export {AnimationRendererType as ɵAnimationRendererType} from './render/api'; diff --git a/packages/core/src/platform/bootstrap.ts b/packages/core/src/platform/bootstrap.ts index c9d802754770d6..1041f596970d2e 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,29 @@ 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 used to disable the bootstrap of components. + * + * This token is used by the Angular CLI in the `@angular/ssr` package to control + * whether components should be bootstrapped during the application initialization process. + * Specifically, it is used during route extraction when server-side rendering is enabled. + * + * By setting this token to `true`, Angular prevents the root component from being bootstrapped + * and avoids invoking it during the route extraction phase, which is necessary for SSR + * to extract routes without requiring new APIs to be exposed. This mechanism helps separate + * the logic for route extraction and component bootstrapping during SSR rendering. + * + * When not provided or set to `false`, Angular will continue with the default behavior + * of bootstrapping the root component(s) during initialization. + */ +export const DISABLE_COMPONENT_BOOTSTRAP = new InjectionToken( + ngDevMode ? 'DISABLE_ROOT_COMPONENT_BOOTSTRAP' : '', +); + export interface BootstrapConfig { platformInjector: Injector; } @@ -125,6 +144,19 @@ 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 disableComponentsBootstrap = envInjector.get(DISABLE_COMPONENT_BOOTSTRAP, false, { + optional: true, + }); + if (disableComponentsBootstrap) { + 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 f64ab6e4d4f093..4cf96ddda37082 100644 --- a/packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json +++ b/packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json @@ -149,6 +149,9 @@ { "name": "DIMENSIONAL_PROP_SET" }, + { + "name": "DISABLE_COMPONENT_BOOTSTRAP" + }, { "name": "DOCUMENT" }, diff --git a/packages/core/test/bundling/animations/bundle.golden_symbols.json b/packages/core/test/bundling/animations/bundle.golden_symbols.json index 9e1fee21f58492..686dc8077fa99b 100644 --- a/packages/core/test/bundling/animations/bundle.golden_symbols.json +++ b/packages/core/test/bundling/animations/bundle.golden_symbols.json @@ -173,6 +173,9 @@ { "name": "DIMENSIONAL_PROP_SET" }, + { + "name": "DISABLE_COMPONENT_BOOTSTRAP" + }, { "name": "DOCUMENT" }, 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 bee79d36895a1c..f62a18b4ac3647 100644 --- a/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json +++ b/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json @@ -95,6 +95,9 @@ { "name": "DEFAULT_APP_ID" }, + { + "name": "DISABLE_COMPONENT_BOOTSTRAP" + }, { "name": "DOCUMENT" }, diff --git a/packages/core/test/bundling/defer/bundle.golden_symbols.json b/packages/core/test/bundling/defer/bundle.golden_symbols.json index 8d0ad0bffdc276..55fa31e23454d7 100644 --- a/packages/core/test/bundling/defer/bundle.golden_symbols.json +++ b/packages/core/test/bundling/defer/bundle.golden_symbols.json @@ -128,6 +128,9 @@ { "name": "DEHYDRATED_VIEWS" }, + { + "name": "DISABLE_COMPONENT_BOOTSTRAP" + }, { "name": "DI_DECORATOR_FLAG" }, 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 0f4181a8a92dc9..767c5cf5f165d7 100644 --- a/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json +++ b/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json @@ -140,6 +140,9 @@ { "name": "DEFAULT_VALUE_ACCESSOR" }, + { + "name": "DISABLE_COMPONENT_BOOTSTRAP" + }, { "name": "DOCUMENT" }, 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 090ce6805ab244..da35ecbe32a4db 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 @@ -146,6 +146,9 @@ { "name": "DEFAULT_VALUE_ACCESSOR" }, + { + "name": "DISABLE_COMPONENT_BOOTSTRAP" + }, { "name": "DOCUMENT" }, 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 e7957fed712e64..05a78f06352386 100644 --- a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json @@ -62,6 +62,9 @@ { "name": "ConsumerObserver" }, + { + "name": "DISABLE_COMPONENT_BOOTSTRAP" + }, { "name": "DOCUMENT2" }, diff --git a/packages/core/test/bundling/hydration/bundle.golden_symbols.json b/packages/core/test/bundling/hydration/bundle.golden_symbols.json index a87abb1d3dd513..7ed7140af8a65e 100644 --- a/packages/core/test/bundling/hydration/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hydration/bundle.golden_symbols.json @@ -89,6 +89,9 @@ { "name": "DEFAULT_APP_ID" }, + { + "name": "DISABLE_COMPONENT_BOOTSTRAP" + }, { "name": "DOCUMENT" }, diff --git a/packages/core/test/bundling/router/bundle.golden_symbols.json b/packages/core/test/bundling/router/bundle.golden_symbols.json index 726dd0c3db0812..72799f75510a3e 100644 --- a/packages/core/test/bundling/router/bundle.golden_symbols.json +++ b/packages/core/test/bundling/router/bundle.golden_symbols.json @@ -149,6 +149,9 @@ { "name": "DEFAULT_SERIALIZER" }, + { + "name": "DISABLE_COMPONENT_BOOTSTRAP" + }, { "name": "DOCUMENT" }, 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 d454dd92ce75a2..e90290ac0e6bea 100644 --- a/packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json +++ b/packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json @@ -80,6 +80,9 @@ { "name": "DEFAULT_APP_ID" }, + { + "name": "DISABLE_COMPONENT_BOOTSTRAP" + }, { "name": "DOCUMENT" }, diff --git a/packages/core/test/bundling/todo/bundle.golden_symbols.json b/packages/core/test/bundling/todo/bundle.golden_symbols.json index dd37518a768668..eab7e89fed0332 100644 --- a/packages/core/test/bundling/todo/bundle.golden_symbols.json +++ b/packages/core/test/bundling/todo/bundle.golden_symbols.json @@ -95,6 +95,9 @@ { "name": "DEFAULT_APP_ID" }, + { + "name": "DISABLE_COMPONENT_BOOTSTRAP" + }, { "name": "DOCUMENT" },