-
Notifications
You must be signed in to change notification settings - Fork 483
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
Impossible to use dynamic routes with Angular Universal?! #1817
Comments
After a lot of reading and trial-and-error I now found a solution to this issue. I feel that it is a little bit hacky, so I would really love some feedback on it. Also I still believe that this should be possible with Angular Universal, without hacking into Basically what I do now, is to fetch the data about the pages, both in the server and the app, before the Angular app gets bootstrapped at all. It look more or less like this:
// All regular routes use the Universal engine
server.get('*', (req, res) => {
// fetch dynamic routes
// /!\ duplicate code to src/main.ts
fetch('http://static.content/')
.then(response => response.json())
.then(resp => {
const routes = resp.entries.map(route => ({
path: route.path,
component: StaticContentComponent,
data: {
id: route._id,
name: route.name
}
}));
res.render(indexHtml, {
req,
providers: [
{ provide: APP_BASE_HREF, useValue: req.baseUrl },
{ provide: DYNAMIC_ROUTES, useValue: routes }
]
});
});
});
return server;
} and basically the same in document.addEventListener('DOMContentLoaded', () => {
// fetch dynamic routes
// /!\ duplicate code to server.ts
fetch('http://static.content/')
.then(response => response.json())
.then(resp => {
const routes = resp.entries.map(route => ({
path: route.path,
component: StaticContentComponent,
data: {
id: route._id,
name: route.name
}
}));
platformBrowserDynamic([
{ provide: DYNAMIC_ROUTES, useValue: routes }
])
.bootstrapModule(AppModule)
.catch(err => console.error(err));
});
}); And then in my @NgModule({
imports: [
RouterModule.forRoot(routes, {
initialNavigation: 'enabled'
})
],
exports: [RouterModule]
})
export class AppRoutingModule {
constructor(@Inject(DYNAMIC_ROUTES) private dynamicRoutes, private router: Router) {
const config = router.config;
config.unshift(...this.dynamicRoutes);
this.router.resetConfig(config);
}
} So this does actually work. I am a bit unhappy about having to make the call twice (but couldn't get it working otherwise). Also I would have preferred to avoid hacking into Any ideas on how to improve this? Or do you see any issues to take this into production? |
@tommueller It works perfect! Only one thing I've refactored was to move the duplicate functionality for creating routes inside a service in a static method so we can call that from both Thank you so much for your idea! |
Currently we are using approach:
|
that's my approach
|
Hello. I am facing this problem now in Angular 9. What is StaticContentComponent? |
@Marcuss17 |
Hi, This solution works fine for SSR and ClientApp but Prerenderer requires DYNAMIC_ROUTES to be provided from 'app.server.module.ts' which seems to be impossible unfortunately. So as a result of this we are unable to prerender dynamic urls. Any ideas of help would greatly appreciated. Thanks, |
@Buyukcaglar Doesn't the whole idea of prerendering contradict with dynamic urls? At least in the way we use this, the content of the pages comes from somewhere else and is hence not static. Prerendering happens while compiling the project, so it does not make sense to prerender pages, that have dynamically changing content. Or am I missing your point? |
@tommueller Hi, The project currently I am working on is an e-commerce platform, so strict SEO requirements and site performance score (Google LightHouse/PageSpeed Insights) is essential. Although 'Product Detail' pages has fixed url prefix so I can define them within the 'routes' array so they are perfectly fine in prerendering. Unfortunately, 'Product Categories' (aka Category Product Listing Pages) are totally dynamic and therefore be their urls must be 'fetched' from backend API. And yes it whenever a product is added/modified or removed from a category that listing page hastto be prerendered again. On the other hand SSR on Category Listing Pages works like charm but Google Pagespeed score is total disaster. Lets say we got consistent 55 out 100 while using SSR but on the same listing page score is 95 out of 100 when page is prerendered. Hope this clarifies the situtation. Kind regards, |
For those curious, I can say with very high confidence that dynamically inserted, server-side rendered routes are possible and do not require API changes in Universal. We've been working on/with our |
Yes, as I stated, I found a solution for this as well which is running fine in our setup for ~2 years now. The proposed library was not around when I asked this question :) Anyways, fine by me to close this 👍 |
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. |
Proposal
What is the summary of the proposal?
It should be possible to use dynamically generated routes with Angular Universal.
What is the proposal?
In the docs it clearly states that it is necessary for Angular Universal to work to use
initialNavigation=enabled
on the router. This, as the name already states, leads to (if I understand correctly) Angular performing the first navigation before i.e. theAPP_INITIALIZER
s are loaded (which seems strange to me in the first place).Now I assume that a common use case for using Angular Universal is to add server side rendering to pages powered by some sort of headless CMS. That is also what I am trying to achieve. Without
initialNavigation=enabled
I had no problem to create the routes dynamically, after fetching page information from our backend. I basically execute this code within anAPP_INITIALIZER
in myapp.modules.ts
:Now with
initialNavigation=enabled
I always receive a 404 because I have no way of adding the routes, before the app tries to navigate there. The app still works with Universal support if I do not useinitialNavigation=enabled
, but I get bad flickering, which is not acceptable to deliver it like this to the user.Is there any way this problem can be solved?
edit: I am not entirely sure if this belongs to the Universal or the Angular Core team, so please feel free to move the ticket accordingly or let me know if I should open it somewhere else.
The text was updated successfully, but these errors were encountered: