Skip to content

Commit

Permalink
feat: use the cache api if there is no kv cache available
Browse files Browse the repository at this point in the history
  • Loading branch information
james-elicx committed Nov 17, 2024
1 parent a87f6b3 commit cc9ad26
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 17 deletions.
7 changes: 7 additions & 0 deletions .changeset/gold-onions-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@opennextjs/cloudflare": minor
---

feat: use the cache api if there is no kv cache available

Instead of requiring a KV cache is available in the environment for Next.js caching to work, the cache handle will default to using the Cache API.
37 changes: 35 additions & 2 deletions packages/cloudflare/src/cli/templates/cache-handler/cache-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ export type CacheStore = {

export function getCacheStore() {
const kvName = process.env.__OPENNEXT_KV_BINDING_NAME;
if (kvName && process.env[kvName]) {
if (process.env[kvName]) {
return new KVStore(process.env[kvName] as unknown as KVNamespace);
}

return new CacheAPIStore();
}

const defaultTTL = 31536000; // 1 year
Expand All @@ -27,6 +29,37 @@ class KVStore implements CacheStore {
}

put(key: string, entry: CacheEntry, ttl = defaultTTL) {
return this.store.put(key, JSON.stringify(entry), { expirationTtl: ttl });
return this.store.put(key, JSON.stringify(entry), {
expirationTtl: ttl,
});
}
}

class CacheAPIStore implements CacheStore {
constructor(private name = "__opennext_cache") {}

async get(key: string) {
const cache = await caches.open(this.name);
const response = await cache.match(this.createCacheKey(key));

if (response) {
return response.json<CacheEntry>();
}

return null;
}

async put(key: string, entry: CacheEntry, ttl = defaultTTL) {
const cache = await caches.open(this.name);

const response = new Response(JSON.stringify(entry), {
headers: { "cache-control": `max-age=${ttl}` },
});

return cache.put(this.createCacheKey(key), response);
}

private createCacheKey(key: string) {
return `https://${this.name}.local/entry/${key}`;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { getCacheStore } from "./cache-store";
import { getSeedBodyFile, getSeedMetaFile, getSeedTextFile, parseCtx } from "./utils";

export class OpenNextCacheHandler implements CacheHandler {
protected cache: CacheStore | undefined;
protected cache: CacheStore;

protected debug: boolean = !!process.env.NEXT_PRIVATE_DEBUG_CACHE;

Expand All @@ -32,13 +32,11 @@ export class OpenNextCacheHandler implements CacheHandler {

if (this.debug) console.log(`cache - get: ${key}, ${ctx?.kind}`);

if (this.cache !== undefined) {
try {
const value = await this.cache.get(key);
if (value) return value;
} catch (e) {
console.error(`Failed to get value for key = ${key}: ${e}`);
}
try {
const value = await this.cache.get(key);
if (value) return value;
} catch (e) {
console.error(`Failed to get value for key = ${key}: ${e}`);
}

// Check for seed data from the file-system.
Expand Down Expand Up @@ -114,10 +112,6 @@ export class OpenNextCacheHandler implements CacheHandler {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [key, entry, _ctx] = args;

if (this.cache === undefined) {
return;
}

if (this.debug) console.log(`cache - set: ${key}`);

const data: CacheEntry = {
Expand All @@ -134,9 +128,6 @@ export class OpenNextCacheHandler implements CacheHandler {

async revalidateTag(...args: Parameters<CacheHandler["revalidateTag"]>) {
const [tags] = args;
if (this.cache === undefined) {
return;
}

if (this.debug) console.log(`cache - revalidateTag: ${JSON.stringify([tags].flat())}`);
}
Expand Down

0 comments on commit cc9ad26

Please sign in to comment.