Skip to content

Commit

Permalink
fix(@angular/ssr): show error when multiple routes are set with `Rend…
Browse files Browse the repository at this point in the history
…erMode.AppShell`

This change introduces error handling to ensure that when multiple routes are configured with `RenderMode.AppShell`, an error message is displayed. This prevents misconfiguration and enhances clarity in route management.
  • Loading branch information
alan-agius4 committed Sep 26, 2024
1 parent 50df631 commit 64c5252
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 10 deletions.
32 changes: 23 additions & 9 deletions packages/angular/ssr/src/routes/ng-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const VALID_REDIRECT_RESPONSE_CODES = new Set([301, 302, 303, 307, 308]);
*/
type ServerConfigRouteTreeAdditionalMetadata = Partial<ServerRoute> & {
/** Indicates if the route has been matched with the Angular router routes. */
matched?: boolean;
presentInClientRouter?: boolean;
};

/**
Expand Down Expand Up @@ -134,15 +134,15 @@ async function* traverseRoutesConfig(options: {
continue;
}

matchedMetaData.matched = true;
matchedMetaData.presentInClientRouter = true;
}

const metadata: ServerConfigRouteTreeNodeMetadata = {
...matchedMetaData,
route: currentRoutePath,
};

delete metadata.matched;
delete metadata.presentInClientRouter;

// Handle redirects
if (typeof redirectTo === 'string') {
Expand Down Expand Up @@ -246,8 +246,8 @@ async function* handleSSGRoute(
if (!getPrerenderParams) {
yield {
error:
`The '${stripLeadingSlash(currentRoutePath)}' route uses prerendering and includes parameters, but 'getPrerenderParams' is missing. ` +
`Please define 'getPrerenderParams' function for this route in your server routing configuration ` +
`The '${stripLeadingSlash(currentRoutePath)}' route uses prerendering and includes parameters, but 'getPrerenderParams' ` +
`is missing. Please define 'getPrerenderParams' function for this route in your server routing configuration ` +
`or specify a different 'renderMode'.`,
};

Expand Down Expand Up @@ -442,24 +442,38 @@ export async function getRoutesFromAngularRouterConfig(
includePrerenderFallbackRoutes,
});

let seenAppShellRoute: string | undefined;
for await (const result of traverseRoutes) {
if ('error' in result) {
errors.push(result.error);
} else {
if (result.renderMode === RenderMode.AppShell) {
if (seenAppShellRoute !== undefined) {
errors.push(
`Error: Both '${seenAppShellRoute}' and '${stripLeadingSlash(result.route)}' routes have ` +
`their 'renderMode' set to 'AppShell'. AppShell renderMode should only be assigned to one route. ` +
`Please review your route configurations to ensure that only one route is set to 'RenderMode.AppShell'.`,
);
}

seenAppShellRoute = stripLeadingSlash(result.route);
}

routesResults.push(result);
}
}

if (serverConfigRouteTree) {
for (const { route, matched } of serverConfigRouteTree.traverse()) {
if (matched || route === '**') {
for (const { route, presentInClientRouter } of serverConfigRouteTree.traverse()) {
if (presentInClientRouter || route === '**') {
// Skip if matched or it's the catch-all route.
continue;
}

errors.push(
`The server route '${route}' does not match any routes defined in the Angular routing configuration. ` +
'Please verify and if unneeded remove this route from the server configuration.',
`The '${route}' server route does not match any routes defined in the Angular ` +
`routing configuration (typically provided as a part of the 'provideRouter' call). ` +
'Please make sure that the mentioned server route is present in the Angular routing configuration.',
);
}
}
Expand Down
24 changes: 23 additions & 1 deletion packages/angular/ssr/test/routes/ng-routes_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ describe('extractRoutesAndCreateRouteTree', () => {

expect(errors).toHaveSize(1);
expect(errors[0]).toContain(
`The server route 'invalid' does not match any routes defined in the Angular routing configuration`,
`The 'invalid' server route does not match any routes defined in the Angular routing configuration`,
);
});

Expand All @@ -339,4 +339,26 @@ describe('extractRoutesAndCreateRouteTree', () => {
`The 'invalid' route does not match any route defined in the server routing configuration`,
);
});

it(`should error when 'RenderMode.AppShell' is used on more than one route`, async () => {
setAngularAppTestingManifest(
[
{ path: 'home', component: DummyComponent },
{ path: 'shell', component: DummyComponent },
],
[{ path: '**', renderMode: RenderMode.AppShell }],
);

const { errors } = await extractRoutesAndCreateRouteTree(
url,
/** manifest */ undefined,
/** invokeGetPrerenderParams */ false,
/** includePrerenderFallbackRoutes */ false,
);

expect(errors).toHaveSize(1);
expect(errors[0]).toContain(
`Both 'home' and 'shell' routes have their 'renderMode' set to 'AppShell'.`,
);
});
});

0 comments on commit 64c5252

Please sign in to comment.