Files
Janka UrygaandGitHub 9b4539301a [dynamicIO] cache tracking for import() (#74152)
This PR introduces some extra tracking which makes us treat
`import(...)` like a call to a cached function. Thanks to this, `await
import(...)` will no longer cause dynamicity errors in `dynamicIO`.
The motivation is the same as allowing `fs.readFileSync` -- if something
is available on the server at prerender time, we don't consider it IO.

Fixes #72589
Closes #75132

### Implementation notes

The tracking is implemented via an SWC transform
(`track_dynamic_imports.ts`) that turns `import(...)` into
`trackDynamicImport(import(...))`.

`trackDynamicImport(promise)` tracks the promise globally, without using
`workUnitStore.cacheSignal`. The prospective render subscribes to
pending modules using `trackPendingModules(cacheSignal)`, which causes
the prospective render to wait for all `import()`s to finish before
proceeding to the final render. The mechanism is analogous to `'use
cache'`, but the "result" of an `import()` is stored *in the module
cache* instead; when we invoke the `import()` again in the actual
prerender, it will resolve at microtask-speed, like we need it to.

The transform is enabled for all modules that run server-side, both RSC
and SSR, because the prerender runs both. This also includes route
handlers, because we also use a `cacheSignal` when prerendering those.
Notably, we also instrument `import()` in `node_modules` to account for
libraries that do lazy initialization.

I've also had to adjust the prospective client render in PPR mode to
wait for `cacheSignal.cacheReady()` - otherwise, it wouldn't wait for
`import()`s to resolve before doing the final client render, which'd
subsequently cause a dynamicity error.
(we didn't need to wait for `cacheSignal` before, because all cached
promises would've already been awaited in the server prerender)

Finally, we no longer need `warmFlightResponse`, because
`trackPendingModules` already makes the `cacheSignal` wait for all
loading chunks to finish, so we don't need to do it ahead of time.
2025-05-06 21:05:41 +00:00

7 lines
105 B
JavaScript

async function foo() {
const { foo } = await import('some-module')
return foo()
}
exports.foo = foo