Skip to content

Commit 59c7577

Browse files
committed
fix(@angular/ssr): unblock route extraction with withEnabledBlockingInitialNavigation
This fix ensures that route extraction is not blocked when `withEnabledBlockingInitialNavigation` is used. Closes #29400 (cherry picked from commit 4a1833d)
1 parent bcc5fab commit 59c7577

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

packages/angular/ssr/src/routes/ng-routes.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -523,11 +523,17 @@ export async function getRoutesFromAngularRouterConfig(
523523
applicationRef = await bootstrap();
524524
}
525525

526+
const injector = applicationRef.injector;
527+
const router = injector.get(Router);
528+
529+
// Workaround to unblock navigation when `withEnabledBlockingInitialNavigation()` is used.
530+
// This is necessary because route extraction disables component bootstrapping.
531+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
532+
(router as any).navigationTransitions.afterPreactivation()?.next?.();
533+
526534
// Wait until the application is stable.
527535
await applicationRef.whenStable();
528536

529-
const injector = applicationRef.injector;
530-
const router = injector.get(Router);
531537
const routesResults: RouteTreeNodeMetadata[] = [];
532538
const errors: string[] = [];
533539

packages/angular/ssr/test/routes/ng-routes_spec.ts

+33
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import '@angular/compiler';
1212
/* eslint-enable import/no-unassigned-import */
1313

1414
import { Component } from '@angular/core';
15+
import { Routes, provideRouter, withEnabledBlockingInitialNavigation } from '@angular/router';
1516
import { extractRoutesAndCreateRouteTree } from '../../src/routes/ng-routes';
1617
import { PrerenderFallback, RenderMode } from '../../src/routes/route-config';
1718
import { setAngularAppTestingManifest } from '../testing-utils';
@@ -495,4 +496,36 @@ describe('extractRoutesAndCreateRouteTree', () => {
495496
expect(errors).toHaveSize(0);
496497
expect(routeTree.toObject()).toHaveSize(2);
497498
});
499+
500+
it('should not bootstrap the root component when using `withEnabledBlockingInitialNavigation`', async () => {
501+
@Component({
502+
standalone: true,
503+
selector: 'app-root',
504+
template: '',
505+
})
506+
class RootComponent {
507+
constructor() {
508+
throw new Error('RootComponent should not be bootstrapped.');
509+
}
510+
}
511+
512+
const routes: Routes = [
513+
{ path: '', component: DummyComponent },
514+
{ path: 'home', component: DummyComponent },
515+
];
516+
517+
setAngularAppTestingManifest(
518+
routes,
519+
[{ path: '**', renderMode: RenderMode.Server }],
520+
undefined,
521+
undefined,
522+
undefined,
523+
RootComponent,
524+
[provideRouter(routes, withEnabledBlockingInitialNavigation())],
525+
);
526+
527+
const { routeTree, errors } = await extractRoutesAndCreateRouteTree({ url });
528+
expect(errors).toHaveSize(0);
529+
expect(routeTree.toObject()).toHaveSize(2);
530+
});
498531
});

packages/angular/ssr/test/testing-utils.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import { Component, Type, provideExperimentalZonelessChangeDetection } from '@angular/core';
9+
import {
10+
Component,
11+
EnvironmentProviders,
12+
Provider,
13+
Type,
14+
provideExperimentalZonelessChangeDetection,
15+
} from '@angular/core';
1016
import { bootstrapApplication } from '@angular/platform-browser';
1117
import { provideServerRendering } from '@angular/platform-server';
1218
import { RouterOutlet, Routes, provideRouter } from '@angular/router';
@@ -35,6 +41,8 @@ class AppComponent {}
3541
* where the keys are asset paths and the values are asset details.
3642
* @param locale - An optional locale to configure for the application during testing.
3743
* @param rootComponent - The root Angular component to bootstrap the application.
44+
* @param extraProviders - An optional array of additional providers that should be available to the
45+
* root component and all its children.
3846
*/
3947
export function setAngularAppTestingManifest(
4048
routes: Routes,
@@ -43,6 +51,7 @@ export function setAngularAppTestingManifest(
4351
additionalServerAssets: Record<string, ServerAsset> = {},
4452
locale?: string,
4553
rootComponent: Type<unknown> = AppComponent,
54+
extraProviders: Array<Provider | EnvironmentProviders> = [],
4655
): void {
4756
destroyAngularServerApp();
4857

@@ -89,6 +98,7 @@ export function setAngularAppTestingManifest(
8998
provideExperimentalZonelessChangeDetection(),
9099
provideRouter(routes),
91100
provideServerRoutesConfig(serverRoutes),
101+
...extraProviders,
92102
],
93103
});
94104
},

0 commit comments

Comments
 (0)