Add router.experimental_prepare() (#101050)
Adds `experimental_prepare(href)` to the router returned by
`useRouter()`. It starts a navigation that goes through all the same
steps as a regular one, including the dynamic request, but doesn't
update the router. The response writes into the same local cache used by
back/forward navigations.
The returned handle has `push()` and `replace()`. Committing performs a
regular navigation, except it can read bfcache entries written since the
prepare began, regardless of stale time. If the prepared request is
still in flight, the commit reuses it instead of starting a new one.
The intended use is to prepare on pointerdown and commit on click, which
starts the dynamic request earlier. We may build this into Link
eventually; the low-level API lets people try it out first.
Semantics:
- If you don't commit, nothing else happens. The data stays in the
bfcache, so a history traversal to an overlapping segment may observe
it. This is intentional. The contract of the API is that you are OK with
the navigation showing data that's as stale as when the preparation
began.
- Prepared data doesn't expire. Committing much later still reuses it;
the caller is responsible for not holding on to a handle too long.
- A refresh or server action between prepare and commit invalidates the
prepared data, the same way it invalidates the bfcache.
- A handle can only be committed once. Later calls are a no-op, with a
dev-only warning.
- A regular navigation to the same route doesn't reuse prepared data;
only the commit ignores stale time.
Gated behind `experimental.prepareNavigation`.