-
Notifications
You must be signed in to change notification settings - Fork 12k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Since 19.1: SSR Apps with urlMatcher
in route config are breaking due to commit 6edb908
#29384
Comments
Before this change, the URL matchers did not function correctly at runtime. With this update, an error is shown during build time instead. For more details, refer to: #29284. I’m interested in understanding the specific use cases where route matchers are used. Could you share yours, along with a code snippet demonstrating your implementation? |
@alan-agius4 thanks for the input. You are right, on local development the matcher is not working. But on our staging server with a production build the routes with urlMatcher are rendered correctly on the server. happy to share our use case: We have a route that lists subpages of various levels in a chronical order. The pages can have related events to it which will have a nested permalink for simplicity here are the path created by the backend: /overview as you can see the "events" urlSegments indicate that the last element is a event. As Angulars router config does not allow wildcards before url segements like Current implementation (which was working in 19.0):export default [
{
path: '',
resolve: {
nav: navigationResolver,
},
children: [
{
path: '',
loadComponent: () =>
import('./overview/overview.component'),
resolve: {
page: overviewResolver,
},
},
{
path: 'past',
loadComponent: () => import('./archive/archive.component'),
resolve: {
page: archiveResolver,
},
},
{
matcher: relatedEvent,
loadComponent: () =>
import('../events/event-detail/event-detail.component'),
},
{
matcher: defaultPage,
loadComponent: () => import('./default-page/default-page.component'),
resolve: {
page: defaultPageResolver,
},
},
],
},
] satisfies Route[]; relatedEvent matcher function export function relatedEvent(url: UrlSegment[]): UrlMatchResult | null {
const isEventDetail = url.length > 2 && url.at(-2)?.path === 'events';
const slug = url.at(-1);
return isEventDetail && slug ? { consumed: url, posParams: { slug } } : null;
} defaultPage matcher function export function defaultPage(url: UrlSegment[]): UrlMatchResult | null {
if (url.length >= 1) {
const isNotEvent = !(
url.length >= 2 && url.at(-2)?.path === 'events'
);
const slug = url.at(-1);
return isNotEvent && slug ? { consumed: url, posParams: { slug } } : null;
}
return null;
} Ideal implementation if Angular route config would allow wildcards (not working in any version of Angular):export default [
{
path: '',
resolve: {
nav: navigationResolver,
},
children: [
{
path: '',
loadComponent: () =>
import('./overview/overview.component'),
resolve: {
page: overviewResolver,
},
},
{
path: 'past',
loadComponent: () => import('./archive/archive.component'),
resolve: {
page: archiveResolver,
},
},
{
path: '**/:slug',
loadComponent: () => import('./default-page/default-page.component'),
resolve: {
page: defaultPageResolver,
},
children: [
{
path: 'events/:event-slug',
loadComponent: () => import('../events/event-detail/event-detail.component'),
}
]
},
],
},
] satisfies Route[]; Maybe there is another way to have n-wildcard-urlSegments before a routerParameter is defined, but i'm not aware of such a solution. The urlMatcher function was giving me exactly this feature. Happy for any help here. |
Based on the provided URL structure, it seems unnecessary to create a custom matcher function. Instead, you can use Angular's built-in matcher and define nested routes with multiple levels or parameters as required. For example: import { Routes } from '@angular/router';
export const routes: Routes = [
{
path: 'overview',
children: [
{
path: '',
loadComponent: () => import('./overview/overview.component'),
},
{
path: 'past',
loadComponent: () => import('./past/past.component'),
},
{
path: ':event',
children: [
{
path: '',
loadComponent: () => import('./events/events.component'),
},
{
path: 'past',
loadComponent: () => import('./past/past.component'),
},
{
path: ':event-detail',
loadComponent: () =>
import('./events-details/events-details.component'),
},
],
},
],
},
]; |
@alan-agius4 true, but this would mean i need to create several child routes and cannot guarantee a "n-deep" hierachy. import { Routes } from '@angular/router';
export const routes: Routes = [
{
path: 'overview',
children: [
{
path: '',
loadComponent: () => import('./overview/overview.component'),
},
{
path: 'past',
loadComponent: () => import('./past/past.component'),
},
{
path: ':event',
children: [
{
path: '',
loadComponent: () => import('./events/events.component'),
},
{
path: ':sub-event',
children: [
{
path: '',
loadComponent: () => import('./../events/events.component'),
},
{
path: ':sub-sub-event',
children: [
{
path: '',
loadComponent: () => import('./../../events/events.component'),
},
{
children: [
... // this would require manual repitition depending on the allowed levels (currently there should not be any limit to the editors)
]
},
{
path: 'events/:event-detail',
loadComponent: () =>
import('./../../events-details/events-details.component'),
},
],
},
{
path: 'events/:event-detail',
loadComponent: () =>
import('./../events-details/events-details.component'),
},
],
},
{
path: 'events/:event-detail',
loadComponent: () =>
import('./events-details/events-details.component'),
},
],
},
],
},
]; |
Oh I missed that sorry |
@alan-agius4 do you think the |
@alan-agius4 I'm just a bit confused as i understood that the const matcher = route.matcher || defaultUrlMatcher; |
We have no issues here with SSR and custom route matcher on version 19.0. No 404s, no errors. Set everything to RenderMode.Server. hmm... |
During SSR, two routers are in use: the traditional Angular router and an additional Angular SSR router (Which is currently in developer preview). The latter, found here, requires routes to be serializable. While route matchers could function possible this was due to a catch-all route being present in the Angular router, which tricked the SSR Router to ignore the matchers. That said, the Angular SSR router, which is currently in developer preview, does not support custom route matchers. This feature is being tracked in #29284 |
@alan-agius4 thanks for the clarification. My first guess was that switchting from So my question: is there a way to update to Angular 19.1 without using the new SSR Router? |
To switch back to the |
hm, even with usage of |
You need to remove |
how to catch routes like /[text]--[id]. without urlMatcher |
@celilunver i guess until |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Command
serve
Is this a regression?
The previous version in which this bug was not present was
19.0
Description
With 19.0 it was possible to use
UrlMatcher
functions within SSR applications. 19.1 introduced a commit 6edb908 which was meant to fix a incompatibality ofUrlMatcher
with SSR applications. I wasn't able to find any documentation that indicatedUrlMatcher
and SSR are not working together. Was this a issue that needed to be solved? The only issue i was able to find on the web was in combination with the @angular-architects/module-federation library (https://dev.to/michaeljota/how-to-add-module-federation-into-your-angular-micro-frontend-apps-jmh)Before we start refactoring our project (which requires SSR and also
UrlMatcher
) or downgrading to 19.0 I would like to know what the implications were for this "fix". Happy for any insights.Minimal Reproduction
ng serve
Exception or Error
Your Environment
Anything else relevant?
No response
The text was updated successfully, but these errors were encountered: