Skip to content

Commit

Permalink
ppr: ensure the router state tree is provided for interception routes (
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
ztanner authored Jan 24, 2024
1 parent a18792b commit db468e3
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 15 deletions.
20 changes: 14 additions & 6 deletions packages/next/src/server/app-render/app-render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ import { DetachedPromise } from '../../lib/detached-promise'
import { isDynamicServerError } from '../../client/components/hooks-server-context'
import { useFlightResponse } from './use-flight-response'
import { isStaticGenBailoutError } from '../../client/components/static-generation-bailout'
import { isInterceptionRouteAppPath } from '../future/helpers/interception-routes'

export type GetDynamicParamFromSegment = (
// [slug] / [[slug]] / [...slug]
Expand Down Expand Up @@ -721,12 +722,19 @@ async function renderToHTMLOrFlightImpl(
/**
* Router state provided from the client-side router. Used to handle rendering from the common layout down.
*/
let providedFlightRouterState =
isRSCRequest && (!isPrefetchRSCRequest || !renderOpts.experimental.ppr)
? parseAndValidateFlightRouterState(
req.headers[NEXT_ROUTER_STATE_TREE.toLowerCase()]
)
: undefined

const shouldProvideFlightRouterState =
isRSCRequest &&
(!isPrefetchRSCRequest ||
!renderOpts.experimental.ppr ||
// interception routes currently depend on the flight router state to extract dynamic params
isInterceptionRouteAppPath(pagePath))

let providedFlightRouterState = shouldProvideFlightRouterState
? parseAndValidateFlightRouterState(
req.headers[NEXT_ROUTER_STATE_TREE.toLowerCase()]
)
: undefined

/**
* The metadata items array created in next-app-loader with all relevant information
Expand Down
10 changes: 1 addition & 9 deletions test/ppr-tests-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@
"headers-static-bailout it provides a helpful link in case static generation bailout is uncaught"
]
},
"test/e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts": {
"failed": [
"parallel-routes-and-interception route intercepting should render modal when paired with parallel routes",
"parallel-routes-and-interception route intercepting should support intercepting local dynamic sibling routes"
]
},
"test/e2e/app-dir/error-boundary-navigation/override-node-env.test.ts": {
"failed": [
"app dir - not found navigation - with overridden node env should be able to navigate to other page from root not-found page"
Expand Down Expand Up @@ -81,9 +75,7 @@
"test/e2e/app-dir/ppr/**/*",
"test/e2e/app-dir/ppr-*/**/*",
"test/e2e/app-dir/app-prefetch*/**/*",
"test/e2e/app-dir/interception-middleware-rewrite/interception-middleware-rewrite.test.ts",
"test/e2e/app-dir/searchparams-static-bailout/searchparams-static-bailout.test.ts",
"test/e2e/app-dir/parallel-route-not-found-params/parallel-route-not-found-params.test.ts"
"test/e2e/app-dir/searchparams-static-bailout/searchparams-static-bailout.test.ts"
]
}
}

0 comments on commit db468e3

Please sign in to comment.