Skip to content

Commit 9e0b50b

Browse files
alan-agius4AndrewKushnir
authored andcommitted
refactor(core): add ENABLE_ROOT_COMPONENT_BOOTSTRAP token (angular#59133)
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: angular/angular-cli#29085 PR Close angular#59133
1 parent 57f3550 commit 9e0b50b

File tree

13 files changed

+49
-2
lines changed

13 files changed

+49
-2
lines changed

packages/core/src/core_private_export.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ export {
105105
} from './metadata/resource_loading';
106106
export {PendingTasksInternal as ɵPendingTasksInternal} from './pending_tasks';
107107
export {ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS} from './platform/platform';
108+
export {ENABLE_ROOT_COMPONENT_BOOTSTRAP as ɵENABLE_ROOT_COMPONENT_BOOTSTRAP} from './platform/bootstrap';
108109
export {ReflectionCapabilities as ɵReflectionCapabilities} from './reflection/reflection_capabilities';
109110
export {AnimationRendererType as ɵAnimationRendererType} from './render/api';
110111
export {

packages/core/src/platform/bootstrap.ts

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import {Subscription} from 'rxjs';
99

1010
import {PROVIDED_NG_ZONE} from '../change_detection/scheduling/ng_zone_scheduling';
11-
import {EnvironmentInjector, R3Injector} from '../di/r3_injector';
11+
import {R3Injector} from '../di/r3_injector';
1212
import {ErrorHandler} from '../error_handler';
1313
import {RuntimeError, RuntimeErrorCode} from '../errors';
1414
import {DEFAULT_LOCALE_ID} from '../i18n/localization';
@@ -22,10 +22,34 @@ import {NgZone} from '../zone/ng_zone';
2222
import {ApplicationInitStatus} from '../application/application_init';
2323
import {_callAndReportToErrorHandler, ApplicationRef, remove} from '../application/application_ref';
2424
import {PROVIDED_ZONELESS} from '../change_detection/scheduling/zoneless_scheduling';
25-
import {Injector} from '../di';
25+
import {InjectionToken, Injector} from '../di';
2626
import {InternalNgModuleRef, NgModuleRef} from '../linker/ng_module_factory';
2727
import {stringify} from '../util/stringify';
2828

29+
/**
30+
* InjectionToken to control root component bootstrap behavior.
31+
*
32+
* This token is primarily used in Angular's server-side rendering (SSR) scenarios,
33+
* particularly by the `@angular/ssr` package, to manage whether the root component
34+
* should be bootstrapped during the application initialization process.
35+
*
36+
* ## Purpose:
37+
* During SSR route extraction, setting this token to `false` prevents Angular from
38+
* bootstrapping the root component. This avoids unnecessary component rendering,
39+
* enabling route extraction without requiring additional APIs or triggering
40+
* component logic.
41+
*
42+
* ## Behavior:
43+
* - **`false`**: Prevents the root component from being bootstrapped.
44+
* - **`true`** (default): Proceeds with the normal root component bootstrap process.
45+
*
46+
* This mechanism ensures SSR can efficiently separate route extraction logic
47+
* from component rendering.
48+
*/
49+
export const ENABLE_ROOT_COMPONENT_BOOTSTRAP = new InjectionToken<boolean>(
50+
ngDevMode ? 'ENABLE_ROOT_COMPONENT_BOOTSTRAP' : '',
51+
);
52+
2953
export interface BootstrapConfig {
3054
platformInjector: Injector;
3155
}
@@ -125,6 +149,17 @@ export function bootstrap<M>(
125149
// If the `LOCALE_ID` provider is defined at bootstrap then we set the value for ivy
126150
const localeId = envInjector.get(LOCALE_ID, DEFAULT_LOCALE_ID);
127151
setLocaleId(localeId || DEFAULT_LOCALE_ID);
152+
153+
const enableRootComponentBoostrap = envInjector.get(ENABLE_ROOT_COMPONENT_BOOTSTRAP, true);
154+
if (!enableRootComponentBoostrap) {
155+
if (isApplicationBootstrapConfig(config)) {
156+
return envInjector.get(ApplicationRef);
157+
}
158+
159+
config.allPlatformModules.push(config.moduleRef);
160+
return config.moduleRef;
161+
}
162+
128163
if (typeof ngDevMode === 'undefined' || ngDevMode) {
129164
const imagePerformanceService = envInjector.get(ImagePerformanceWarning);
130165
imagePerformanceService.start();

packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"EMPTY_PAYLOAD",
6565
"EMPTY_PLAYER_ARRAY",
6666
"EMPTY_SUBSCRIPTION",
67+
"ENABLE_ROOT_COMPONENT_BOOTSTRAP",
6768
"ENTER_TOKEN_REGEX",
6869
"ENVIRONMENT_INITIALIZER",
6970
"EVENT_MANAGER_PLUGINS",

packages/core/test/bundling/animations/bundle.golden_symbols.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
"EMPTY_PAYLOAD",
7373
"EMPTY_PLAYER_ARRAY",
7474
"EMPTY_SUBSCRIPTION",
75+
"ENABLE_ROOT_COMPONENT_BOOTSTRAP",
7576
"ENTER_TOKEN_REGEX",
7677
"ENVIRONMENT_INITIALIZER",
7778
"EVENT_MANAGER_PLUGINS",

packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"EMPTY_OBSERVER",
4545
"EMPTY_PAYLOAD",
4646
"EMPTY_SUBSCRIPTION",
47+
"ENABLE_ROOT_COMPONENT_BOOTSTRAP",
4748
"ENVIRONMENT_INITIALIZER",
4849
"EVENT_MANAGER_PLUGINS",
4950
"EffectScheduler",

packages/core/test/bundling/defer/bundle.golden_symbols.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"EMPTY_OBSERVER",
6161
"EMPTY_PAYLOAD",
6262
"EMPTY_SUBSCRIPTION",
63+
"ENABLE_ROOT_COMPONENT_BOOTSTRAP",
6364
"ENVIRONMENT_INITIALIZER",
6465
"EVENT_MANAGER_PLUGINS",
6566
"EffectScheduler",

packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
"EMPTY_OBSERVER",
6363
"EMPTY_PAYLOAD",
6464
"EMPTY_SUBSCRIPTION",
65+
"ENABLE_ROOT_COMPONENT_BOOTSTRAP",
6566
"ENVIRONMENT_INITIALIZER",
6667
"ERRORED",
6768
"EVENT_MANAGER_PLUGINS",

packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
"EMPTY_OBSERVER",
6464
"EMPTY_PAYLOAD",
6565
"EMPTY_SUBSCRIPTION",
66+
"ENABLE_ROOT_COMPONENT_BOOTSTRAP",
6667
"ENVIRONMENT_INITIALIZER",
6768
"ERRORED",
6869
"EVENT_MANAGER_PLUGINS",

packages/core/test/bundling/hello_world/bundle.golden_symbols.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"EMPTY_OBSERVER",
2929
"EMPTY_PAYLOAD",
3030
"EMPTY_SUBSCRIPTION",
31+
"ENABLE_ROOT_COMPONENT_BOOTSTRAP",
3132
"ENVIRONMENT_INITIALIZER",
3233
"EffectScheduler",
3334
"ElementRef",

packages/core/test/bundling/hydration/bundle.golden_symbols.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"EMPTY_OBSERVER",
4242
"EMPTY_PAYLOAD",
4343
"EMPTY_SUBSCRIPTION",
44+
"ENABLE_ROOT_COMPONENT_BOOTSTRAP",
4445
"ENVIRONMENT_INITIALIZER",
4546
"EVENT_MANAGER_PLUGINS",
4647
"EffectScheduler",

0 commit comments

Comments
 (0)