fix(middleware): run on missing build assets#2242
Conversation
|
/bigbonk review for issues |
commit: |
|
Performance benchmarksCompared 4 improved · 0 regressed · 2 within ±1.5%
View detailed results and traces 🟢 improvement · 🔴 regression · ⚫ change below 1.5% · paired base/head |
|
@james-elicx Bonk workflow was cancelled. View workflow run · To retry, trigger Bonk again. |
|
/bigbonk review for issues |
|
|
Posted my review to PR #2242. Summary of findings: Blocking issue: incomplete fix for the primary deployment targetThe PR fixes the Node prod servers (
Result: a middleware rewrite of a missing static chunk works on the Node server but silently fails when deployed to Workers — exactly the dev/prod divergence AGENTS.md warns against, left as an in-scope "known bug." Test gapThe new assertions only exercise the Pages Router Node prod server. There's no coverage for the App Router prod server (also modified here) or either Workers entry, so CI stays green while the Workers regression ships unnoticed. Correct parts
Recommendation: apply the same change to both Workers entries and add coverage that actually exercises them before merge. |
|
/bigbonk review for issues |
|
|
Posted my review to PR #2242. I independently verified every finding against the four parity sites in AGENTS.md (the PR is unchanged at SummaryBlocking: incomplete fix for the primary deployment target (Workers) The Node prod-server fix is correct, but the same short-circuit still exists in both Cloudflare Workers entries:
Result: a middleware rewrite of a missing Test gap The new assertions only exercise the Pages Router Node prod server ( Verified correct
Recommendation: Apply the fix to both Workers entries and add coverage that exercises them before merge. |
|
/bigbonk review for issues |
There was a problem hiding this comment.
/bigbonk review
Re-reviewed at 7d6106c, which adds the follow-up commit "fix(middleware): preserve missing asset rewrites on workers" on top of the original Node-side fix. The prior blocking concerns are now resolved. I verified all four parity sites in AGENTS.md and ran the targeted tests.
Prior blocking issue — now fixed ✅
The previous review flagged that the fix only applied to the Node prod servers, leaving both Cloudflare Workers entries (the primary deployment target) short-circuiting missing assets before middleware. Commit 7d6106c addresses this by introducing a shared helper and wiring it into both Workers entries:
worker-utils.ts:39-46— newfinalizeMissingStaticAssetResponse(response, missingBuildAsset)helper: only rewrites a404to the canonical plain-text static 404 (and drains the routed body viacancelResponseBody) when the request was asset-shaped; otherwise passes the response through untouched.- App Router (Workers)
app-router-entry.ts— replaces the earlynotFoundStaticAssetResponse()with amissingBuildAssetflag, lets the request reachrscHandler, then finalizes through the helper (and theresult === nullpath usesnotFoundStaticAssetResponse()only whenmissingBuildAsset). - Pages Router (Workers)
deploy.ts:624,716,719— same pattern: detect the asset shape up front, route throughrunPagesRequest, finalize after. - Hand-written example worker
examples/pages-router-cloudflare/worker/index.ts— finalizes its main return paths (:119,:248,:253) too.
The Node-side logic from the original commit remains sound: the flag is consulted only on the static-miss path, valid assets early-return before middleware (preserving the no-middleware fast path), and cancelResponseBody drains the routed 404 body before emitting the plain-text response.
Prior test-coverage gap — now closed ✅
Coverage now exercises all four handlers:
- App Router Node prod server —
tests/asset-prefix.test.ts:633("unset: emits URLs under /_next/static/") builds the App Routerapp-basicfixture (whose middleware now rewrites/_next/static/middleware-rewrite.js) and asserts the three-part contract viastartProdServer. - Pages Router Node prod server —
tests/asset-prefix.test.ts:697(basePath fixture,disableAppRouter). - App Router Workers —
tests/e2e/cloudflare-workers/ssr.spec.ts. - Pages Router Workers —
tests/e2e/cloudflare-pages-router/middleware.spec.ts.
Plus a focused unit test for the helper itself (tests/deploy.test.ts "finalizes only missing build-asset 404 responses") verifying body cancellation, the 200 passthrough, and the missingBuildAsset=false passthrough.
Verified locally
vp test run tests/deploy.test.ts— 282 passedvp test run tests/asset-prefix.test.ts -t "unset: emits URLs under"— passed (App Router prod path)vp test run tests/asset-prefix.test.ts -t "Pages Router with basePath alone serves assets"— passedvp checkon all four changed source files — clean (format, lint, types)
Non-blocking observations
-
Inconsistent asset-shape detection across the two Node prod paths. App Router uses
isNextStaticPath(...)(prod-server.ts:1333region) while Pages Router derives the flag fromresolveAppRouterAssetPath(...) !== null(prod-server.ts:1674). Both correctly scope to/_next/static/*-shaped paths, so net behavior matches, but two different predicates for "is this an asset request" is a minor readability/maintenance smell. Consider standardizing on one. -
A couple of un-finalized early returns won't be reached for asset paths, but are worth a glance for future-proofing. In
deploy.ts,dataNorm.notFoundResponse(:650) and the image-optimization branch (:659) return beforefinalizeMissingStaticAssetResponse; in the example worker, the API-route branch (:211-212) returnsmergeHeaders(...)directly. None of these can be reached by a/_next/static/*request today (data/image/API shapes are disjoint from the static-asset shape), so there's no live bug — just paths that would need finalization if those shapes ever overlapped. Not a blocker.
Summary
The follow-up commit fully addresses the previous blocking review: both Workers entries now run middleware on missing build assets via the shared finalizeMissingStaticAssetResponse helper, and all four parity sites have test coverage. The PR title and description are now accurate on Workers as well as Node. The remaining observations are minor and non-blocking. LGTM.
|
Review posted to PR #2242. SummaryI re-reviewed the PR at its current head ( Prior blocking issue — fixed ✅
Prior test-gap — closed ✅
Verified locally: deploy.test.ts (282 passed), both asset-prefix prod-server tests passed, Non-blocking observations (noted in the review): the two Node prod paths use different predicates for asset-shape detection (functionally equivalent), and a few early-return paths skip finalization but can't be reached by asset-shaped requests today. Verdict: LGTM — the follow-up commit makes the PR title/description accurate on Workers as well as Node. |
Summary
/_next/static/*requests reach middleware instead of returning from the static-file fast path404 Not Foundresponse when middleware/routing does not handle the missing assetFailure cluster
The latest Next.js deploy-suite artifact for
test/e2e/middleware-general/test/node-runtime.test.tsshowed the non-cache assertion:should be able to rewrite on _next/static/chunks/pages/ 404: expected200, received404The related original-request-shape assertion also observed no middleware header for a missing
/_next/static/*URL. Data-request assertions from the same suite are owned separately by #2239; the Suspense/app-static cluster is also actively owned elsewhere.Root cause
The Node production servers served existing build assets before middleware, which is correct, but also returned a static-layer 404 immediately for missing asset-shaped paths. Next.js allows middleware to rewrite or respond to a missing
/_next/static/*request before falling back to its plain-text asset 404.Next.js parity
Regression coverage is ported from:
test/e2e/middleware-general/test/index.test.tsThe local fixture verifies all three parts of the contract:
200without middleware headers/_next/static/*request404 text/plain; charset=utf-8with bodyNot FoundValidation
Targeted one-worker tests only:
vp test run tests/asset-prefix.test.ts -t "Pages Router with basePath alone serves assets" --maxWorkers=1vp test run tests/asset-prefix.test.ts -t "unset: emits URLs under /_next/static/" --maxWorkers=1vp check packages/vinext/src/server/prod-server.ts tests/asset-prefix.test.ts