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

Investigate zoneless support #3561

Closed
wants to merge 9 commits into from
Closed

Conversation

mmalerba
Copy link
Contributor

@mmalerba mmalerba commented Aug 13, 2024

Results of investigation into make zonewrap zoneless-compatible

It seems like the current zonewrap API is not really compatible with Angular's SSR in general (either with or without zones). The problem is that at its core it relies on saving off injected services onto a global variable. However in SSR, each request has its own separate instances of these services, meaning that zonewrap is consulting the wrong instance of these services for every request other than the first one.

This seems to have gone unnoticed because zones kind of naturally keep everything unstable anyways. Ironically it seems that the only reason this works at all in zone applications with SSR is because after the first request, zonewrap inadvertently runs everything outside of the NgZone (by running it in the wrong instance of NgZone). I've noticed that with zones enabled, the first request seems to hang indefinitely due to the zone never stabilizing. It is only on subsequent requests (where zonewrap is running things in the wrong zone) that the application stabilizes and allows the server to respond.

In attempting to implement zoneless, the opposite happened where I was able to add the appropriate pending tasks to keep the application unstable for the first request, but on subsequent requests zonewrap had the wrong instance of ExperimentalPendingTasks and was therefore unable to stop the application from immediately becoming stable and returning a blank page.

Unfortunately I don't think there's an easy fix for this, other than to redesign the API to be compatible with the fact that each request is running a separate instance of the app. (i.e. we can't just wrap the function globally on import, it needs to somehow account for the context of the current application).

Using the APIs in zoneless apps with manual task management

The good news is that as of f283d1a usages of all Zones APIs that are strictly incompatible with zoneless applications have been removed. This means that the library can now be used in zoneless apps, though users won't be able to rely on auto-magic wrapping behavior, and will have to instead manage tasks themselves to keep the application unstable until the appropriate time during SSR.

Examples from the samples/advanced app:

  constructor(state: TransferState) {
    const key = makeStateKey<any>('DATABASE');
    const existing = state.get(key, undefined);
    this.testObjectValue$ = of(undefined).pipe(
      switchMap(() => import('./lazyDatabase')),
      switchMap(({valueChanges}) => valueChanges),
      traceUntilFirst('database'),
      tap(it => state.set(key, it)),
      existing ? startWith(existing) : tap(),
    );
  }

To make this work in zoneless, it can be modified to manually keep a task open until a value arrives:

  constructor(state: TransferState, tasks: ExperimentalPendingTasks) {
    const key = makeStateKey<any>('DATABASE');
    const existing = state.get(key, undefined);
    const taskDone = tasks.add();
    this.testObjectValue$ = of(undefined).pipe(
      switchMap(() => import('./lazyDatabase')),
      switchMap(({valueChanges}) => valueChanges),
      <any>traceUntilFirst('database'),
      tap(it => state.set(key, it)),
      existing ? startWith(existing) : tap(),
      tap(() => taskDone())
    );
  }

@mmalerba mmalerba changed the title zoneless support WIP: zoneless support Aug 15, 2024
@mmalerba
Copy link
Contributor Author

Closing based on the findings mentioned above. As shown above it should be possible to use angularfire in zoneless application, though the pending tasks will need to be explicitly managed by the user.

In the longer-term it may make sense to redesign some of the APIs to be compatible with having multiple application instances on the server, and at that point add support for more automatic management of the pending tasks

@mmalerba mmalerba closed this Aug 26, 2024
@mmalerba mmalerba changed the title WIP: zoneless support Investigate zoneless support Sep 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant