-
Notifications
You must be signed in to change notification settings - Fork 27.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Segment Cache] Add PPR header to segment prefetch #73756
Conversation
Tests Passed |
Stats from current PRDefault BuildGeneral Overall increase
|
vercel/next.js canary | acdlite/next.js segment-cache-ppr-header | Change | |
---|---|---|---|
buildDuration | 18.4s | 16.9s | N/A |
buildDurationCached | 16s | 13.5s | N/A |
nodeModulesSize | 409 MB | 409 MB | |
nextStartRea..uration (ms) | 486ms | 481ms | N/A |
Client Bundles (main, webpack)
vercel/next.js canary | acdlite/next.js segment-cache-ppr-header | Change | |
---|---|---|---|
1187-HASH.js gzip | 50.7 kB | 50.8 kB | N/A |
8276.HASH.js gzip | 169 B | 168 B | N/A |
8377-HASH.js gzip | 5.36 kB | 5.36 kB | N/A |
bccd1874-HASH.js gzip | 53 kB | 53 kB | N/A |
framework-HASH.js gzip | 57.5 kB | 57.5 kB | N/A |
main-app-HASH.js gzip | 232 B | 235 B | N/A |
main-HASH.js gzip | 34 kB | 34 kB | N/A |
webpack-HASH.js gzip | 1.71 kB | 1.71 kB | N/A |
Overall change | 0 B | 0 B | ✓ |
Legacy Client Bundles (polyfills)
vercel/next.js canary | acdlite/next.js segment-cache-ppr-header | Change | |
---|---|---|---|
polyfills-HASH.js gzip | 39.4 kB | 39.4 kB | ✓ |
Overall change | 39.4 kB | 39.4 kB | ✓ |
Client Pages
vercel/next.js canary | acdlite/next.js segment-cache-ppr-header | Change | |
---|---|---|---|
_app-HASH.js gzip | 193 B | 193 B | ✓ |
_error-HASH.js gzip | 193 B | 193 B | ✓ |
amp-HASH.js gzip | 512 B | 510 B | N/A |
css-HASH.js gzip | 343 B | 342 B | N/A |
dynamic-HASH.js gzip | 1.84 kB | 1.84 kB | ✓ |
edge-ssr-HASH.js gzip | 265 B | 265 B | ✓ |
head-HASH.js gzip | 363 B | 362 B | N/A |
hooks-HASH.js gzip | 393 B | 392 B | N/A |
image-HASH.js gzip | 4.49 kB | 4.49 kB | N/A |
index-HASH.js gzip | 268 B | 268 B | ✓ |
link-HASH.js gzip | 2.35 kB | 2.34 kB | N/A |
routerDirect..HASH.js gzip | 328 B | 328 B | ✓ |
script-HASH.js gzip | 397 B | 397 B | ✓ |
withRouter-HASH.js gzip | 323 B | 326 B | N/A |
1afbb74e6ecf..834.css gzip | 106 B | 106 B | ✓ |
Overall change | 3.59 kB | 3.59 kB | ✓ |
Client Build Manifests
vercel/next.js canary | acdlite/next.js segment-cache-ppr-header | Change | |
---|---|---|---|
_buildManifest.js gzip | 747 B | 746 B | N/A |
Overall change | 0 B | 0 B | ✓ |
Rendered Page Sizes
vercel/next.js canary | acdlite/next.js segment-cache-ppr-header | Change | |
---|---|---|---|
index.html gzip | 524 B | 522 B | N/A |
link.html gzip | 539 B | 537 B | N/A |
withRouter.html gzip | 520 B | 519 B | N/A |
Overall change | 0 B | 0 B | ✓ |
Edge SSR bundle Size
vercel/next.js canary | acdlite/next.js segment-cache-ppr-header | Change | |
---|---|---|---|
edge-ssr.js gzip | 128 kB | 128 kB | N/A |
page.js gzip | 203 kB | 203 kB | N/A |
Overall change | 0 B | 0 B | ✓ |
Middleware size
vercel/next.js canary | acdlite/next.js segment-cache-ppr-header | Change | |
---|---|---|---|
middleware-b..fest.js gzip | 671 B | 667 B | N/A |
middleware-r..fest.js gzip | 155 B | 156 B | N/A |
middleware.js gzip | 31.2 kB | 31.2 kB | N/A |
edge-runtime..pack.js gzip | 844 B | 844 B | ✓ |
Overall change | 844 B | 844 B | ✓ |
Next Runtimes
vercel/next.js canary | acdlite/next.js segment-cache-ppr-header | Change | |
---|---|---|---|
523-experime...dev.js gzip | 322 B | 322 B | ✓ |
523.runtime.dev.js gzip | 314 B | 314 B | ✓ |
app-page-exp...dev.js gzip | 323 kB | 323 kB | N/A |
app-page-exp..prod.js gzip | 127 kB | 127 kB | N/A |
app-page-tur..prod.js gzip | 140 kB | 140 kB | N/A |
app-page-tur..prod.js gzip | 135 kB | 135 kB | N/A |
app-page.run...dev.js gzip | 313 kB | 313 kB | N/A |
app-page.run..prod.js gzip | 123 kB | 123 kB | N/A |
app-route-ex...dev.js gzip | 37.3 kB | 37.3 kB | ✓ |
app-route-ex..prod.js gzip | 25.4 kB | 25.4 kB | ✓ |
app-route-tu..prod.js gzip | 25.4 kB | 25.4 kB | ✓ |
app-route-tu..prod.js gzip | 25.2 kB | 25.2 kB | ✓ |
app-route.ru...dev.js gzip | 38.9 kB | 38.9 kB | ✓ |
app-route.ru..prod.js gzip | 25.2 kB | 25.2 kB | ✓ |
pages-api-tu..prod.js gzip | 9.67 kB | 9.67 kB | ✓ |
pages-api.ru...dev.js gzip | 11.6 kB | 11.6 kB | ✓ |
pages-api.ru..prod.js gzip | 9.66 kB | 9.66 kB | ✓ |
pages-turbo...prod.js gzip | 21.7 kB | 21.7 kB | ✓ |
pages.runtim...dev.js gzip | 27.4 kB | 27.4 kB | ✓ |
pages.runtim..prod.js gzip | 21.7 kB | 21.7 kB | ✓ |
server.runti..prod.js gzip | 916 kB | 916 kB | N/A |
Overall change | 279 kB | 279 kB | ✓ |
build cache
vercel/next.js canary | acdlite/next.js segment-cache-ppr-header | Change | |
---|---|---|---|
0.pack gzip | 2.05 MB | 2.05 MB | N/A |
index.pack gzip | 72.4 kB | 72.1 kB | N/A |
Overall change | 0 B | 0 B | ✓ |
Diff details
Diff for edge-ssr.js
Diff too large to display
Diff for 1187-HASH.js
Diff too large to display
Diff for main-HASH.js
Diff too large to display
Diff for app-page-exp..ntime.dev.js
Diff too large to display
Diff for app-page-exp..time.prod.js
Diff too large to display
Diff for app-page-tur..time.prod.js
Diff too large to display
Diff for app-page-tur..time.prod.js
Diff too large to display
Diff for app-page.runtime.dev.js
Diff too large to display
Diff for app-page.runtime.prod.js
Diff too large to display
Diff for server.runtime.prod.js
Diff too large to display
a561377
to
b56bfd2
Compare
// to indicate that the response contains dynamic data, but here we're | ||
// only using it to indicate that the feature is enabled — the segment | ||
// response itself contains whether the data is dynamic. | ||
res.setHeader(NEXT_DID_POSTPONE_HEADER, '2') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this distinction feels very subtle but I suppose the end-goal will be to remove this case all together and not worth adding a new header for
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah just didn't feel worth adding another header
@@ -3044,10 +3044,19 @@ export default abstract class Server< | |||
} | |||
) | |||
|
|||
if (isPrefetchRSCRequest && typeof segmentPrefetchHeader === 'string') { | |||
if (isRoutePPREnabled && typeof segmentPrefetchHeader === 'string') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
woops, this always should have been gated on PPR right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It used to not have the check so that it would 404/204 if PPR was disabled (since why not, nothing should be issuing these requests and it's better than it falling through to a old-style prefetch) but then it turned out I need it to fallthrough to an old-style prefetch anyway.
// TODO: Replace with e2e test once the client part is implemented | ||
it('prefetch responds with 204 if PPR is disabled for a route', async () => { | ||
it('route tree prefetch falls through to pre-Segment Cache implementation if PPR is disabled for a route', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it('route tree prefetch falls through to pre-Segment Cache implementation if PPR is disabled for a route', async () => { | |
it('route tree prefetch falls through to per-segment cache implementation if PPR is disabled for a route', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that was actually the intended wording. I meant the "old" (before Segment Cache) implementation. I'll rephrase 😆
Follow-up to vercel#73715. Since PPR should always result in a cache hit for a prefetch (even in the worst case, there's a fallback cache entry), the only reason a route tree prefetch would not be found in the per-segment cache is because PPR is disabled. So we should just fallthrough to the old prefetching flow whenever PPR is disabled. But the client still needs some way to tell whether the response was served from the per-segment cache or by the old implementation. So I added an explicit response header to every per-segment prefetch. If the header is missing, the client can infer that the route does not support PPR.
b56bfd2
to
1b54cfd
Compare
Follow-up to #73715. Since PPR should always result in a cache hit for a prefetch (even in the worst case, there's a fallback cache entry), the only reason a route tree prefetch would not be found in the per-segment cache is because PPR is disabled.
So we should just fallthrough to the old prefetching flow whenever PPR is disabled.
But the client still needs some way to tell whether the response was served from the per-segment cache or by the old implementation.
So I added an explicit response header to every per-segment prefetch. If the header is missing, the client can infer that the route does not support PPR.