I was scrolling through Tech Twitter a few months back, when I saw this tweet by the infamous Brandon:
If you don't know, Brandon created AnalogJS, the NextJS-like meta framework for Angular. I'm a huge fan of what he does for the Angular community, so I had to respond. He will be the first to tell you I want to solve everything with resolvers.
And...
Not one... single... like or response.
I don't post a lot on Twitter, nor do I have a following, so I didn't think anything of it.
However, I came across this post again randomly and read the comments, and I realized no one agrees with me! I honestly wonder if they even understand what I'm talking about.
There are actually two popular paradigms in JavaScript to load data.
This was the first way I ever learned in Angular. When I first took Fireship's Original Angular Course, I never even learned about resolvers. Resolvers are not popular, and I think extremely misunderstood.
Brandon's example above shows the data being loaded AFTER the component has rendered. This is the same pattern for other frameworks:<script> // Detect dark theme var iframe = document.getElementById('tweet-1836847595806732317-750'); if (document.body.className.includes('dark-theme')) { iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1836847595806732317&theme=dark" } </script>
Did you notice a pattern here? Server Side frameworks prefer load functions (resolver), while client frameworks fetch data in a signal reactively. But...
Angular is NOT a Server Side Framework!
The problem isn't that Angular is not an SSR frameworks, the problem is that it pretends to be.
Now I don't expect the Angular Team to add all of my feature requests. However, it would be nice to have basic .env support in the main builder, and the ability to make endpoints with the Angular Router. Brandon can handle the rest.
It is also still crazy to me that I can't deploy a basic Angular SSR application to Vercel.
I read an article about resolvers from 2019 that says the use case for resolvers is "very rare." Basically, you should only use them when you're fetching data that can load quickly. Ok, agreed. In reality, you would only load slow data in rare use cases. You want your site or application to be quick.
? What the heck man...
What would Josh Morony say?
You should not use RxJS in Angular unless you need to handle asynchronous events with race conditions or coordinate complex data flow.
He was referring to Signals VS Observables there, so I have no idea. Nevertheless, I like to think you should just fetch in the resolver by default UNTIL you have these advanced use cases.
If you're building a professional SSR application, you will need SEO generated from a database. You MUST use a resolver, or manually pause the component from loading with PendingTask, which is extremly funky.
In Analog, I suspect people are fetching only inside the file based endpoints, or they are generating static pages where it doesn't matter.
The programming patterns for my two favorite frameworks are polar opposites.
One popular answer to slow loading in the resolver, is HTTP Streaming. NextJS and SvelteKit support this, but it was turned down for Angular.
?
Currently, anything in the resolver will get fetched twice (server client). This needs to be handled in the future as well. ? Resolvers should pass the state automatically... use my useAsyncTrasferState function in a resolver for that.
I used ngxtension for the demo for brevity, but the result is the same.
id = injectParams('id'); idNumber = computed(() => Number(this.id())); todo = derivedAsync<Todo>(() => fetch(`https://jsonplaceholder.typicode.com/todos/${this.id()}`).then( (response) => response.json() ) ); prevId = computed(() => Math.max(this.idNumber() - 1, 1)); nextId = computed(() => this.idNumber() + 1);
todo = injectRouteData<Todo>('data'); idNumber = computed(() => this.todo()!.id); prevId = computed(() => Math.max(this.idNumber() - 1, 1)); nextId = computed(() => this.idNumber() + 1);
This is loaded from the resolver.
import { ResolveFn } from '@angular/router'; export const routeResolverResolver: ResolveFn<boolean> = async (route) => { const todoId = route.paramMap.get('id'); if (!todoId) { throw new Error('Todo ID is missing in the route!'); } // Fetch the todo from the API const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${todoId}`); if (!response.ok) { throw new Error('Failed to fetch the todo'); } return await response.json(); };
In this particular demo, there is a "flicker" in the effect version, while there is no flicker in the resolver version. I believe the resolver is better in this use case.
What do you think?
? Because Vercel doesn't support SSR Deployment, the demo is loading the resolver on the client only. This means routing only works from the home page.
I would say that it is on life support for asynchronous fetches. In reality, Angular SSR users should consider resolvers more for this use case and SvelteKit users should consider loading in $effect() for more use cases. But maybe that is the point? The userbase is different.
I'm still learning, but these questions fascinate me. Hopefully we see more shake ups in both ecosystems.
J
The above is the detailed content of Are Angular Resolvers on Life Support ?. For more information, please follow other related articles on the PHP Chinese website!