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

Facilitate Garbage Collection with weak refs in Angular Universal / SSR #4513

Open
2 tasks
amakhrov opened this issue Aug 29, 2024 · 0 comments
Open
2 tasks

Comments

@amakhrov
Copy link
Contributor

amakhrov commented Aug 29, 2024

Which @ngrx/* package(s) are relevant/related to the feature request?

store

Information

createSelector uses a memoization function under the hood that stores the reference to the last argument (state object). This works great in a browser, where there is a single global NgRx state per app.
On the server (server rendering with Angular Universal), we get a new instance of the store, and a new instance of the global state for each user request.

It has two implications

  • Memoization is less efficient in SSR, when multiple requests are handled in parallel that use the same selector. All those requests keep overriding the stored last argument in the selector, effectively invalidating it every time.
  • After a request is finished, the memoized selector keeps the reference to the last State instance in the closure. It prevents this state instance from being garbage collected. In its extreme, we can end up in the situation where each selector stores a ref to a different State - having as many not GC'd State instances as we have selectors.

This feature request is primarily concerned with the second item - multiple state instances that are not GC'd between the requests.

The suggested solution would involve using weak refs to store the last argument of a memoized selector.
Furthermore, with weak refs we could store more that one last argument in the cache (via WeakMap) - thus also addressing my first bullet point from the above (should be careful with selectors args that are primitives though).

Describe any alternatives/workarounds you're currently using

None so far.

Theoretically, we could use createSelectorFactory (with a typing workaround because of #3987). But it means we need to update all selectors across the app. There is no way to override the default memoize function globally in the app.

I would be willing to submit a PR to fix this issue

  • Yes
  • No
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants