Skip to content

fix(pages-router): default Cache-Control on gssp responses#1574

Draft
james-elicx wants to merge 1 commit into
mainfrom
fix/gssp-cache-control-header
Draft

fix(pages-router): default Cache-Control on gssp responses#1574
james-elicx wants to merge 1 commit into
mainfrom
fix/gssp-cache-control-header

Conversation

@james-elicx
Copy link
Copy Markdown
Member

Closes #1461

Summary

  • Pages Router getServerSideProps responses now set the default Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate unless overridden, and forward res.setHeader('Cache-Control', ...) values to the final response.

Test plan

  • Test asserts default header
  • Test asserts user override sticks
  • vp check passes

getServerSideProps responses now ship the Next.js default
`private, no-cache, no-store, max-age=0, must-revalidate` Cache-Control
header in both dev and prod, and forward `res.setHeader('Cache-Control', ...)`
overrides set inside gssp through to the final response.

Mirrors next/src/server/route-modules/pages/pages-handler.ts where a
gssp page resolves to `revalidate: 0` and getCacheControlHeader emits
the same string, gated by `if (!res.getHeader('Cache-Control'))` to
preserve user overrides.

Closes #1461
@james-elicx
Copy link
Copy Markdown
Member Author

/bigbonk review

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 22, 2026

Open in StackBlitz

npm i https://pkg.pr.new/vinext@1574

commit: 6bb4a50

@github-actions
Copy link
Copy Markdown

Example Preview Production Original
app-router-cloudflare preview production
pages-router-cloudflare preview production
app-router-playground preview production original
realworld-api-rest preview production
nextra-docs-template preview production
benchmarks preview production
hackernews preview production original
web preview production

Copy link
Copy Markdown
Contributor

@ask-bonk ask-bonk Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, well-scoped fix. Both code paths (dev-server + pages-page-response) are covered, the priority cascade (user override > nonce > ISR > gSSP default) is correct, and the tests exercise both the default and the override in dev and prod.

Two minor observations — neither blocks merge:

  1. Duplicate default in dev-server: dev-server.ts:592-598 sets the default Cache-Control into gsspExtraHeaders, then the streamPageToResponse path spreads gsspExtraHeaders into extraHeaders at line 1070-1072. That works, but the same default is also applied inside renderPagesPageResponse at line 392-396 (the prod path). For dev, this means the default could theoretically be set twice — once in gsspExtraHeaders and once in renderPagesPageResponse (since renderPagesPageResponse is not used in the dev streaming path, this doesn't actually double-fire today). Worth a comment noting that the dev-server addition is dev-only (streaming path) while the pages-page-response.ts addition covers the prod renderPagesPageResponse path, so they don't overlap. The existing comments are close but don't make this fully explicit.

  2. Fixture typing: ssr-cache-control.tsx:18 uses { res: any } for the gSSP context. Minor, but the existing ssr-headers.tsx fixture does the same, so it's consistent. Not a blocker.

Tests are thorough — covers dev default, dev override, prod default, and prod override. LGTM.

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented May 22, 2026

Approved PR #1574 with review. Here's the summary:

Verdict: APPROVE

The fix correctly adds the default Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate header on getServerSideProps responses, matching Next.js behavior. The priority cascade is correct: user override > nonce > ISR > gSSP default.

Both code paths are covered:

  • dev-server.ts — dev streaming path via gsspExtraHeaders
  • pages-page-response.ts — prod path via renderPagesPageResponse

Tests cover all four scenarios: dev default, dev override, prod default, and prod override.

Two minor non-blocking observations were noted about the dev/prod path separation clarity and fixture typing consistency.

github run

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.

Pages Router: gssp/getStaticProps responses missing default and user-set Cache-Control header

1 participant