@@ -109,6 +109,44 @@ export class NetlifyCacheHandler implements CacheHandler {
109
109
return restOfRouteValue
110
110
}
111
111
112
+ private captureCacheTags ( cacheValue : NetlifyIncrementalCacheValue | null , key : string ) {
113
+ if ( ! cacheValue ) {
114
+ return
115
+ }
116
+
117
+ const requestContext = getRequestContext ( )
118
+ // Bail if we can't get request context
119
+ if ( ! requestContext ) {
120
+ return
121
+ }
122
+
123
+ // Bail if we already have cache tags - `captureCacheTags()` is called on both `CacheHandler.get` and `CacheHandler.set`
124
+ // that's because `CacheHandler.get` might not have a cache value (cache miss or on-demand revalidation) in which case
125
+ // response is generated in blocking way and we need to capture cache tags from the cache value we are setting.
126
+ // If both `CacheHandler.get` and `CacheHandler.set` are called in the same request, we want to use cache tags from
127
+ // first `CacheHandler.get` and not from following `CacheHandler.set` as this is pattern for Stale-while-revalidate behavior
128
+ // and stale response is served while new one is generated.
129
+ if ( requestContext . responseCacheTags ) {
130
+ return
131
+ }
132
+
133
+ if (
134
+ cacheValue . kind === 'PAGE' ||
135
+ cacheValue . kind === 'APP_PAGE' ||
136
+ cacheValue . kind === 'ROUTE'
137
+ ) {
138
+ if ( cacheValue . headers ?. [ NEXT_CACHE_TAGS_HEADER ] ) {
139
+ const cacheTags = ( cacheValue . headers [ NEXT_CACHE_TAGS_HEADER ] as string ) . split ( ',' )
140
+ requestContext . responseCacheTags = cacheTags
141
+ } else if ( cacheValue . kind === 'PAGE' && typeof cacheValue . pageData === 'object' ) {
142
+ // pages router doesn't have cache tags headers in PAGE cache value
143
+ // so we need to generate appropriate cache tags for it
144
+ const cacheTags = [ `_N_T_${ key === '/index' ? '/' : key } ` ]
145
+ requestContext . responseCacheTags = cacheTags
146
+ }
147
+ }
148
+ }
149
+
112
150
private async injectEntryToPrerenderManifest (
113
151
key : string ,
114
152
revalidate : NetlifyCachedPageValue [ 'revalidate' ] ,
@@ -176,6 +214,7 @@ export class NetlifyCacheHandler implements CacheHandler {
176
214
}
177
215
178
216
this . captureResponseCacheLastModified ( blob , key , span )
217
+ this . captureCacheTags ( blob . value , key )
179
218
180
219
switch ( blob . value ?. kind ) {
181
220
case 'FETCH' :
@@ -273,6 +312,10 @@ export class NetlifyCacheHandler implements CacheHandler {
273
312
274
313
const value = this . transformToStorableObject ( data , context )
275
314
315
+ // if previous CacheHandler.get call returned null (page was either never rendered on was on-demand revalidated)
316
+ // and we didn't yet capture cache tags, we try to get cache tags from freshly produced cache value
317
+ this . captureCacheTags ( value , key )
318
+
276
319
await this . blobStore . setJSON ( blobKey , {
277
320
lastModified,
278
321
value,
0 commit comments