Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .changeset/cloudflare-cache-service.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
"@opennextjs/cloudflare": minor
---

Move the cache behind a dedicated cache handler function

The incremental cache and the tag cache no longer run inside the server function. They now run in
the cache handler function, bundled to `.open-next/cache-function` as a fetch handler and served by
the worker through the `OpenNextCache` named entrypoint. The server and the middleware reach it over
a service binding.

This requires a new self referencing service binding in the wrangler configuration:

```jsonc
"services": [
{
"binding": "NEXT_CACHE_SERVICE",
"service": "<your-worker-name>",
"entrypoint": "OpenNextCache"
}
]
```

The cache runs in the same worker by default. Pointing the binding at another worker is enough to
run the cache as a service of its own.

Workers Caching should also be configured per entrypoint so that only the cache entrypoint is served
from the Workers cache, never the Next.js server. This requires wrangler `4.107.0` or greater:

```jsonc
"exports": {
// The Next.js server must not be served from the Workers cache.
"default": { "type": "worker", "cache": { "enabled": false } },
// The OpenNext cache entrypoint returns cacheable responses, cache them.
"OpenNextCache": { "type": "worker", "cache": { "enabled": true } }
}
```

`defineCloudflareConfig` is otherwise unchanged. Configurations that are not created by
`defineCloudflareConfig` should move `incrementalCache` and `tagCache` from `default.override` to
the new top level `cacheHandler` option, and set `default.override.cache`.
2 changes: 1 addition & 1 deletion create-cloudflare/next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@
"oxlint": "^1.42.0",
"tailwindcss": "^4",
"typescript": "catalog:",
"wrangler": "^4.59.3"
"wrangler": "^4.107.0"
}
}
15 changes: 15 additions & 0 deletions create-cloudflare/next/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,27 @@
// see https://opennext.js.org/cloudflare/howtos/image
"binding": "IMAGES"
},
"exports": {
// The Next.js server must not be served from the Workers cache.
"default": { "type": "worker", "cache": { "enabled": false } },
// The OpenNext cache entrypoint returns cacheable responses, cache them.
// see https://opennext.js.org/cloudflare/caching
"OpenNextCache": { "type": "worker", "cache": { "enabled": true } }
},
"services": [
{
// Self-reference service binding, the service name must match the worker name
// see https://opennext.js.org/cloudflare/caching
"binding": "WORKER_SELF_REFERENCE",
"service": "worker_name"
},
{
// The OpenNext cache runs behind a named entrypoint of this worker.
// The service name must match the worker name.
// see https://opennext.js.org/cloudflare/caching
"binding": "NEXT_CACHE_SERVICE",
"service": "worker_name",
"entrypoint": "OpenNextCache"
}
],
"observability": {
Expand Down
12 changes: 12 additions & 0 deletions examples-cloudflare/e2e/app-pages-router/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,22 @@
"bucket_name": "cache"
}
],
"exports": {
// The Next.js server must not be served from the Workers cache.
"default": { "type": "worker", "cache": { "enabled": false } },
// The OpenNext cache entrypoint returns cacheable responses, cache them.
// see https://opennext.js.org/cloudflare/caching
"OpenNextCache": { "type": "worker", "cache": { "enabled": true } }
},
"services": [
{
"binding": "WORKER_SELF_REFERENCE",
"service": "app-pages-router"
},
{
"binding": "NEXT_CACHE_SERVICE",
"service": "app-pages-router",
"entrypoint": "OpenNextCache"
}
],
"vars": {
Expand Down
2 changes: 1 addition & 1 deletion examples-cloudflare/e2e/app-router/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"clean": "rm -rf .turbo node_modules .next .open-next",
"build:worker:cf": "pnpm opennextjs-cloudflare build",
"preview:worker": "pnpm opennextjs-cloudflare preview",
"preview": "pnpm build:worker && pnpm preview:worker",
"preview": "pnpm build:worker:cf && pnpm preview:worker",
"e2e:cf": "playwright test -c e2e/playwright.config.ts",
"build:worker-turbopack": "pnpm build:worker --openNextConfigPath open-next.turbopack.config.ts",
"e2e-turbopack": "playwright test -c e2e/playwright.turbopack.config.ts"
Expand Down
12 changes: 12 additions & 0 deletions examples-cloudflare/e2e/app-router/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,22 @@
"bucket_name": "cache"
}
],
"exports": {
// The Next.js server must not be served from the Workers cache.
"default": { "type": "worker", "cache": { "enabled": false } },
// The OpenNext cache entrypoint returns cacheable responses, cache them.
// see https://opennext.js.org/cloudflare/caching
"OpenNextCache": { "type": "worker", "cache": { "enabled": true } }
},
"services": [
{
"binding": "WORKER_SELF_REFERENCE",
"service": "app-router"
},
{
"binding": "NEXT_CACHE_SERVICE",
"service": "app-router",
"entrypoint": "OpenNextCache"
}
],
"vars": {
Expand Down
12 changes: 12 additions & 0 deletions examples-cloudflare/e2e/experimental/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,22 @@
"bucket_name": "cache"
}
],
"exports": {
// The Next.js server must not be served from the Workers cache.
"default": { "type": "worker", "cache": { "enabled": false } },
// The OpenNext cache entrypoint returns cacheable responses, cache them.
// see https://opennext.js.org/cloudflare/caching
"OpenNextCache": { "type": "worker", "cache": { "enabled": true } }
},
"services": [
{
"binding": "WORKER_SELF_REFERENCE",
"service": "experimental"
},
{
"binding": "NEXT_CACHE_SERVICE",
"service": "experimental",
"entrypoint": "OpenNextCache"
}
]
}
12 changes: 12 additions & 0 deletions examples-cloudflare/e2e/pages-router/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,22 @@
"bucket_name": "cache"
}
],
"exports": {
// The Next.js server must not be served from the Workers cache.
"default": { "type": "worker", "cache": { "enabled": false } },
// The OpenNext cache entrypoint returns cacheable responses, cache them.
// see https://opennext.js.org/cloudflare/caching
"OpenNextCache": { "type": "worker", "cache": { "enabled": true } }
},
"services": [
{
"binding": "WORKER_SELF_REFERENCE",
"service": "pages-router"
},
{
"binding": "NEXT_CACHE_SERVICE",
"service": "pages-router",
"entrypoint": "OpenNextCache"
}
],
"vars": {
Expand Down
14 changes: 14 additions & 0 deletions examples-cloudflare/overrides/d1-tag-next/wrangler.e2e.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@
"directory": ".open-next/assets",
"binding": "ASSETS",
},
"exports": {
// The Next.js server must not be served from the Workers cache.
"default": { "type": "worker", "cache": { "enabled": false } },
// The OpenNext cache entrypoint returns cacheable responses, cache them.
// see https://opennext.js.org/cloudflare/caching
"OpenNextCache": { "type": "worker", "cache": { "enabled": true } },
},
"services": [
{
"binding": "NEXT_CACHE_SERVICE",
"service": "ssg-app",
"entrypoint": "OpenNextCache",
},
],
"vars": {
"APP_VERSION": "1.2.345",
},
Expand Down
14 changes: 14 additions & 0 deletions examples-cloudflare/overrides/kv-tag-next/wrangler.e2e.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@
"directory": ".open-next/assets",
"binding": "ASSETS",
},
"exports": {
// The Next.js server must not be served from the Workers cache.
"default": { "type": "worker", "cache": { "enabled": false } },
// The OpenNext cache entrypoint returns cacheable responses, cache them.
// see https://opennext.js.org/cloudflare/caching
"OpenNextCache": { "type": "worker", "cache": { "enabled": true } },
},
"services": [
{
"binding": "NEXT_CACHE_SERVICE",
"service": "ssg-app",
"entrypoint": "OpenNextCache",
},
],
"vars": {
"APP_VERSION": "1.2.345",
},
Expand Down
12 changes: 12 additions & 0 deletions examples-cloudflare/overrides/memory-queue/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,22 @@
"id": "<BINDING_ID>"
}
],
"exports": {
// The Next.js server must not be served from the Workers cache.
"default": { "type": "worker", "cache": { "enabled": false } },
// The OpenNext cache entrypoint returns cacheable responses, cache them.
// see https://opennext.js.org/cloudflare/caching
"OpenNextCache": { "type": "worker", "cache": { "enabled": true } }
},
"services": [
{
"binding": "WORKER_SELF_REFERENCE",
"service": "memory-queue"
},
{
"binding": "NEXT_CACHE_SERVICE",
"service": "memory-queue",
"entrypoint": "OpenNextCache"
}
]
}
14 changes: 14 additions & 0 deletions examples-cloudflare/overrides/r2-incremental-cache/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@
"directory": ".open-next/assets",
"binding": "ASSETS"
},
"exports": {
// The Next.js server must not be served from the Workers cache.
"default": { "type": "worker", "cache": { "enabled": false } },
// The OpenNext cache entrypoint returns cacheable responses, cache them.
// see https://opennext.js.org/cloudflare/caching
"OpenNextCache": { "type": "worker", "cache": { "enabled": true } }
},
"services": [
{
"binding": "NEXT_CACHE_SERVICE",
"service": "r2-incremental-cache",
"entrypoint": "OpenNextCache"
}
],
"env": {
"e2e": {
"d1_databases": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,19 @@
"assets": {
"directory": ".open-next/assets",
"binding": "ASSETS"
}
},
"exports": {
// The Next.js server must not be served from the Workers cache.
"default": { "type": "worker", "cache": { "enabled": false } },
// The OpenNext cache entrypoint returns cacheable responses, cache them.
// see https://opennext.js.org/cloudflare/caching
"OpenNextCache": { "type": "worker", "cache": { "enabled": true } }
},
"services": [
{
"binding": "NEXT_CACHE_SERVICE",
"service": "static-assets-incremental-cache",
"entrypoint": "OpenNextCache"
}
]
}
12 changes: 12 additions & 0 deletions examples-cloudflare/playground16/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,22 @@
"vars": {
"hello": "Hello World from the cloudflare context!"
},
"exports": {
// The Next.js server must not be served from the Workers cache.
"default": { "type": "worker", "cache": { "enabled": false } },
// The OpenNext cache entrypoint returns cacheable responses, cache them.
// see https://opennext.js.org/cloudflare/caching
"OpenNextCache": { "type": "worker", "cache": { "enabled": true } }
},
"services": [
{
"binding": "WORKER_SELF_REFERENCE",
"service": "playground16"
},
{
"binding": "NEXT_CACHE_SERVICE",
"service": "playground16",
"entrypoint": "OpenNextCache"
}
],
"durable_objects": {
Expand Down
14 changes: 14 additions & 0 deletions examples-cloudflare/prisma/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@
"directory": ".open-next/assets",
"binding": "ASSETS"
},
"exports": {
// The Next.js server must not be served from the Workers cache.
"default": { "type": "worker", "cache": { "enabled": false } },
// The OpenNext cache entrypoint returns cacheable responses, cache them.
// see https://opennext.js.org/cloudflare/caching
"OpenNextCache": { "type": "worker", "cache": { "enabled": true } }
},
"services": [
{
"binding": "NEXT_CACHE_SERVICE",
"service": "api",
"entrypoint": "OpenNextCache"
}
],
"d1_databases": [
{
"binding": "DB",
Expand Down
11 changes: 9 additions & 2 deletions examples/app-pages-router/open-next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import type { OpenNextConfig, OverrideOptions } from "@opennextjs/core/types/ope
const devOverride = {
wrapper: "express-dev",
converter: "node",
incrementalCache: "fs-dev",
cache: "local",
queue: "direct",
tagCache: "fs-dev-nextMode",
} satisfies OverrideOptions;

export default {
Expand All @@ -26,6 +25,14 @@ export default {
},
loader: "fs-dev",
},
cacheHandler: {
override: {
wrapper: "dummy",
converter: "dummy",
},
incrementalCache: "fs-dev",
tagCache: "fs-dev-nextMode",
},
// You can override the build command here so that you don't have to rebuild next every time you make a change
// buildCommand: "echo 'No build command'",
} satisfies OpenNextConfig;
12 changes: 10 additions & 2 deletions examples/app-router/open-next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ export default {
override: {
wrapper: "express-dev",
converter: "node",
incrementalCache: "fs-dev",
cache: "local",
queue: "direct",
tagCache: "fs-dev-nextMode",
},
},

Expand All @@ -23,6 +22,15 @@ export default {
loader: "fs-dev",
},

cacheHandler: {
override: {
wrapper: "dummy",
converter: "dummy",
},
incrementalCache: "fs-dev",
tagCache: "fs-dev-nextMode",
},

// You can override the build command here so that you don't have to rebuild next every time you make a change
//buildCommand: "echo 'No build command'",
} satisfies OpenNextConfig;
Loading
Loading