Skip to content
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

Use Resolvers Instead of Async Imports #1033

Open
2 tasks
jdgamble555 opened this issue Apr 13, 2024 · 2 comments
Open
2 tasks

Use Resolvers Instead of Async Imports #1033

jdgamble555 opened this issue Apr 13, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@jdgamble555
Copy link

jdgamble555 commented Apr 13, 2024

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
@jdgamble555 jdgamble555 added the enhancement New feature or request label Apr 13, 2024
@atscott
Copy link

atscott commented Apr 14, 2024

Obviously if Angular adds a way to resolve things in the component with Zoneless, that way would be an option too.

This will happen and likely as soon as 18.1 or 18.2. We use the PendingTasks service internally and this is actually how everything contributes to application stability, including ZoneJS. Having a public api for this is a blocker for zoneless becoming stable and also likely a blocker for graduating from experimental to developer preview.

@jdgamble555
Copy link
Author

@atscott - Well when you guys do look at it, perhaps you could look at server only routes (APP_INITIALIZER, except similar to ROUTE_INITIALIZER --- if that existed)...

Glad to know these things are evolving so quickly!

J

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants