Skip to content

Commit

Permalink
fix: Falling back to header if cache tags are not given from fetched …
Browse files Browse the repository at this point in the history
…object (#557)


Co-authored-by: Dario Piotrowicz <[email protected]>
  • Loading branch information
susemeee and dario-piotrowicz authored Nov 26, 2023
1 parent dbe2c78 commit d7b34cc
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/empty-cups-pull.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cloudflare/next-on-pages': patch
---

Falling back to header if cache tags are not given from fetched CachedFetchValue object. The change was introduced from Next.js 13.5+.
15 changes: 15 additions & 0 deletions packages/next-on-pages/templates/_worker.js/utils/cache.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type { CacheAdaptor, IncrementalCacheValue } from '../../cache';
import { SUSPENSE_CACHE_URL } from '../../cache';

// https://github.com/vercel/next.js/blob/48a566bc/packages/next/src/server/lib/incremental-cache/fetch-cache.ts#L19
const CACHE_TAGS_HEADER = 'x-vercel-cache-tags';

/**
* Handles an internal request to the suspense cache.
*
Expand Down Expand Up @@ -50,6 +53,18 @@ export async function handleSuspenseCacheRequest(request: Request) {
case 'POST': {
// Update the value in the cache.
const body = await request.json<IncrementalCacheValue>();
// Falling back to the cache tags header for Next.js 13.5+
if (body.data.tags === undefined) {
body.tags ??=
request.headers
.get(CACHE_TAGS_HEADER)
?.split(',')
?.filter(Boolean) ?? [];
} else {
body.tags = body.data.tags;
delete body.data.tags;
}

await cache.set(cacheKey, body);

return new Response(null, { status: 200 });
Expand Down
12 changes: 9 additions & 3 deletions packages/next-on-pages/templates/cache/adaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class CacheAdaptor {
switch (newEntry.value?.kind) {
case 'FETCH': {
// Update the tags with the cache key.
const tags = newEntry.value.data.tags ?? [];
const tags = newEntry.value.tags ?? [];
await this.setTags(tags, { cacheKey: key });

getDerivedTags(tags).forEach(tag => revalidatedTags.delete(tag));
Expand Down Expand Up @@ -87,7 +87,9 @@ export class CacheAdaptor {
await this.loadTagsManifest();

// Check if the cache entry is stale or fresh based on the tags.
const tags = getDerivedTags(data.value.data.tags ?? []);
const tags = getDerivedTags(
data.value.tags ?? data.value.data.tags ?? [],
);
const isStale = tags.some(tag => {
// If a revalidation has been triggered, the current entry is stale.
if (revalidatedTags.has(tag)) return true;
Expand Down Expand Up @@ -196,16 +198,20 @@ export type TagsManifest = {
};
export type TagsManifestItem = { keys: string[]; revalidatedAt?: number };

// https://github.com/vercel/next.js/blob/fda1ecc/packages/next/src/server/response-cache/types.ts#L16
// https://github.com/vercel/next.js/blob/df4c2aa8/packages/next/src/server/response-cache/types.ts#L24
export type CachedFetchValue = {
kind: 'FETCH';
data: {
headers: { [k: string]: string };
body: string;
url: string;
status?: number;
// field used by older versions of Next.js (see: https://github.com/vercel/next.js/blob/fda1ecc/packages/next/src/server/response-cache/types.ts#L23)
tags?: string[];
};
// tags are only present with file-system-cache
// fetch cache stores tags outside of cache entry
tags?: string[];
revalidate: number;
};

Expand Down

0 comments on commit d7b34cc

Please sign in to comment.