next.js
1e1f9e69 - test: cover Pages Router _app availability in Turbopack dev (#99789) (#99910)

Commit
7 days ago
test: cover Pages Router _app availability in Turbopack dev (#99789) (#99910) ### What? Regression coverage for #99789, stacked on #98823. This is PR 2 of a six-PR stack, based on `canary`: 1. #98823 — Pages Router dev client graph chaining 2. **This PR** — regression test for Pages Router `_app` availability (#99789) 3. #98734 — use graph-derived merged groups 4. #99750 — chunking takes a `ChunkGroupKey` 5. #98685 — chunk-group availability bitmaps 6. #99050 — keyed chunk-group index lookups - **New e2e suite** `test/e2e/pages-app-availability-boundary`: a Pages Router app with the import shape from #99789: - `_app` imports `c-shared` and dynamically imports a module that also imports it. - `pages/index` imports `a-page-only`, `b-boundary`, `c-shared`, `d-boundary`, `e-page`, and dynamically imports a module that imports `b`/`d`, which makes `b` and `d` batching boundaries. The test asserts that the page hydrates (a marker set in `useEffect`), that every imported value renders, and that no "module factory is not available" error is logged. - **`app-document-import-order`**: the "loads modules shared by _app and the page only once" assertion added in #97664 was skipped in all of dev. It now runs everywhere and is gated `// @gate !(turbopack && dev)` (expected failure). ### Why? In Turbopack dev, #97664 seeds each page's client chunk group with `/_app`'s availability. But each page had its own module graph, so availability items (`ModuleOrBatch` identities) were compared across graphs. In the page graph, batching can produce a `ModuleOrBatch::Module(c-shared)` node whose edges point at earlier siblings (`a`, `b`). Because `/_app` already has `Module(c-shared)`, the traversal excluded that subtree, and `a`/`b` were never chunked. Hydration then fails with `Module [project]/lib/a-page-only.js … was instantiated … but the module factory is not available`. No test covered this, because the #97664 test was skipped in dev. #98823 chains `/_app` and the page into one dev client module graph, which fixes the missing modules. It does **not** yet dedupe the `app-document-import-order` fixture in Turbopack dev. The shared module is still emitted in both the `_app` and the page chunk, because the page's batches in the combined graph carry different chunk-group bitmaps than `_app`'s own graph, so they don't match `_app`'s availability items. Hence the gate. It stays valid through #98734 and #99750; #98685 (higher in this stack) dedupes the fixture in Turbopack dev, turning it into a "stale gate", and removes it. ### How was it verified? Local JS build of this branch plus the preview native binaries of #98823's head (`8dd759a`) and its base (`26fd598`) in `packages/next-swc/native`. The two commits differ only in Rust. | Suite | Mode | #98823 base | #98823 head | |---|---|---|---| | `pages-app-availability-boundary` | Turbopack dev | ❌ module factory not available | ✅ | | `pages-app-availability-boundary` | Turbopack start, webpack dev/start | | ✅ | | `app-document-import-order` | Turbopack dev | | ✅ (gated: failed as expected) | | `app-document-import-order` | webpack dev, Turbopack/webpack start | | ✅ | After restacking onto canary, with native builds of each layer, in Turbopack dev: - This PR's tree: `pages-app-availability-boundary` ✅, `app-document-import-order` ✅ (gated: failed as expected). - #98734 and #99750: gated assertion still fails as expected. - #98685 and #99050: gate stale, so #98685 removes it; ungated, both suites ✅. Fixes #99789 (together with #98823) <!-- NEXT_JS_LLM --> <!-- fleet a7614af3-e186-4297-beaf-7e55eaddc0da --> <!-- fleet 4f67c6f7-bbe2-454b-9a17-822a60ef8f7e --> Co-authored-by: vercel-fleet-prod[bot] <318278635+vercel-fleet-prod[bot]@users.noreply.github.com> Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com> Co-authored-by: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com>
Author
Parents
Loading