Skip to content

Commit db468e3

Browse files
authored
ppr: ensure the router state tree is provided for interception routes (vercel#61059)
### What? Interception routes on dynamic paths don't currently work when PPR is turned on, and instead trigger an MPA navigation to the full route. ### Why? Route interception relies on the `Next-Flight-Router-State` header to extract the dynamic params necessary to convert something like `[locale]`, which would correspond with a URL of `/en`, to something like `["locale", "en", "d"]`. (See [this function](https://github.com/vercel/next.js/blob/fbfd7b5f81397fc6500e3c3a25bfd6627e9abb8f/packages/next/src/server/app-render/app-render.tsx#L129-L137) for more info). When PPR is turned on, we currently ignore this request header and don't provide it to the functions that render the component tree. Without the flight router state, this function bails out and instead will leave the segment key as `[locale]`. When the client router goes to diff the current tree on the client with the response from the server, it will detect a mismatch between the current segment and the incoming segment, and trigger an MPA navigation in [this block](https://github.com/vercel/next.js/blob/fbfd7b5f81397fc6500e3c3a25bfd6627e9abb8f/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts#L414-L416). ### How? This special-cases interception routes to not strip this header. Closes NEXT-2215
1 parent a18792b commit db468e3

File tree

2 files changed

+15
-15
lines changed

2 files changed

+15
-15
lines changed

packages/next/src/server/app-render/app-render.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ import { DetachedPromise } from '../../lib/detached-promise'
8080
import { isDynamicServerError } from '../../client/components/hooks-server-context'
8181
import { useFlightResponse } from './use-flight-response'
8282
import { isStaticGenBailoutError } from '../../client/components/static-generation-bailout'
83+
import { isInterceptionRouteAppPath } from '../future/helpers/interception-routes'
8384

8485
export type GetDynamicParamFromSegment = (
8586
// [slug] / [[slug]] / [...slug]
@@ -721,12 +722,19 @@ async function renderToHTMLOrFlightImpl(
721722
/**
722723
* Router state provided from the client-side router. Used to handle rendering from the common layout down.
723724
*/
724-
let providedFlightRouterState =
725-
isRSCRequest && (!isPrefetchRSCRequest || !renderOpts.experimental.ppr)
726-
? parseAndValidateFlightRouterState(
727-
req.headers[NEXT_ROUTER_STATE_TREE.toLowerCase()]
728-
)
729-
: undefined
725+
726+
const shouldProvideFlightRouterState =
727+
isRSCRequest &&
728+
(!isPrefetchRSCRequest ||
729+
!renderOpts.experimental.ppr ||
730+
// interception routes currently depend on the flight router state to extract dynamic params
731+
isInterceptionRouteAppPath(pagePath))
732+
733+
let providedFlightRouterState = shouldProvideFlightRouterState
734+
? parseAndValidateFlightRouterState(
735+
req.headers[NEXT_ROUTER_STATE_TREE.toLowerCase()]
736+
)
737+
: undefined
730738

731739
/**
732740
* The metadata items array created in next-app-loader with all relevant information

test/ppr-tests-manifest.json

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,6 @@
2020
"headers-static-bailout it provides a helpful link in case static generation bailout is uncaught"
2121
]
2222
},
23-
"test/e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts": {
24-
"failed": [
25-
"parallel-routes-and-interception route intercepting should render modal when paired with parallel routes",
26-
"parallel-routes-and-interception route intercepting should support intercepting local dynamic sibling routes"
27-
]
28-
},
2923
"test/e2e/app-dir/error-boundary-navigation/override-node-env.test.ts": {
3024
"failed": [
3125
"app dir - not found navigation - with overridden node env should be able to navigate to other page from root not-found page"
@@ -81,9 +75,7 @@
8175
"test/e2e/app-dir/ppr/**/*",
8276
"test/e2e/app-dir/ppr-*/**/*",
8377
"test/e2e/app-dir/app-prefetch*/**/*",
84-
"test/e2e/app-dir/interception-middleware-rewrite/interception-middleware-rewrite.test.ts",
85-
"test/e2e/app-dir/searchparams-static-bailout/searchparams-static-bailout.test.ts",
86-
"test/e2e/app-dir/parallel-route-not-found-params/parallel-route-not-found-params.test.ts"
78+
"test/e2e/app-dir/searchparams-static-bailout/searchparams-static-bailout.test.ts"
8779
]
8880
}
8981
}

0 commit comments

Comments
 (0)