Skip to content

Commit

Permalink
fix(@angular/ssr): unblock route extraction with `withEnabledBlocking…
Browse files Browse the repository at this point in the history
…InitialNavigation`

This fix ensures that route extraction is not blocked when `withEnabledBlockingInitialNavigation` is used.

Closes #29400
  • Loading branch information
alan-agius4 committed Jan 20, 2025
1 parent a0efac8 commit 4a1833d
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 3 deletions.
10 changes: 8 additions & 2 deletions packages/angular/ssr/src/routes/ng-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -523,11 +523,17 @@ export async function getRoutesFromAngularRouterConfig(
applicationRef = await bootstrap();
}

const injector = applicationRef.injector;
const router = injector.get(Router);

// Workaround to unblock navigation when `withEnabledBlockingInitialNavigation()` is used.
// This is necessary because route extraction disables component bootstrapping.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(router as any).navigationTransitions.afterPreactivation()?.next?.();

// Wait until the application is stable.
await applicationRef.whenStable();

const injector = applicationRef.injector;
const router = injector.get(Router);
const routesResults: RouteTreeNodeMetadata[] = [];
const errors: string[] = [];

Expand Down
33 changes: 33 additions & 0 deletions packages/angular/ssr/test/routes/ng-routes_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import '@angular/compiler';
/* eslint-enable import/no-unassigned-import */

import { Component } from '@angular/core';
import { Routes, provideRouter, withEnabledBlockingInitialNavigation } from '@angular/router';
import { extractRoutesAndCreateRouteTree } from '../../src/routes/ng-routes';
import { PrerenderFallback, RenderMode } from '../../src/routes/route-config';
import { setAngularAppTestingManifest } from '../testing-utils';
Expand Down Expand Up @@ -495,4 +496,36 @@ describe('extractRoutesAndCreateRouteTree', () => {
expect(errors).toHaveSize(0);
expect(routeTree.toObject()).toHaveSize(2);
});

it('should not bootstrap the root component when using `withEnabledBlockingInitialNavigation`', async () => {
@Component({
standalone: true,
selector: 'app-root',
template: '',
})
class RootComponent {
constructor() {
throw new Error('RootComponent should not be bootstrapped.');
}
}

const routes: Routes = [
{ path: '', component: DummyComponent },
{ path: 'home', component: DummyComponent },
];

setAngularAppTestingManifest(
routes,
[{ path: '**', renderMode: RenderMode.Server }],
undefined,
undefined,
undefined,
RootComponent,
[provideRouter(routes, withEnabledBlockingInitialNavigation())],
);

const { routeTree, errors } = await extractRoutesAndCreateRouteTree({ url });
expect(errors).toHaveSize(0);
expect(routeTree.toObject()).toHaveSize(2);
});
});
12 changes: 11 additions & 1 deletion packages/angular/ssr/test/testing-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { Component, Type, provideExperimentalZonelessChangeDetection } from '@angular/core';
import {
Component,
EnvironmentProviders,
Provider,
Type,
provideExperimentalZonelessChangeDetection,
} from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { provideServerRendering } from '@angular/platform-server';
import { RouterOutlet, Routes, provideRouter } from '@angular/router';
Expand Down Expand Up @@ -35,6 +41,8 @@ class AppComponent {}
* where the keys are asset paths and the values are asset details.
* @param locale - An optional locale to configure for the application during testing.
* @param rootComponent - The root Angular component to bootstrap the application.
* @param extraProviders - An optional array of additional providers that should be available to the
* root component and all its children.
*/
export function setAngularAppTestingManifest(
routes: Routes,
Expand All @@ -43,6 +51,7 @@ export function setAngularAppTestingManifest(
additionalServerAssets: Record<string, ServerAsset> = {},
locale?: string,
rootComponent: Type<unknown> = AppComponent,
extraProviders: Array<Provider | EnvironmentProviders> = [],
): void {
destroyAngularServerApp();

Expand Down Expand Up @@ -89,6 +98,7 @@ export function setAngularAppTestingManifest(
provideExperimentalZonelessChangeDetection(),
provideRouter(routes),
provideServerRoutesConfig(serverRoutes),
...extraProviders,
],
});
},
Expand Down

0 comments on commit 4a1833d

Please sign in to comment.