Is it safe to use createSelector in SSR? #617
-
Hi, I have a setup using Next.js 12 and Redux (RTK/RTKQ), using next-redux-wrapper. It suddenly occurred to me that it might not be safe to use createSelector in SSR environments as it might cause cross-request data leakage. The thing I'm worried about is the built-in createSelector memoization, since the selectors are defined globally (not scoped to the request). This seems like it could case a scenario where one user can request a page that is server-side rendered and invokes a selector on the server, and then another user could get the same result from the cache, causing potential data leakage. I've looked into the source code a bit and it seems like this could be a major issue for me, but I wanted to first check whether someone else has investigated this more thoroughly before I start making big changes. What confuses me further is the README saying the following:
This makes me think it might be safe after all, since the original states will have different references. But this, in turn, confuses me about how the memoization works after all if reference checks are applied everywhere. I wrote this as a discussion rather than an issue since this isn't really a library problem (because it was not originally meant to be running in server environments). Thanks in advance :) |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 4 replies
-
I think that the reference checks are exactly why this shouldn't be an issue. But also I think this is a somewhat mistaken concern (?). Every SSR request should have an entirely separate Redux store to begin with, because different users may have different data needs + the actual leakage concerns. If I have a single selector instance, ie
So, I understand your concern, but I'm pretty sure there's actually nothing to worry about here. |
Beta Was this translation helpful? Give feedback.
-
Thanks for the fast reply :) Yeah it does seem kind of obvious now, I guess my initial confusion came from wondering how the cache works at all if reference checks are applied, but apparently I forgot the most important rule - immutability. Anyway, at the risk of going off-topic, I'd like to ask a followup question if you don't mind: Even though it is safe in terms of data leakage, is it smart to use it on the server at all? Considering:
import { createSelectorCreator, defaultMemoize } from 'reselect';
export const createStoreSelector = createSelectorCreator(
typeof window === 'undefined' ? (func) => func : defaultMemoize
);
Again, this might be off-topic from the original discussion theme, but I might as well ask here instead of creating another one. Thanks again :) |
Beta Was this translation helpful? Give feedback.
I think that the reference checks are exactly why this shouldn't be an issue. But also I think this is a somewhat mistaken concern (?).
Every SSR request should have an entirely separate Redux store to begin with, because different users may have different data needs + the actual leakage concerns.
If I have a single selector instance, ie
const selectTodos = createSelector(.....)
, it is indeed a shared cache, and using that across different requests could conceptually "share" results in a sense. BUT:selectTodos(store1.getState())
andselectTodos(store2.getState())
will force the selector to recalculate because it's grabbing d…