Fix react-loadable-manifest chunk hash mismatch by preserving async loader mapping (#88775)
## What?
Fixes a bug where `react-loadable-manifest.json` in Turbopack dev mode
contained references to chunk files with wrong hashes, causing 404
errors when loading dynamic imports.
## Why?
When using `next/dynamic` with nested imports (e.g., a dynamic component
that itself imports other modules), the chunk files referenced in
`react-loadable-manifest.json` had different hashes than the actual
generated chunk files.
The root cause was that `collect_next_dynamic_chunks` was
**recomputing** chunk content that was already computed by
`make_chunk_group`. This pattern was inherently brittle because Next.js
code had to carefully mirror Turbopack's internal chunking logic to get
consistent hashes.
This brittleness was exposed when the
`turbopackClientSideNestedAsyncChunking` feature was disabled in dev
mode (released in 16.1). The subtle differences in how availability info
was computed led to hash mismatches.
## How?
Instead of recomputing chunks for next/dynamic imports, this PR
preserves the module→async loader mapping from when chunks are first
computed in `make_chunk_group`, and looks up pre-computed chunks
directly. This eliminates the need for Next.js to replicate Turbopack's
chunking logic.
### Key changes:
1. **Extended `MakeChunkGroupResult` and `ChunkGroupResult`** with
`async_loaders_by_module` field
- Maps `ResolvedVc<Box<dyn ChunkableModule>>` → `ResolvedVc<Box<dyn
ChunkItem>>`
- Preserves the module→loader relationship computed during chunking
2. **Eliminated redundancy** in `MakeChunkGroupResult`
- Removed the separate `references` field (was just upcasted async
loaders)
- Added `references()` method that derives references on-demand from the
map
3. **Simplified `collect_next_dynamic_chunks`**
- Now performs simple lookup instead of recomputation
- Removed `module_graph` and `chunking_context` parameters
- Uses `NextDynamicChunkAvailability` enum to access pre-computed chunk
groups
4. **Added regression test** to verify chunk files referenced in
manifest exist
### Files modified:
- `turbopack/crates/turbopack-core/src/chunk/chunk_group.rs` - Add
mapping, remove redundant field
- `turbopack/crates/turbopack-core/src/chunk/chunking_context.rs` -
Extend ChunkGroupResult
- `turbopack/crates/turbopack-browser/src/chunking_context.rs` - Pass
through mapping
- `turbopack/crates/turbopack-nodejs/src/chunking_context.rs` - Pass
through mapping
- `crates/next-api/src/dynamic_imports.rs` - Lookup instead of recompute
- `crates/next-api/src/pages.rs` - Updated caller
- `crates/next-api/src/app.rs` - Updated caller
- `crates/next-core/src/next_app/app_client_references_chunks.rs` -
Initialize empty map
Fixes #87680