Skip to content

Commit

Permalink
fix cache for next 15 (#512)
Browse files Browse the repository at this point in the history
* fix for next 15

* review fix

* Create tasty-cherries-sort.md
  • Loading branch information
conico974 authored Sep 22, 2024
1 parent 4ec9265 commit 55a6bcc
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/tasty-cherries-sort.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"open-next": patch
---

fix incremental cache for next 15
58 changes: 51 additions & 7 deletions packages/open-next/src/adapters/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ interface CachedRedirectValue {
}

interface CachedRouteValue {
kind: "ROUTE";
kind: "ROUTE" | "APP_ROUTE";
// this needs to be a RenderResult so since renderResponse
// expects that type instead of a string
body: Buffer;
Expand All @@ -39,7 +39,7 @@ interface CachedImageValue {
}

interface IncrementalCachedPageValue {
kind: "PAGE";
kind: "PAGE" | "PAGES";
// this needs to be a string since the cache expects to store
// the string value
html: string;
Expand All @@ -48,9 +48,21 @@ interface IncrementalCachedPageValue {
headers?: Record<string, undefined | string>;
}

interface IncrementalCachedAppPageValue {
kind: "APP_PAGE";
// this needs to be a string since the cache expects to store
// the string value
html: string;
rscData: Buffer;
headers?: Record<string, undefined | string | string[]>;
postponed?: string;
status?: number;
}

type IncrementalCacheValue =
| CachedRedirectValue
| IncrementalCachedPageValue
| IncrementalCachedAppPageValue
| CachedImageValue
| CachedFetchValue
| CachedRouteValue;
Expand Down Expand Up @@ -94,6 +106,7 @@ declare global {
var disableDynamoDBCache: boolean;
var disableIncrementalCache: boolean;
var lastModified: Record<string, number>;
var isNextAfter15: boolean;
}
// We need to use globalThis client here as this class can be defined at load time in next 12 but client is not available at load time
export default class S3Cache {
Expand Down Expand Up @@ -203,7 +216,7 @@ export default class S3Cache {
return {
lastModified: _lastModified,
value: {
kind: "ROUTE",
kind: globalThis.isNextAfter15 ? "APP_ROUTE" : "ROUTE",
body: Buffer.from(
cacheData.body ?? Buffer.alloc(0),
isBinaryContentType(String(meta?.headers?.["content-type"]))
Expand All @@ -215,10 +228,22 @@ export default class S3Cache {
},
} as CacheHandlerValue;
} else if (cacheData?.type === "page" || cacheData?.type === "app") {
if (globalThis.isNextAfter15 && cacheData?.type === "app") {
return {
lastModified: _lastModified,
value: {
kind: "APP_PAGE",
html: cacheData.html,
rscData: Buffer.from(cacheData.rsc),
status: meta?.status,
headers: meta?.headers,
},
} as CacheHandlerValue;
}
return {
lastModified: _lastModified,
value: {
kind: "PAGE",
kind: globalThis.isNextAfter15 ? "PAGES" : "PAGE",
html: cacheData.html,
pageData:
cacheData.type === "page" ? cacheData.json : cacheData.rsc,
Expand Down Expand Up @@ -259,7 +284,7 @@ export default class S3Cache {
.getStore()
?.pendingPromiseRunner.withResolvers<void>();
try {
if (data?.kind === "ROUTE") {
if (data?.kind === "ROUTE" || data?.kind === "APP_ROUTE") {
const { body, status, headers } = data;
await globalThis.incrementalCache.set(
key,
Expand All @@ -277,8 +302,8 @@ export default class S3Cache {
},
false,
);
} else if (data?.kind === "PAGE") {
const { html, pageData } = data;
} else if (data?.kind === "PAGE" || data?.kind === "PAGES") {
const { html, pageData, status, headers } = data;
const isAppPath = typeof pageData === "string";
if (isAppPath) {
await globalThis.incrementalCache.set(
Expand All @@ -287,6 +312,10 @@ export default class S3Cache {
type: "app",
html,
rsc: pageData,
meta: {
status,
headers,
},
},
false,
);
Expand All @@ -301,6 +330,21 @@ export default class S3Cache {
false,
);
}
} else if (data?.kind === "APP_PAGE") {
const { html, rscData, headers, status } = data;
await globalThis.incrementalCache.set(
key,
{
type: "app",
html,
rsc: rscData.toString("utf8"),
meta: {
status,
headers,
},
},
false,
);
} else if (data?.kind === "FETCH") {
await globalThis.incrementalCache.set<true>(key, data, true);
} else if (data?.kind === "REDIRECT") {
Expand Down
9 changes: 7 additions & 2 deletions packages/open-next/src/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,11 +374,12 @@ async function createImageOptimizationBundle(config: OpenNextConfig) {
// Build Lambda code (2nd pass)
// note: bundle in user's Next.js app again b/c the adapter relies on the
// "next" package. And the "next" package from user's app should
// be used.
// be used. We also set @opentelemetry/api as external because it seems to be
// required by Next 15 even though it's not used.
esbuildSync(
{
entryPoints: [path.join(outputPath, "index.mjs")],
external: ["sharp"],
external: ["sharp", "@opentelemetry/api"],
allowOverwrite: true,
outfile: path.join(outputPath, "index.mjs"),
banner: {
Expand Down Expand Up @@ -685,6 +686,9 @@ async function createCacheAssets(monorepoRoot: string) {
export function compileCache(format: "cjs" | "esm" = "cjs") {
const ext = format === "cjs" ? "cjs" : "mjs";
const outfile = path.join(options.outputDir, ".build", `cache.${ext}`);

const isAfter15 = compareSemver(options.nextVersion, "15.0.0") >= 0;

esbuildSync(
{
external: ["next", "styled-jsx", "react", "@aws-sdk/*"],
Expand All @@ -700,6 +704,7 @@ export function compileCache(format: "cjs" | "esm" = "cjs") {
`globalThis.disableDynamoDBCache = ${
config.dangerous?.disableTagCache ?? false
};`,
`globalThis.isNextAfter15 = ${isAfter15};`,
].join(""),
},
},
Expand Down

0 comments on commit 55a6bcc

Please sign in to comment.