Skip to content

Emit onMiss on prerender configs - #114

Draft
lubakravche wants to merge 1 commit into
mainfrom
emit-onmiss-prerender
Draft

Emit onMiss on prerender configs#114
lubakravche wants to merge 1 commit into
mainfrom
emit-onmiss-prerender

Conversation

@lubakravche

Copy link
Copy Markdown
Collaborator

Note

Draft as a merge-order guard, not review status. This PR is ready for review now. It stays draft until the vercel/proxy dispatch PR and the vercel/api carriage PR merge and the proxy flag is enabled — merging the adapter side first would ship a field nothing consumes yet, and the changeset's behavior-change notice must land in the same release window as the platform actually honoring it.

Why

  • BOA prerender configs gain onMiss: "sync" | "dynamic", controlling how the platform serves a prerender cache miss. Absence means the current behavior: block the request on a synchronous revalidation. dynamic means serve the miss dynamically per request while a single coalesced async revalidation backfills the shell. RFC (approved): https://app.notion.com/p/3c9e06b059c481e4b84ee7e2abc06488
  • The adapter derives the mode per prerender group from Next.js's existing response classification (routeType / response / compute, emitted since next@16.3.0-canary.96 — the pin main already carries from Emit initialMetadata on prerender configs #107). This is a framework heuristic with no developer override.
  • The mapping, and why:
    • response: "complete"onMiss: "sync", emitted explicitly: the stored shell is the finished response, so blocking miss revalidation with its request collapsing (one invocation, one cache write) stays the cheapest way to serve it. Emitting the value rather than relying on absence makes new-Next builds distinguishable from legacy configs that merely lack classification data.
    • response: "initial" | "empty"onMiss: "dynamic": routes with dynamic holes already cost two invocations on a sync miss (shell render + resume), so per-request dynamic serving plus one coalesced async shell backfill is cost-neutral — and the miss is answered immediately instead of blocking.
    • Unclassified groups (older Next.js, fallback: false templates) and Route-Handler-only groups (routeType: "route") omit the key entirely — never an empty or undefined value — and keep the legacy blocking-miss behavior.
  • Supersedes Add static hints to prerender configs #98 (staticHint), which was the direct skeleton for this change: same group-level derivation point, but emitting the onMiss enum for classified groups instead of a boolean hint. staticHint is not emitted.

What

  • handlePrerenderOutputs builds a group-level map keyed by groupId from the group's canonical UI output (routeType !== 'route' && response !== undefined) before any outputs are processed, then applies it to every written prerender config in the group. Next.js classifies only the canonical output, but the platform reads each path's config independently, so the group's HTML and RSC configs must both carry the value.
  • initialMetadata emission (Emit initialMetadata on prerender configs #107) is untouched; this PR only adds the onMiss key.
  • No Next.js pin bump: main already pins 16.3.0-canary.96, the first canary with the classification fields.
  • Patch changeset for the chore: version packages (beta) flow, written to be conspicuous: once the proxy flag is enabled, upgrading the adapter changes miss behavior for all PPR routes with dynamic holes — intended and cost-neutral, but visible.

Validation

  • Unit tests in outputs.test.ts using the existing makePrerenderOutput / written-config helpers: a complete group emits onMiss: "sync" on both its HTML and RSC configs; initial and empty groups emit "dynamic" on both; an unclassified output gains no onMiss property; a Route-Handler-only group (routeType: "route") gains none.
  • biome check on touched files, vitest run (10/10), and tsc --noEmit all pass.

🤖 Generated with Claude Code


Recreated from #112 (same commit), which was opened from a fork by a sandboxed agent that lacked push access to this repo.

Derive the BOA prerender onMiss mode per prerender group from the
Next.js response classification on the group's canonical UI output:
'sync' when the response is complete (the stored shell is the finished
page, so a miss keeps blocking revalidation and its request collapsing),
'dynamic' when it is initial or empty (dynamic-hole routes already cost
two invocations on a blocking miss, so per-request dynamic serving plus
one coalesced async shell backfill is cost-neutral and serves misses
immediately). Unclassified groups and Route Handlers omit the key and
keep the legacy blocking-miss behavior.

The mode is captured per groupId before outputs are processed and
applied to both the HTML and RSC configs, since the platform reads each
path's config independently. The field is inert until the platform
proxy flag is enabled.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6a3668c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@next-community/adapter-vercel Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Aug 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
adapter-vercel-adapter Ready Ready Preview Aug 28, 2026 6:51pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant