analog
analog copied to clipboard
Use Resolvers Instead of Async Imports
Which scope/s are relevant/related to the feature request?
create-analog
Information
Now that we know Zoneless is coming sooner than later as experimental, I think Analog needs to prepare for it. I actually wrote the waitFor function that was later implemented in Analog trying to avoid resolvers, when I didn't really understand that we definitely need to use them instead. Get rid of it. Get rid of all importing directly into the component, as this is not how Angular works, or should work.
It will break Analog when we go Zoneless!
I think this is the problem I keep going back to with Analog from different directions. The markdown components have a bug keeping SSR working correctly. Importing routes doesn't work as expected. We need transfer state for resolvers (provideClientHydration) so that we don't double fetch. This all seems to be problems related to not using resolvers. I have a few solutions.
import { TransferState, inject, makeStateKey } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { map } from "rxjs";
// put in resolver for async operations
export const useAsyncTransferState = async <T>(
name: string,
fn: () => T
) => {
const state = inject(TransferState);
const key = makeStateKey<T>(name);
const cache = state.get(key, null);
if (cache) {
return cache;
}
const data = await fn() as T;
state.set(key, data);
return data;
};
// put in resolver for non-async operations
export const useTransferState = <T>(
name: string,
fn: () => T
) => {
const state = inject(TransferState);
const key = makeStateKey<T>(name);
const cache = state.get(key, null);
if (cache) {
return cache;
}
const data = fn() as T;
state.set(key, data);
return data;
};
// idea accidently came from Brandon
export const injectResolver = <T>(name: string) =>
inject(ActivatedRoute).data.pipe<T>(map(r => r[name]));
export const injectSnapResolver = <T>(name: string) =>
inject(ActivatedRoute).snapshot.data[name] as T;
You can see an example of useAsyncTransferState()
in my Analog Firebase Repo.
We can use resolvers easier thanks to Brandon's accidental idea trying to understand my though process. I use them, they work great!
Problems to Solve
- The
.md
files should be loaded in the resolver on the server and transferred to the client. The JS bundle for importing them should not even be on the client. - The server-only routes should be automatically injected into the browser with
TransferState
inside the resolver. - After the regular gets fixed, there should be
dependency
tracking so that it only gets reran when necessary similar to SvelteKit.
I think my functions above could be added to the framework as utility functions anyone could use.
This has been the only thing I have seen that holds back Analog.
Thanks,
J
Describe any alternatives/workarounds you're currently using
Obviously if Angular adds a way to resolve things in the component with Zoneless, that way would be an option too.
I would be willing to submit a PR to fix this issue
- [ ] Yes
- [ ] No