UNPKG

next

Version:

The React Framework

154 lines (153 loc) 9.13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); 0 && (module.exports = { createFlightRouterStateFromLoaderTree: null, createRouteTreePrefetch: null }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: all[name] }); } _export(exports, { createFlightRouterStateFromLoaderTree: function() { return createFlightRouterStateFromLoaderTree; }, createRouteTreePrefetch: function() { return createRouteTreePrefetch; } }); const _approutertypes = require("../../shared/lib/app-router-types"); const _segment = require("../../shared/lib/segment"); async function createFlightRouterStateFromLoaderTreeImpl(loaderTree, hintTree, prefetchInliningEnabled, cacheComponents, partialPrefetching, isStaticGeneration, isBuildTimePrerendering, getDynamicParamFromSegment, searchParams, didFindRootLayout) { const [segment, parallelRoutes, { layout, loading, page }] = loaderTree; const dynamicParam = getDynamicParamFromSegment(loaderTree); const treeSegment = dynamicParam ? dynamicParam.treeSegment : segment; const segmentTree = [ (0, _segment.addSearchParamsIfPageSegment)(treeSegment, searchParams), {} ]; // Load the layout or page module to check its instant and prefetch // configs. When a segment doesn't export prefetch, it defaults to // 'partial' if the app has opted into partial prefetching globally via the // `partialPrefetching` config in next.config.js. const mod = layout ? await layout[0]() : page ? await page[0]() : undefined; const instantConfig = mod ? mod.instant : undefined; const prefetchConfig = (mod ? mod.prefetch : undefined) ?? (partialPrefetching === 'unstable_eager' ? 'unstable_eager' : partialPrefetching ? 'partial' : undefined); let prefetchHints = 0; // Union in the precomputed build-time hints (e.g. segment inlining // decisions) if available. When hints are not available (e.g. dev mode or // if prefetch-hints.json was not generated), we fall through and still // compute the other hints below. In the future this should be a build // error, but for now we gracefully degrade. // // TODO: Move more of the hints computation (IsRootLayoutOrAbove, instant config, // loading boundary detection) into the build-time measurement step in // collectPrefetchHints, so this function only needs to union the // precomputed bitmask rather than re-derive hints on every render. if (hintTree !== null) { prefetchHints |= hintTree.hints; } else if (prefetchInliningEnabled) { if (isBuildTimePrerendering) { // Prefetch inlining is enabled but no hint tree was provided during a // build-time prerender. This happens for the initial RSC payload // generated before collectPrefetchHints has run. Mark so the client // can expire the route cache entry and re-fetch the tree with correct // hints. prefetchHints |= _approutertypes.PrefetchHint.InliningHintsStale; } else if (isStaticGeneration) { // TODO(#91407): Temporary mitigation: when hints are missing during // runtime static generation, fall back to treating every segment as // unprefetchable. This currently happens for routes with // `instant = false` at the root segment, which causes the prerender // to run per-request instead of being cached, and the prefetch hints // manifest is not available. // // Once that bug is fixed, this branch should become an error again — // hints should always be available from the manifest during ISR. prefetchHints |= _approutertypes.PrefetchHint.PrefetchDisabled; } else if (cacheComponents) { // At runtime with no hint tree, this is a fully dynamic route with no // manifest entry. Treat every segment as unprefetchable. Do NOT set // InliningHintsStale — that would cause the client to enter an // infinite re-fetch loop trying to get hints that will never exist. prefetchHints |= _approutertypes.PrefetchHint.PrefetchDisabled; } else { // Without cacheComponents, dynamic pages have no static shell so // hints are never computed. Don't disable prefetching — just skip // the inlining hint system and let prefetching proceed normally. } } // Mark every segment at or above the root layout (i.e. until we descend past // the first segment that has a layout). if (!didFindRootLayout) { prefetchHints |= _approutertypes.PrefetchHint.IsRootLayoutOrAbove; if (typeof layout !== 'undefined') { // This segment is the root layout; its descendants are below it. didFindRootLayout = true; } } if (instantConfig === false) { // The segment explicitly opts out of Partial Prefetching. We don't change // the prefetch behavior, but we record it so the dev-time // `<Link prefetch={true}>` warning can be suppressed for this route. prefetchHints |= _approutertypes.PrefetchHint.SubtreeHasInstantFalse; } if (prefetchConfig === 'partial') { prefetchHints |= _approutertypes.PrefetchHint.SubtreeHasPartialPrefetching; } else if (prefetchConfig === 'unstable_eager') { // Like 'partial' (uses the PPR fetch strategy) but also marks the segment // as eager, so App Shells keeps prefetching it instead of relying on the // shared app shell. prefetchHints |= _approutertypes.PrefetchHint.SubtreeHasPartialPrefetching | _approutertypes.PrefetchHint.SubtreeHasEagerPrefetch; } else if (prefetchConfig === 'force-disabled') { prefetchHints |= _approutertypes.PrefetchHint.PrefetchDisabled; } // Mark the segment as "eager" unless its effective prefetch strategy is // 'partial'. 'unstable_eager' already set the bit above. Under App Shells, // a subtree with no eager segment skips its Speculative prefetch and relies // on the shared app shell instead. if (prefetchConfig !== 'partial') { prefetchHints |= _approutertypes.PrefetchHint.SubtreeHasEagerPrefetch; } // Check if this segment has a loading boundary if (loading) { prefetchHints |= _approutertypes.PrefetchHint.SegmentHasLoadingBoundary; } const children = {}; for(const parallelRouteKey in parallelRoutes){ var _hintTree_slots; // Look up the child hint node by parallel route key, traversing the // hint tree in parallel with the loader tree. const childHintNode = (hintTree == null ? void 0 : (_hintTree_slots = hintTree.slots) == null ? void 0 : _hintTree_slots[parallelRouteKey]) ?? null; const child = await createFlightRouterStateFromLoaderTreeImpl(parallelRoutes[parallelRouteKey], childHintNode, prefetchInliningEnabled, cacheComponents, partialPrefetching, isStaticGeneration, isBuildTimePrerendering, getDynamicParamFromSegment, searchParams, didFindRootLayout); // Propagate subtree flags from children if (child[4] !== undefined) { prefetchHints = (0, _approutertypes.propagateSubtreeBits)(prefetchHints, child[4]); } children[parallelRouteKey] = child; } segmentTree[1] = children; if (prefetchHints !== 0) { segmentTree[4] = prefetchHints; } return segmentTree; } async function createFlightRouterStateFromLoaderTree(loaderTree, hintTree, prefetchInliningEnabled, cacheComponents, partialPrefetching, isStaticGeneration, isBuildTimePrerendering, getDynamicParamFromSegment, searchParams, // Whether a root layout was already found above this loader tree slice, so a // slice that starts below the root layout doesn't mark a sub-layout as the // root layout. didFindRootLayout = false) { return createFlightRouterStateFromLoaderTreeImpl(loaderTree, hintTree, prefetchInliningEnabled, cacheComponents, partialPrefetching, isStaticGeneration, isBuildTimePrerendering, getDynamicParamFromSegment, searchParams, didFindRootLayout); } async function createRouteTreePrefetch(loaderTree, hintTree, prefetchInliningEnabled, cacheComponents, partialPrefetching, isStaticGeneration, isBuildTimePrerendering, getDynamicParamFromSegment, // See note on createFlightRouterStateFromLoaderTree's didFindRootLayout. didFindRootLayout = false) { // Search params should not be added to page segment's cache key during a // route tree prefetch request, because they do not affect the structure of // the route. The client cache has its own logic to handle search params. const searchParams = {}; return createFlightRouterStateFromLoaderTreeImpl(loaderTree, hintTree, prefetchInliningEnabled, cacheComponents, partialPrefetching, isStaticGeneration, isBuildTimePrerendering, getDynamicParamFromSegment, searchParams, didFindRootLayout); } //# sourceMappingURL=create-flight-router-state-from-loader-tree.js.map