@@ -15,7 +15,6 @@ import type {
1515} from '../../../shared/lib/app-router-types'
1616import { DEFAULT_SEGMENT_KEY } from '../../../shared/lib/segment'
1717import { matchSegment } from '../match-segments'
18- import { revalidateEntireCache } from '../segment-cache/cache'
1918import { createHrefFromUrl } from './create-href-from-url'
2019import { createRouterCacheKey } from './create-router-cache-key'
2120import {
@@ -111,6 +110,8 @@ export function startPPRNavigation(
111110 oldCacheNode : CacheNode ,
112111 oldRouterState : FlightRouterState ,
113112 newRouterState : FlightRouterState ,
113+ seedData : CacheNodeSeedData | null ,
114+ seedHead : HeadData | null ,
114115 prefetchData : CacheNodeSeedData | null ,
115116 prefetchHead : HeadData | null ,
116117 isPrefetchHeadPartial : boolean ,
@@ -125,6 +126,8 @@ export function startPPRNavigation(
125126 oldRouterState ,
126127 newRouterState ,
127128 false ,
129+ seedData ,
130+ seedHead ,
128131 prefetchData ,
129132 prefetchHead ,
130133 isPrefetchHeadPartial ,
@@ -137,18 +140,14 @@ export function startPPRNavigation(
137140export function startPPRRefresh (
138141 navigatedAt : number ,
139142 currentRouterState : FlightRouterState ,
140- currentNextUrl : string | null ,
143+ seedData : CacheNodeSeedData | null ,
144+ seedHead : HeadData | null ,
141145 accumulation : NavigationRequestAccumulation
142146) : Task | null {
143147 // A refresh is a special case of a navigation where all the dynamic data in
144148 // the page is re-fetched. There is no "shared layout" to consider because
145149 // the route hasn't changed.
146150
147- // TODO: Currently, all refreshes purge the prefetch cache. In the future,
148- // only client-side refreshes will have this behavior; the server-side
149- // `refresh` should send new data without purging the prefetch cache.
150- revalidateEntireCache ( currentNextUrl , currentRouterState )
151-
152151 // TODO: Currently refreshes do not read from the prefetch cache, as in the
153152 // pre-Segment Cache implementation. This will be added in a subsequent PR.
154153 const prefetchData = null
@@ -167,6 +166,8 @@ export function startPPRRefresh(
167166 navigatedAt ,
168167 currentRouterState ,
169168 existingCacheNode ,
169+ seedData ,
170+ seedHead ,
170171 prefetchData ,
171172 prefetchHead ,
172173 isPrefetchHeadPartial ,
@@ -182,6 +183,8 @@ function updateCacheNodeOnNavigation(
182183 oldRouterState : FlightRouterState ,
183184 newRouterState : FlightRouterState ,
184185 didFindRootLayout : boolean ,
186+ seedData : CacheNodeSeedData | null ,
187+ seedHead : HeadData | null ,
185188 prefetchData : CacheNodeSeedData | null ,
186189 prefetchHead : HeadData | null ,
187190 isPrefetchHeadPartial : boolean ,
@@ -192,6 +195,7 @@ function updateCacheNodeOnNavigation(
192195 // Diff the old and new trees to reuse the shared layouts.
193196 const oldRouterStateChildren = oldRouterState [ 1 ]
194197 const newRouterStateChildren = newRouterState [ 1 ]
198+ const seedDataChildren = seedData !== null ? seedData [ 1 ] : null
195199 const prefetchDataChildren = prefetchData !== null ? prefetchData [ 1 ] : null
196200
197201 if ( ! didFindRootLayout ) {
@@ -257,9 +261,13 @@ function updateCacheNodeOnNavigation(
257261 const oldRouterStateChild : FlightRouterState | void =
258262 oldRouterStateChildren [ parallelRouteKey ]
259263 const oldSegmentMapChild = oldParallelRoutes . get ( parallelRouteKey )
264+ const seedDataChild : CacheNodeSeedData | void | null =
265+ seedDataChildren !== null
266+ ? ( seedDataChildren [ parallelRouteKey ] ?? null )
267+ : null
260268 const prefetchDataChild : CacheNodeSeedData | void | null =
261269 prefetchDataChildren !== null
262- ? prefetchDataChildren [ parallelRouteKey ]
270+ ? ( prefetchDataChildren [ parallelRouteKey ] ?? null )
263271 : null
264272
265273 const newSegmentChild = newRouterStateChild [ 0 ]
@@ -299,7 +307,9 @@ function updateCacheNodeOnNavigation(
299307 newRouterStateChild ,
300308 oldCacheNodeChild ,
301309 didFindRootLayout ,
302- prefetchDataChild !== undefined ? prefetchDataChild : null ,
310+ seedDataChild ,
311+ seedHead ,
312+ prefetchDataChild ,
303313 prefetchHead ,
304314 isPrefetchHeadPartial ,
305315 newSegmentPathChild ,
@@ -340,7 +350,9 @@ function updateCacheNodeOnNavigation(
340350 newRouterStateChild ,
341351 oldCacheNodeChild ,
342352 didFindRootLayout ,
343- prefetchDataChild !== undefined ? prefetchDataChild : null ,
353+ seedDataChild ,
354+ seedHead ,
355+ prefetchDataChild ,
344356 prefetchHead ,
345357 isPrefetchHeadPartial ,
346358 newSegmentPathChild ,
@@ -364,6 +376,8 @@ function updateCacheNodeOnNavigation(
364376 oldRouterStateChild ,
365377 newRouterStateChild ,
366378 didFindRootLayout ,
379+ seedDataChild ,
380+ seedHead ,
367381 prefetchDataChild ,
368382 prefetchHead ,
369383 isPrefetchHeadPartial ,
@@ -380,7 +394,9 @@ function updateCacheNodeOnNavigation(
380394 newRouterStateChild ,
381395 oldCacheNodeChild ,
382396 didFindRootLayout ,
383- prefetchDataChild !== undefined ? prefetchDataChild : null ,
397+ seedDataChild ,
398+ seedHead ,
399+ prefetchDataChild ,
384400 prefetchHead ,
385401 isPrefetchHeadPartial ,
386402 newSegmentPathChild ,
@@ -395,7 +411,9 @@ function updateCacheNodeOnNavigation(
395411 newRouterStateChild ,
396412 oldCacheNodeChild ,
397413 didFindRootLayout ,
398- prefetchDataChild !== undefined ? prefetchDataChild : null ,
414+ seedDataChild ,
415+ seedHead ,
416+ prefetchDataChild ,
399417 prefetchHead ,
400418 isPrefetchHeadPartial ,
401419 newSegmentPathChild ,
@@ -495,6 +513,8 @@ function beginRenderingNewRouteTree(
495513 newRouterState : FlightRouterState ,
496514 existingCacheNode : CacheNode | void ,
497515 didFindRootLayout : boolean ,
516+ seedData : CacheNodeSeedData | null ,
517+ seedHead : HeadData | null ,
498518 prefetchData : CacheNodeSeedData | null ,
499519 possiblyPartialPrefetchHead : HeadData | null ,
500520 isPrefetchHeadPartial : boolean ,
@@ -537,6 +557,8 @@ function beginRenderingNewRouteTree(
537557 navigatedAt ,
538558 newRouterState ,
539559 existingCacheNode ,
560+ seedData ,
561+ seedHead ,
540562 prefetchData ,
541563 possiblyPartialPrefetchHead ,
542564 isPrefetchHeadPartial ,
@@ -551,6 +573,8 @@ function createCacheNodeOnNavigation(
551573 navigatedAt : number ,
552574 routerState : FlightRouterState ,
553575 existingCacheNode : CacheNode | void ,
576+ seedData : CacheNodeSeedData | null ,
577+ seedHead : HeadData | null ,
554578 prefetchData : CacheNodeSeedData | null ,
555579 possiblyPartialPrefetchHead : HeadData | null ,
556580 isPrefetchHeadPartial : boolean ,
@@ -597,7 +621,22 @@ function createCacheNodeOnNavigation(
597621 let loading : LoadingModuleData | Promise < LoadingModuleData >
598622 let head : HeadData | null
599623 let cacheNodeNavigatedAt : number
600- if (
624+ if ( seedData !== null ) {
625+ // When navigating in response to a Server Action, the server may send back
626+ // RSC data alongside the action body response. If so, we can use this data
627+ // directly without consulting the client cache and without triggering a new
628+ // request from the server.
629+ // TODO: Since Server Action responses are streaming, we may not be able to
630+ // render the UI immediately, even though we already have a reference to it
631+ // here. It's worth checking the prefetch cache to see if there's a partial
632+ // state we can show in the meantime. We'll implement this once this module
633+ // is updated to access the prefetch cache directly, instead of passing it
634+ // down via the CacheNodeSeedData type.
635+ rsc = seedData [ 0 ]
636+ loading = seedData [ 2 ]
637+ head = isLeafSegment ? seedHead : null
638+ cacheNodeNavigatedAt = navigatedAt
639+ } else if (
601640 existingCacheNode !== undefined &&
602641 // DYNAMIC_STALETIME_MS defaults to 0, but it can be increased using
603642 // the experimental.staleTimes.dynamic config. When set, we'll avoid
@@ -673,6 +712,7 @@ function createCacheNodeOnNavigation(
673712 // new one from the server. Keep traversing down the tree until we reach
674713 // something that requires a dynamic request.
675714 const prefetchDataChildren = prefetchData !== null ? prefetchData [ 1 ] : null
715+ const seedDataChildren = seedData !== null ? seedData [ 1 ] : null
676716 const taskChildren = new Map ( )
677717 const existingCacheNodeChildren =
678718 existingCacheNode !== undefined ? existingCacheNode . parallelRoutes : null
@@ -693,9 +733,13 @@ function createCacheNodeOnNavigation(
693733 for ( let parallelRouteKey in routerStateChildren ) {
694734 const routerStateChild : FlightRouterState =
695735 routerStateChildren [ parallelRouteKey ]
696- const prefetchDataChild : CacheNodeSeedData | void | null =
736+ const seedDataChild : CacheNodeSeedData | null =
737+ seedDataChildren !== null
738+ ? ( seedDataChildren [ parallelRouteKey ] ?? null )
739+ : null
740+ const prefetchDataChild : CacheNodeSeedData | null =
697741 prefetchDataChildren !== null
698- ? prefetchDataChildren [ parallelRouteKey ]
742+ ? ( prefetchDataChildren [ parallelRouteKey ] ?? null )
699743 : null
700744 const existingSegmentMapChild =
701745 existingCacheNodeChildren !== null
@@ -719,6 +763,8 @@ function createCacheNodeOnNavigation(
719763 navigatedAt ,
720764 routerStateChild ,
721765 existingCacheNodeChild ,
766+ seedDataChild ,
767+ seedHead ,
722768 prefetchDataChild ,
723769 possiblyPartialPrefetchHead ,
724770 isPrefetchHeadPartial ,
0 commit comments