mirror of
https://github.com/hanzoai/next.js.git
synced 2026-10-30 14:46:38 +00:00
Previously, in a `'use cache'` module, we only compiled statically-known
exported functions and arrow expressions to cache functions. Now, we
also compile re-exports and exports of values that might be functions.
This includes exports like:
- `export { getData } from './data'` - re-exporting from another module
- `export const aliased = getData` - exporting an imported identifier
- `const Page = withSlug(...); export default Page` - exporting the
result of a function call
These cases can't be statically verified as functions at compile time,
so we generate runtime wrappers with `typeof === "function"` checks
(simplified):
```js
let $$RSC_SERVER_CACHE_getData = getData;
if (typeof getData === "function") {
$$RSC_SERVER_CACHE_getData = React.cache(function() {
return cache("default", "...", 0, getData, arguments);
});
registerServerReference($$RSC_SERVER_CACHE_getData, "...", null);
Object.defineProperty($$RSC_SERVER_CACHE_getData, "name", { value: "getData" });
}
export { $$RSC_SERVER_CACHE_getData as getData };
```
This ensures that all function exports from `'use cache'` modules are
properly cached, while non-function exports pass through unchanged.
This approach comes with some limitations compared to statically-known
function exports:
1. **No compile-time type checking:** We can't verify that these exports
are actually functions. Non-function exports will be passed through
as-is at runtime.
2. **No async enforcement:** We can't enforce that functions must be
async (as we do for statically-known functions). Synchronous functions
are supported, but will lie about their type signature. They become
async after being wrapped as cache functions, even though their original
signature was synchronous.
closes NAR-196
32 lines
779 B
JavaScript
32 lines
779 B
JavaScript
'use cache'
|
|
|
|
// @ts-ignore
|
|
import { getStuff, wrap } from './foo'
|
|
// @ts-ignore
|
|
export { getData } from './data'
|
|
|
|
export const getCachedData = async () => {
|
|
// This is not using the wrapped version of getStuff, as we're only
|
|
// runtime-wrapping what flows out of the module, not into it. Would one
|
|
// expect this to be cached?
|
|
return getStuff()
|
|
}
|
|
|
|
export const aliased = getStuff
|
|
|
|
const Layout = wrap(async () => <div>Layout</div>)
|
|
const Other = wrap(async () => <div>Other</div>)
|
|
export const Sync = wrap(() => <div>Sync</div>)
|
|
|
|
export const wrapped = wrap(
|
|
async () => 'foo',
|
|
async () => 'bar',
|
|
async () => async () => 'baz',
|
|
() => 'sync'
|
|
)
|
|
|
|
export default Layout
|
|
export { Other, getStuff, staticallyKnownFunction }
|
|
|
|
async function staticallyKnownFunction() {}
|