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

Docs: "use cache" non-serializable values contradiction #74498

Open
someone635 opened this issue Jan 3, 2025 · 2 comments · May be fixed by #74598
Open

Docs: "use cache" non-serializable values contradiction #74498

someone635 opened this issue Jan 3, 2025 · 2 comments · May be fixed by #74598

Comments

@someone635
Copy link

someone635 commented Jan 3, 2025

[This issue is based on a wrong interpretation of the docs, see comment below. Leaving this as reference as to how the docs could be misinterpreted, to guide as to how they may be improved. Still don't know yet if the docs ought to be improved, or if I am the problem for misunderstanding it]


What is the documentation issue?

In the documentation of "use cache", it is stated that:

"Any non-serializable arguments, props, or closed-over values will turn into opaque references inside the cached function, and can be only passed through and not inspected nor modified. These non-serializable values will be filled in at the request time and won't become a part of the cache key."

In the blog post explaining use cache in more details (Composable caching), this example is given:

function Profile({ id }) {
  async function getNotifications(index, limit) {
    'use cache';
    return await db
      .select()
      .from(notifications)
      .limit(limit)
      .offset(index)
      .where(eq(notifications.userId, id));
  }
 
  return <User notifications={getNotifications} />;
}

Now the db variable in the example is a closed-over non-serializable value, but in the example it is introspected without issue. (its select property is read). So not all non-serializable values are treated the same, contrary to what the documentation says. It is logical that functions or methods used for the caching functions functionality not be tampered with, as they should be referentially stable anyway, and thus not have any impact on the caching. But how does the compiler distinguish between an object used for functionality, or an object used as a value? That is not documented.

Is there any context that might help us understand?

Blog posts:
Composable caching
Our journey with caching

Does the docs page already exist? Please link to it.

https://nextjs.org/docs/app/api-reference/directives/use-cache

@someone635 someone635 added the Documentation Related to Next.js' official documentation. label Jan 3, 2025
@someone635
Copy link
Author

Oh okay, I reread Composable caching more carefully, and now I understand values are turned in opaque references when they are stored in the cache, not when the cached function receives them as arguments (or closures). I still feel the sentence in the docs "Any non-serializable arguments, props, or closed-over values will turn into opaque references inside the cached function, and can be only passed through and not inspected nor modified" can be misleading, (my confused thought process for reference: they cannot be inspected in the function because they already are opaque references at that point, thus all functions or non-serializable values become unusable in the function. But since it is impossible to write a cached function without using any subfunctions, the compiler must use some magic to distinguish between non-serializable values used for functionality and those used as part of the cache value.)

@someone635
Copy link
Author

I read the use-cache-wrapper code and think I understand better the internals of how it works. Will open a PR to suggest a clearer wording of the docs.

@samcx samcx removed the Documentation Related to Next.js' official documentation. label Jan 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants