Commit graph

7 commits

Author SHA1 Message Date
Zack Tanner
d371f648d2
Renew prefetch cache entry after update from server (#61573)
### What
When a prefetch cache entry becomes "stale", it'll remain stale until
eventually it gets evicted. However during that stale window, the cache
is never revalidated, and so instant navigations stop working and data
is fetched from origin every navigation.

### Why
The `lastUsedTime` entry on the prefetch cache is currently only updated
after the first read. Once it becomes stale, `applyFlightData`'s
recursive functions will see that there is no longer a reusable prefetch
cache entry, and will trigger a lazy fetch of the new data on every
subsequent navigation.

### How
This updates prefetch cache handling to always ensure we’re using a
fresh or reusable prefetch cache entry. This means that stale prefetch
entries will be refreshed on a navigation event. As a result of this,
I’ve had to disable one of our tests that relies on this stale cache
behavior. It’s not ideal that we’re blocked on the loading boundary when
fetching child segment data—ideally we can refactor this to cache the
loading component in the CacheNode and copy it over on navigations,
similar to how ‘head’ is handled. I’ll work on this in a separate PR.

Note: The new client cache test for this is disabled in PPR for the same
reason as the other tests: auto prefetching with PPR navigations is
currently loading fresh data rather than reusing the prefetch cache.


Fixes #58969
Fixes #58723
Closes NEXT-1904
2024-02-20 09:07:18 -08:00
Wyatt Johnson
252d9cf453
Navigation Signals in PPR (#60450)
### What

This adds support for navigation signals like `notFound()` and
`redirect(url)` when Partial Prerendering has been enabled.

### Why

Navigation API's like `notFound()` and `redirect(url)` throw errors in
order to interrupt the rendering of components. When a page both invokes
API's that cause the render to be marked as dynamic (like
`unstable_noStore()`) and also a navigation API, these errors may race
to the end. In the case where the navigation error does not beat out the
error emitted by dynamic API's will still trigger the detection warning
that's present to warn you about situations where you may have
accidentally caught the error.

### How

This resolves this issue by explicitly checking for navigation signals
(errors) thrown during the render, and not displaying the "caught
dynamic API" error and console warning.

Closes NEXT-2037
2024-02-06 12:25:50 -07:00
Zack Tanner
db468e399b
ppr: ensure the router state tree is provided for interception routes (#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](fbfd7b5f81/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](fbfd7b5f81/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
2024-01-24 10:20:47 -08:00
Zack Tanner
1481b2649f
Fix TypeError when using params in RootLayout with parallel routes (#60401)
### What?
When accessing `params` on a `RootLayout`, while also using parallel
routes, two potential errors would occur:
- A `Warning: React.createElement: type is invalid` error when
attempting to render a `NotFound` component that doesn't exist
- A `TypeError: Cannot read properties of undefined` error when
attempting to access params in the root layout.

### Why?
`createComponentTree` will render a duplicate `RootLayout` (to ensure
the `notFound()` fallback in unmatched parallel slots have a
`NotFoundBoundary` to catch them) but it currently doesn't ensure a
`NotFound` component exists nor does it forward `params` to the layout.

### How?
This forwards the params to the `RootLayout` and doesn't render a
`NotFoundComponent` if one doesn't exist. This replaces a few `any`
types with more sound types that would have helped catch these mistakes.
There's still a lot more typing that needs to be done (left a comment
below with some additional details) but I opted to make the minimal
changes related to this issue.

Longer term we should remove this duplicate `RootLayout` (see #60220)
which will require special UI to show unmatched slots (similar to the
error overlay, but less harsh)

Closes NEXT-1909
Fixes #59711
2024-01-09 07:06:24 -08:00
Wyatt Johnson
2da04af2e8
Partial Pre Rendering Headers (#59447)
This fixes some of headers (and adds associated tests) for pages when
PPR is enabled. Namely, the `Cache-Control` headers are now returning
correctly, reflecting the non-cachability of some requests:

- Requests that postpone (dynamic data is streamed after the initial
static shell is streamed)
- Requests for the Dynamic RSC payload

Additionally, the `X-NextJS-Cache` header has been updated for better
support for PPR:

- Requests that postpone no longer return this header as it doesn't
reflect the cache state of the request (because it streams)
- Requests for the Prefetch RSC now returns the correct cache headers
depending on the segment and pre-postpone state

This also enables the other pathnames in the test suites 🙌🏻 

Closes NEXT-1840
2023-12-14 13:14:06 -07:00
Wyatt Johnson
eab1fe8397
Enable PPR for dynamic = "force-dynamic" (#58779)
This makes some critical modifications to the app render pipeline when
PPR has been enabled for pages with segments defining:

```js
export const dynamic = "force-dynamic"
```

Importantly, it no longer modifies the revalidation time to zero for
those pages, and now falls back to the provided default revalidation
time. When static render occurs, if the page being rendered has a
segment config defining `dynamic === "force-dynamic"`, then it will
postpone at the root of the component tree. This ensures that no render
code is executed for the page, as the entirety of the tree will have
postponed. This fixes the bug where the flight prefetch wasn't generated
correctly as well.
2023-12-06 01:10:00 +00:00
Zack Tanner
809164d776
Enable PPR tests for test suites (#59030)
Cherry-picks #58708 without the dependency on https://github.com/vercel/next.js/pull/58779

Co-authored-by: Wyatt Johnson <633002+wyattjoh@users.noreply.github.com>
2023-11-29 03:22:45 +00:00