UNPKG

next

Version:

The React Framework

82 lines (81 loc) • 4.1 kB
import { PrefetchKind } from './router-reducer/router-reducer-types'; import { createPrefetchURL } from './app-router-utils'; import { getCurrentAppRouterState } from './app-router-instance'; import { isJavaScriptURLString } from '../lib/javascript-url'; import { createCacheKey } from './segment-cache/cache-key'; import { schedulePrefetchTask } from './segment-cache/scheduler'; import { FetchStrategy, PrefetchPriority } from './segment-cache/types'; /** * The public prefetch operation, exposed through `router.prefetch`. Converts * the public options into a fetch strategy, reads the current router state, * and drives the Segment Cache. * * Unlike the old implementation, the Segment Cache doesn't store its data in * the router reducer state; it writes into a global mutable cache. So we * don't need to dispatch an action. */ export function prefetchRoute(href, options) { if (isJavaScriptURLString(href)) { throw new Error('Next.js has blocked a javascript: URL as a security precaution.'); } const state = getCurrentAppRouterState(); if (state === null) { throw new Error('Internal Next.js error: Router action dispatched before initialization.'); } const prefetchKind = options?.kind ?? PrefetchKind.AUTO; // We don't currently offer a way to issue a runtime prefetch via `router.prefetch()`. // This will be possible when we update its API to not take a PrefetchKind. let fetchStrategy; switch(prefetchKind){ case PrefetchKind.AUTO: { // We default to PPR. We'll discover whether or not the route supports it with the initial prefetch. fetchStrategy = FetchStrategy.PPR; break; } case PrefetchKind.FULL: { fetchStrategy = FetchStrategy.Full; break; } default: { prefetchKind; // Despite typescript thinking that this can't happen, // we might get an unexpected value from user code. // We don't know what they want, but we know they want a prefetch, // so use the default. fetchStrategy = FetchStrategy.PPR; } } prefetch(href, state.nextUrl, state.root, fetchStrategy, options?.onInvalidate ?? null); } /** * Entrypoint for prefetching a URL into the Segment Cache. * @param href - The URL to prefetch. Typically this will come from a <Link>, * or router.prefetch. It must be validated before we attempt to prefetch it. * @param nextUrl - A special header used by the server for interception routes. * Roughly corresponds to the current URL. * @param renderTreeAtTimeOfPrefetch - The active render tree and head, and * their vary paths. * @param fetchStrategy - Whether to prefetch dynamic data, in addition to * static data. This is used by `<Link prefetch={true}>`. * @param onInvalidate - A callback that will be called when the prefetch cache * When called, it signals to the listener that the data associated with the * prefetch may have been invalidated from the cache. This is not a live * subscription — it's called at most once per `prefetch` call. The only * supported use case is to trigger a new prefetch inside the listener, if * desired. It also may be called even in cases where the associated data is * still cached. Prefetching is a poll-based (pull) operation, not an event- * based (push) one. Rather than subscribe to specific cache entries, you * occasionally poll the prefetch cache to check if anything is missing. */ export function prefetch(href, nextUrl, renderTreeAtTimeOfPrefetch, fetchStrategy, onInvalidate) { const url = createPrefetchURL(href); if (url === null) { // This href should not be prefetched. return; } const cacheKey = createCacheKey(url.href, nextUrl); schedulePrefetchTask(cacheKey, renderTreeAtTimeOfPrefetch, fetchStrategy, PrefetchPriority.Default, onInvalidate, null // navigationLockPrefetch ); } //# sourceMappingURL=prefetch.js.map