Request Memoization for fetch and cache()
Hard · Caching
During one server render pass, Next.js memoizes fetch calls: a GET with the same URL and options made by several layouts, pages or components runs only once and everyone gets the same result. React's cache(fn) does the same for your own functions (for example database queries). Memoization lasts for a single request only, it is not a persistent cache. It does not apply in Route Handlers (they are not part of the React tree), and you can opt a fetch out by passing an AbortController signal.
Write renderRequests(requests) that simulates this. This is a simplified model of request memoization. Each request is { kind: "page" | "route", calls }. A call is { type: "fetch", url, options? } or { type: "cache", fn, args }.
- Every real execution increases a counter shared by all requests (starting at 1) and produces the value "<label>#<counter>", where the label is the url for fetch and fn for cache.
- In a "route" request nothing is memoized.
- In a "page" request, a fetch is memoized when its method (options.method, default "GET", case-insensitive) is GET and options.signal is not set. Its key is the URL plus the other options (without method) compared deeply, so key order inside objects does not matter. A cache call is memoized by fn plus its args (primitives). Fetch and cache calls never share entries.
- A memoized call whose key was already seen in the same request returns the earlier value without executing.
Return { results, executions }: results[i] is the list of values of request i in call order, executions is the final counter value.