Skip to content

Commit ae2d5d5

Browse files
committed
patch use cache for ISR
1 parent 4012f4f commit ae2d5d5

File tree

5 files changed

+136
-4
lines changed

5 files changed

+136
-4
lines changed

packages/open-next/src/build/createServerBundle.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
patchFetchCacheSetMissingWaitUntil,
2929
patchNextServer,
3030
patchUnstableCacheForISR,
31+
patchUseCacheForISR,
3132
} from "./patch/patches/index.js";
3233

3334
interface CodeCustomization {
@@ -212,6 +213,7 @@ async function generateBundle(
212213
patchNextServer,
213214
patchEnvVars,
214215
patchBackgroundRevalidation,
216+
patchUseCacheForISR,
215217
...additionalCodePatches,
216218
]);
217219

packages/open-next/src/build/patch/patches/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export { patchNextServer } from "./patchNextServer.js";
33
export {
44
patchFetchCacheForISR,
55
patchUnstableCacheForISR,
6+
patchUseCacheForISR,
67
} from "./patchFetchCacheISR.js";
78
export { patchFetchCacheSetMissingWaitUntil } from "./patchFetchCacheWaitUntil.js";
89
export { patchBackgroundRevalidation } from "./patchBackgroundRevalidation.js";

packages/open-next/src/build/patch/patches/patchFetchCacheISR.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,29 @@ fix:
7878
($STORE_OR_CACHE.isOnDemandRevalidate && !globalThis.__openNextAls?.getStore()?.isISRRevalidation)
7979
`;
8080

81+
export const useCacheRule = `
82+
rule:
83+
kind: member_expression
84+
pattern: $STORE_OR_CACHE.isOnDemandRevalidate
85+
inside:
86+
kind: binary_expression
87+
has:
88+
kind: member_expression
89+
pattern: $STORE_OR_CACHE.isDraftMode
90+
inside:
91+
kind: if_statement
92+
stopBy: end
93+
has:
94+
kind: return_statement
95+
any:
96+
- has:
97+
kind: 'true'
98+
- has:
99+
regex: '!0'
100+
stopBy: end
101+
fix:
102+
'($STORE_OR_CACHE.isOnDemandRevalidate && !globalThis.__openNextAls?.getStore()?.isISRRevalidation)'`;
103+
81104
export const patchFetchCacheForISR: CodePatcher = {
82105
name: "patch-fetch-cache-for-isr",
83106
patches: [
@@ -111,3 +134,20 @@ export const patchUnstableCacheForISR: CodePatcher = {
111134
},
112135
],
113136
};
137+
138+
export const patchUseCacheForISR: CodePatcher = {
139+
name: "patch-use-cache-for-isr",
140+
patches: [
141+
{
142+
versions: ">=15.3.0",
143+
field: {
144+
pathFilter: getCrossPlatformPathRegex(
145+
String.raw`(server/chunks/.*\.js|.*\.runtime\..*\.js|use-cache/use-cache-wrapper\.js)$`,
146+
{ escape: false },
147+
),
148+
contentFilter: /\.isOnDemandRevalidate/,
149+
patchCode: createPatchCode(useCacheRule, Lang.JavaScript),
150+
},
151+
},
152+
],
153+
};

packages/tests-e2e/tests/experimental/use-cache.test.ts

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ test("cached component should work in ssr", async ({ page }) => {
2121
isrText = await isrElt.textContent();
2222
await page.waitForTimeout(1000);
2323
} while (isrText === initialIsrText);
24-
25-
expect(fullyCachedElt).toHaveText(initialFullyCachedText ?? "");
26-
expect(isrElt).not.toHaveText(initialIsrText ?? "");
24+
const fullyCachedText = await fullyCachedElt.textContent();
25+
expect(fullyCachedText).toEqual(initialFullyCachedText);
2726
});
2827

2928
test("revalidateTag should work for fullyCached component", async ({
@@ -42,5 +41,47 @@ test("revalidateTag should work for fullyCached component", async ({
4241

4342
await page.reload();
4443
await expect(fullyCachedElt).toBeVisible();
45-
expect(fullyCachedElt).not.toHaveText(initialFullyCachedText ?? "");
44+
const newFullyCachedText = await fullyCachedElt.textContent();
45+
expect(newFullyCachedText).not.toEqual(initialFullyCachedText);
46+
});
47+
48+
test("cached component should work in isr", async ({ page }) => {
49+
await page.goto("/use-cache/isr");
50+
51+
let fullyCachedElt = page.getByTestId("fullyCached");
52+
let isrElt = page.getByTestId("isr");
53+
54+
await expect(fullyCachedElt).toBeVisible();
55+
await expect(isrElt).toBeVisible();
56+
57+
let initialFullyCachedText = await fullyCachedElt.textContent();
58+
let initialIsrText = await isrElt.textContent();
59+
60+
// We have to force reload until ISR has triggered at least once, otherwise the test will be flakey
61+
62+
let isrText = initialIsrText;
63+
64+
while (isrText === initialIsrText) {
65+
await page.reload();
66+
isrElt = page.getByTestId("isr");
67+
fullyCachedElt = page.getByTestId("fullyCached");
68+
await expect(isrElt).toBeVisible();
69+
isrText = await isrElt.textContent();
70+
await expect(fullyCachedElt).toBeVisible();
71+
initialFullyCachedText = await fullyCachedElt.textContent();
72+
await page.waitForTimeout(1000);
73+
}
74+
initialIsrText = isrText;
75+
76+
do {
77+
await page.reload();
78+
fullyCachedElt = page.getByTestId("fullyCached");
79+
isrElt = page.getByTestId("isr");
80+
await expect(fullyCachedElt).toBeVisible();
81+
await expect(isrElt).toBeVisible();
82+
isrText = await isrElt.textContent();
83+
await page.waitForTimeout(1000);
84+
} while (isrText === initialIsrText);
85+
const fullyCachedText = await fullyCachedElt.textContent();
86+
expect(fullyCachedText).toEqual(initialFullyCachedText);
4687
});

packages/tests-unit/tests/build/patch/patches/patchFetchCacheISR.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
22
import {
33
fetchRule,
44
unstable_cacheRule,
5+
useCacheRule,
56
} from "@opennextjs/aws/build/patch/patches/patchFetchCacheISR.js";
67
import { describe } from "vitest";
78

@@ -54,6 +55,24 @@ const patchFetchCacheCodeMinifiedNext15 = `
5455
let t=P.isOnDemandRevalidate?null:await V.get(n,{kind:l.IncrementalCacheKind.FETCH,revalidate:_,fetchUrl:y,fetchIdx:X,tags:N,softTags:C});
5556
`;
5657

58+
const patchUseCacheUnminified = `
59+
function shouldForceRevalidate(workStore, workUnitStore) {
60+
if (workStore.isOnDemandRevalidate || workStore.isDraftMode) {
61+
return true;
62+
}
63+
if (workStore.dev && workUnitStore) {
64+
if (workUnitStore.type === 'request') {
65+
return workUnitStore.headers.get('cache-control') === 'no-cache';
66+
}
67+
if (workUnitStore.type === 'cache') {
68+
return workUnitStore.forceRevalidate;
69+
}
70+
}
71+
return false;
72+
}`;
73+
const patchUseCacheMinified = `
74+
function D(e,t){if(e.isOnDemandRevalidate||e.isDraftMode)return!0;if(e.dev&&t){if("request"===t.type)return"no-cache"===t.headers.get("cache-control");if("cache"===t.type)return t.forceRevalidate}return!1}`;
75+
5776
describe("patchUnstableCacheForISR", () => {
5877
test("on unminified code", async () => {
5978
expect(
@@ -124,3 +143,32 @@ describe("patchFetchCacheISR", () => {
124143
});
125144
//TODO: Add test for Next 14.2.24
126145
});
146+
147+
describe("patchUseCache", () => {
148+
test("on unminified code", async () => {
149+
expect(
150+
patchCode(patchUseCacheUnminified, useCacheRule),
151+
).toMatchInlineSnapshot(`
152+
"function shouldForceRevalidate(workStore, workUnitStore) {
153+
if ((workStore.isOnDemandRevalidate && !globalThis.__openNextAls?.getStore()?.isISRRevalidation) || workStore.isDraftMode) {
154+
return true;
155+
}
156+
if (workStore.dev && workUnitStore) {
157+
if (workUnitStore.type === 'request') {
158+
return workUnitStore.headers.get('cache-control') === 'no-cache';
159+
}
160+
if (workUnitStore.type === 'cache') {
161+
return workUnitStore.forceRevalidate;
162+
}
163+
}
164+
return false;
165+
}"`);
166+
});
167+
test("on minified code", async () => {
168+
expect(
169+
patchCode(patchUseCacheMinified, useCacheRule),
170+
).toMatchInlineSnapshot(`
171+
"function D(e,t){if((e.isOnDemandRevalidate && !globalThis.__openNextAls?.getStore()?.isISRRevalidation)||e.isDraftMode)return!0;if(e.dev&&t){if("request"===t.type)return"no-cache"===t.headers.get("cache-control");if("cache"===t.type)return t.forceRevalidate}return!1}"
172+
`);
173+
});
174+
});

0 commit comments

Comments
 (0)