You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`@opennextjs/cloudflare` is an adapter that takes a Next.js `standalone` build and runs it on Cloudflare Workers via the Node.js compatibility layer. It sits on top of `@opennextjs/aws`, which provides the generic OpenNext build/runtime core; this package plugs Cloudflare-specific bindings (KV, R2, D1, Durable Objects, Assets, Images) into the override points that `@opennextjs/aws` exposes, and also contains the esbuild plugins and AST grep patches needed to rewrite Next's emitted code to run on Workers.
4
+
5
+
# Layout
6
+
7
+
```
8
+
packages/cloudflare/ # the adapter
9
+
src/api/ # runtime surface users import (small)
10
+
src/cli/ # the `opennextjs-cloudflare` build CLI
11
+
commands/ # build, deploy, preview, etc. commands live here
templates/ # starter configs copied by `migrate` command
14
+
examples/ # sample Next apps used for manual + e2e testing
15
+
create-cloudflare/ # templates for the `create-cloudflare` CLI
16
+
benchmarking/ # perf harness
17
+
```
18
+
19
+
Two things to keep separate in your head: **`src/api`** is the tiny surface users import at runtime; **`src/cli`** is the much larger build tool. Changes to `src/api` are user-visible; changes in `src/cli/build/patches` are user-invisible but the riskiest code in the repo.
|`pnpm install`| also triggers a `postinstall` build of the adapter. |
28
+
|`pnpm build`| build `packages/cloudflare`. |
29
+
|`pnpm --filter cloudflare build:watch`| rebuild on change. |
30
+
|`pnpm test`| builds, then runs all vitest suites. |
31
+
|`pnpm code:checks`| prettier + eslint + tsc. |
32
+
|`pnpm fix`| auto-fix prettier + eslint. |
33
+
|`pnpm --filter <example> preview`| build + preview an example app end-to-end. Add `SKIP_NEXT_APP_BUILD=true` when only the adapter changed. |
34
+
|`pnpm e2e` / `pnpm e2e:dev`| Playwright suites against the example apps. |
35
+
|`pnpm --filter <example> e2e`| Run a specific example's Playwright suite. |
36
+
|`pnpm changeset`| create a changeset for changes. |
37
+
38
+
# Conventions
39
+
40
+
-**Strict TypeScript**. Don't loosen; reach for generics or narrowing.
41
+
-**ESM only**. Internal imports use the `.js` extension (`./foo.js`) even though the source is `.ts` - this is required for bundling, not a mistake.
42
+
-**Unit tests are `*.spec.ts` colocated with source**, run with Vitest. Use `mock-fs` for filesystem-heavy tests. E2E coverage lives in `examples/` and runs under Playwright.
43
+
-**Formatting is prettier**. Don't fight it; `pnpm fix`.
44
+
-**Imports are sorted by `simple-import-sort`.** Let eslint reorder them.
45
+
-**Dependency versions live in `pnpm-workspace.yaml` under `catalog:`.** When adding a shared dep, add it to the catalog and reference it as `"catalog:"` in the package.json. Don't pin versions inline when a catalog entry already exists.
46
+
-**`packages/cloudflare` ships to users**. Be deliberate about adding runtime `dependencies`. Prefer `devDependencies`, inlining small helpers, or moving logic into code that only runs in the CLI.
47
+
-**`CloudflareEnv` is augmented globally** in `src/api/cloudflare-context.ts`. New bindings that users configure should be declared there with a comment explaining what they're for.
48
+
-**User-facing logs** go through `@opennextjs/aws`'s logger, not `console.*`. Warn (don't throw) when experimental features are used.
49
+
50
+
## Where things tend to go wrong
51
+
52
+
-**`src/cli/build/patches/`** contains esbuild plugins and `@ast-grep/napi` transforms that rewrite Next's emitted code to run on Workers. Every patch needs a spec, and ideally a minimal fixture of the input it's matching. Upstream Next changes break these; when a patch stops matching, fix the matcher, don't widen it blindly.
53
+
-**Overrides in `src/api/overrides/`** implement contracts defined in `@opennextjs/aws`. Check the upstream type before changing a signature. `@opennextjs/aws` is pinned in `package.json`, so bumping it is a deliberate change with its own changeset.
54
+
55
+
# Pre-PR checklist
56
+
57
+
1.`pnpm code:checks` is clean.
58
+
2.`pnpm test` passes.
59
+
3. Changeset included if necessary.
60
+
61
+
## Changesets
62
+
63
+
Any behavioural change to `packages/cloudflare` needs one. Skip for internal refactors, test-only changes, example/doc tweaks.
64
+
65
+
```sh
66
+
pnpm changeset
67
+
```
68
+
69
+
Format:
70
+
71
+
```
72
+
<type>: <imperative title>
73
+
74
+
<body explaining the why>
75
+
```
76
+
77
+
-`type` is one of `feature | fix | refactor | docs | chore`.
Copy file name to clipboardExpand all lines: packages/cloudflare/CHANGELOG.md
+45Lines changed: 45 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,50 @@
1
1
# @opennextjs/cloudflare
2
2
3
+
## 1.19.4
4
+
5
+
### Patch Changes
6
+
7
+
-[#1221](https://github.com/opennextjs/opennextjs-cloudflare/pull/1221)[`a2679bf`](https://github.com/opennextjs/opennextjs-cloudflare/commit/a2679bf9549f620e1ab0e1900dcc7a6b6ac03e0a) Thanks [@mushan0x0](https://github.com/mushan0x0)! - Stop bundling `@vercel/og` (and its ~1.4 MiB `resvg.wasm`) when the app does not use it.
8
+
9
+
Next.js's `externalImport` helper keeps a dynamic `import("next/dist/compiled/@vercel/og/index.edge.js")` in the emitted handler even for apps that never use `ImageResponse` / `opengraph-image`. Previously this module was marked as `external` when `useOg` was `false`, which left Wrangler to resolve and bundle it — pulling in ~800 KiB of JS plus `resvg.wasm` and pushing many Workers over the Cloudflare free-tier 3 MiB gzip limit.
10
+
11
+
When `useOg` is `false`, the edge entry is now aliased to the existing `throw.js` shim, so the unreachable dynamic import resolves to a tiny module and the real `@vercel/og` library is no longer pulled into the Worker bundle.
12
+
13
+
-[#1208](https://github.com/opennextjs/opennextjs-cloudflare/pull/1208)[`2c5b472`](https://github.com/opennextjs/opennextjs-cloudflare/commit/2c5b4729b6a48560b550af820c46c2350e149fa6) Thanks [@edmundhung](https://github.com/edmundhung)! - Use `OPEN_NEXT_BUILD_ID` instead of `NEXT_BUILD_ID` in the cache keys.
14
+
15
+
As of Next 16.2 `NEXT_BUILD_ID` is a fixed value when deploymentId is set explicitly.
16
+
17
+
See <https://github.com/opennextjs/opennextjs-aws/pull/1144>
18
+
19
+
-[#1193](https://github.com/opennextjs/opennextjs-cloudflare/pull/1193)[`1e8d232`](https://github.com/opennextjs/opennextjs-cloudflare/commit/1e8d232672353920a8e05e468cf3a5890b82b0f6) Thanks [@conico974](https://github.com/conico974)! - Fix tag cache stale logic
20
+
21
+
## 1.19.3
22
+
23
+
### Patch Changes
24
+
25
+
-[#1215](https://github.com/opennextjs/opennextjs-cloudflare/pull/1215)[`608893e`](https://github.com/opennextjs/opennextjs-cloudflare/commit/608893e63e1ee16d07c7ec42da979657cf2a62bd) Thanks [@vicb](https://github.com/vicb)! - Factor large repeated values in manifests
Remove process.version / process.versions.node overrides now that [unjs/unenv#493](https://github.com/unjs/unenv/pull/493) is merged and shipped in [[email protected]](https://github.com/unjs/unenv/releases/tag/v2.0.0-rc.16) (project uses 2.0.0-rc.24)
32
+
33
+
-[#1199](https://github.com/opennextjs/opennextjs-cloudflare/pull/1199)[`32594d6`](https://github.com/opennextjs/opennextjs-cloudflare/commit/32594d6a921c5ebdbe25f38635bb2c9dabdcbff1) Thanks [@SdSadat](https://github.com/SdSadat)! - fix(cli): fail fast in non-TTY environments instead of hanging on config-creation prompts
34
+
35
+
When `open-next.config.ts` (or `wrangler.(toml|json|jsonc)`) is missing, the CLI
36
+
prompts the user to auto-create it. In non-TTY environments (Cloudflare Workers
37
+
Builds, Docker, CI) the Enquirer prompt can't read stdin, so the build hangs or
38
+
fails with a truncated prompt and a cryptic exit code — the user sees
39
+
`? Missing required open-next.config.ts file, do you want to create one? (Y/n)`
40
+
and then ` ELIFECYCLE Command failed with exit code 13`, with no hint at what
41
+
to do next.
42
+
43
+
Now, in non-interactive environments, both prompts throw an actionable error
44
+
with the exact template to paste (for `open-next.config.ts`) or point at the
`bypassTagCacheOnCacheHit is not recommended for Next 16+ as it is not compatible with SWR tags. Make sure to always use \`revalidateTag\` with \`{ expire: 0 }\` if you want to bypass the tag cache.`
0 commit comments