Files
Andrew ClarkandGitHub 0344392f8e [Segment Cache] Initial implementation (#72875)
Based on:

- #72874 
- #72890 
- #72872 

---

This adds an initial implementation of the client Segment Cache, behind
the experimental `clientSegmentCache` flag. (Note: It is not anywhere
close to being ready for production use. It will take a while for it to
reach parity with the existing implementation.)

I've discussed the motivation in previous PRs, but I'll share a brief
summary here again:

The client Segment Cache is a rewrite of App Router's client caching
implementation, designed with PPR and "use cache" in mind. Its main
distinguishing feature from the current implementation is that it
fetches/caches/expires data per route segment, rather than per full URL.
An example of what this means in practical terms is that shared layouts
are deduplicated in the cache, resulting in less bandwidth. There are
other benefits we have in mind but that's the starting point.

I've tried to extract the work here into reasonably-sized commits (many
of which have already landed) but this one here is sorta unavoidably
large. Here are the main pieces:

-
[segment-cache/cache.ts](https://github.com/acdlite/next.js/blob/initial-implementation-client-segment-cache/packages/next/src/client/components/segment-cache/cache.ts):
This module is where the cache entries are maintained in memory. An
important design principle is that you must be able to read from the
cache synchronously without awaiting any promises. We avoid the use of
async/await wherever possible; instead, async tasks write their results
directly into the cache. This also helps to avoid race conditions.

Currently there's no eviction policy other than stale time, but
eventually we'll use an LRU for memory management.

-
[segment-cache/scheduler.ts](https://github.com/acdlite/next.js/blob/initial-implementation-client-segment-cache/packages/next/src/client/components/segment-cache/scheduler.ts):
This module is primarily a task scheduler. It's also used to manage
network bandwidth. The design is inspired by React Suspense and Rust
Futures — tasks are pull-based, not push-based. The backing data
structure is a MinHeap/PriorityQueue, to support efficient
reprioritization of tasks.

-
[segment-cache/navigation.ts](https://github.com/acdlite/next.js/blob/initial-implementation-client-segment-cache/packages/next/src/client/components/segment-cache/navigation.ts):
This module is responsible for creating a snapshot of the cache at the
time of a navigation. Right now it's mostly a bunch of glue code to
interop with the data structures used by the rest of the App Router,
like CacheNodeSeedData and FlightRouterState. The long term plan is to
move everything to using the Segment Cache and refactoring those data
structures.

Additional explanations are provided inline.
2024-11-20 15:23:00 -05:00

27 lines
558 B
TypeScript

import { Suspense } from 'react'
import { connection } from 'next/server'
async function DynamicText({ text }) {
await connection()
return text
}
export function StreamingText({
static: staticText,
dynamic,
}: {
static: string
dynamic: string
}) {
return (
<div>
<div data-streaming-text-static={staticText}>{staticText}</div>
<Suspense fallback={<div>Loading... [{dynamic}]</div>}>
<div data-streaming-text-dynamic={dynamic}>
<DynamicText text={dynamic} />
</div>
</Suspense>
</div>
)
}