fix(app-router): propagate "use cache" tags to route-handler ISR entries (#1453)#1848
Conversation
|
/bigbonk review for issues |
commit: |
|
|
@james-elicx Bonk workflow was cancelled. View workflow run · To retry, trigger Bonk again. |
|
/bigbonk review for issues |
|
|
Review posted to PR #1848. SummaryI reviewed the tag-propagation changes and found one real correctness gap, confirmed empirically. What works (verified):
Bug found — nested The parent-scope tag bubbling lives only in I confirmed this with a scratch test (then removed it): the outer entry's stored tags came back Minor: The comment on The full review with the suggested fix and reproduction is posted at the PR comment link above. |
|
/bigbonk review for issues |
|
|
Review posted to PR #1848. SummaryThis PR has two commits — the original fix ( Previously-flagged nested-HIT bug — now fixed: Stale comment — reconciled: the docstring now accurately describes both HIT and MISS behavior. Verification (all local, green):
Notes (no action required): a harmless deduped double-push on the nested MISS path, and a consistent (pre-existing, non-regression) edge where a public cache nested inside a LGTM. |
Summary
Addresses #1453 (the route-handler revalidate sub-part); the other sub-parts
are deferred (see below).
A route handler whose body is produced by a
"use cache"function tagged withcacheTag()could not be invalidated viarevalidateTag()/revalidatePath().cacheTag()tags were attached only to the inner data cache entry and neverpropagated to the surrounding route-handler ISR entry, so on-demand
revalidation evicted the data cache entry but left the cached route-handler
response in place — the handler kept serving stale (
HIT) output.Fix
In the
"use cache"runtime (packages/vinext/src/shims/cache-runtime.ts),propagate a cache scope's tags up to the surrounding request's collected tags
(which feed the page / route-handler ISR entry), mirroring Next.js's
propagateCacheLifeAndTagsToRevalidateStore:tags.ctx.tags."use cache"scopes bubble their tags into the parent scope, so onlythe outermost scope writes onto the request tag list.
"use cache: private"tags stay isolated (private caches only nest inside private caches).
New helper
addCollectedRequestTags()infetch-cache.tsappends (deduped)into the same
currentRequestTagslist that taggedfetch()already uses.Test
tests/app-router-production-server.test.ts— new case:"route handler ISR: revalidateTag evicts a 'use cache' cacheTag()-tagged route
handler". Fixtures:
app/api/use-cache-tagged(a"use cache"-bodied GET taggeduse-cache-rh-tag, longrevalidateso only tag invalidation evicts it) andapp/api/revalidate-use-cache-rh-tag. Fails before the fix (post-revalidaterequest still
HITwith the old timestamp), passes after.Deferred (other #1453 sub-parts, out of scope here)
"use cache"evaluation for metadata route handlers / sitemap /robots (
sentinel=buildtime)."use cache: private"exposing cookies / searchParams."use cache"-bodied route handler with noexport const revalidatebeing implicitly ISR-cacheable from its resolved
cacheLife.These need broader/separate changes and are intentionally not bundled here to
keep this PR small.