Skip to main content

cloudflare-nextjs

Deploy Next.js to Cloudflare Workers via the OpenNext adapter (@opennextjs/cloudflare). Use for SSR/ISR/SSG/App or Pages Router, getCloudflareContext, bindings (D1/R2/KV/AI/Hyperdrive), caching tiers, skew protection, multi-worker, custom worker, env vars, or worker size/runtime/keep_names/FinalizationRegistry/connection-scoping errors.

소스 정보

저장소
secondsky/claude-skills
최근 소스 활동
2026년 8월 5일 16:05
감지된 SKILL.md 언어
영어
스타
240
포크
33

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
17 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
cloudflare-nextjs
description
Deploy Next.js to Cloudflare Workers via the OpenNext adapter (@opennextjs/cloudflare). Use for SSR/ISR/SSG/App or Pages Router, getCloudflareContext, bindings (D1/R2/KV/AI/Hyperdrive), caching tiers, skew protection, multi-worker, custom worker, env vars, or worker size/runtime/keep_names/FinalizationRegistry/connection-scoping errors.
license
MIT
metadata
{"version":"2.0.0","last_verified":"2026-08-05T00:00:00.000Z","package_versions":{"@opennextjs/cloudflare":"^1.18.1","next":"^14.2.0 || ^15.0.0 || ^16.0.0","wrangler":"^4.81.0"},"compatibility_requirements":{"compatibility_date":"2025-05-05","compatibility_flags":["nodejs_compat","global_fetch_strictly_public"],"min_wrangler":"3.99.0"},"token_savings":"~60%","errors_prevented":"18+","sources":{"overview":"https://opennext.js.org/cloudflare","get_started":"https://opennext.js.org/cloudflare/get-started","cli":"https://opennext.js.org/cloudflare/cli","bindings":"https://opennext.js.org/cloudflare/bindings","caching":"https://opennext.js.org/cloudflare/caching","howto_stripe":"https://opennext.js.org/cloudflare/howtos/stripeAPI","howto_db":"https://opennext.js.org/cloudflare/howtos/db","howto_dev_deploy":"https://opennext.js.org/cloudflare/howtos/dev-deploy","howto_env_vars":"https://opennext.js.org/cloudflare/howtos/env-vars","howto_image":"https://opennext.js.org/cloudflare/howtos/image","howto_custom_worker":"https://opennext.js.org/cloudflare/howtos/custom-worker","howto_keep_names":"https://opennext.js.org/cloudflare/howtos/keep_names","howto_workerd":"https://opennext.js.org/cloudflare/howtos/workerd","howto_skew":"https://opennext.js.org/cloudflare/howtos/skew","howto_assets":"https://opennext.js.org/cloudflare/howtos/assets","howto_multi_worker":"https://opennext.js.org/cloudflare/howtos/multi-worker","performance":"https://opennext.js.org/cloudflare/perf","known_issues":"https://opennext.js.org/cloudflare/known-issues","troubleshooting":"https://opennext.js.org/cloudflare/troubleshooting","migration_06_to_1":"https://opennext.js.org/cloudflare/migrate-from-0.6-to-1.0.0-beta","open_issues":"https://github.com/opennextjs/opennextjs-cloudflare/issues"},"keywords":["OpenNext Cloudflare","@opennextjs/cloudflare","opennextjs-cloudflare cli","Next.js on Workers","Next.js App Router Cloudflare","Next.js Pages Router Cloudflare","Next.js SSR Cloudflare","Next.js ISR Workers","server components cloudflare","server actions workers","Next.js middleware workers","getCloudflareContext","nodejs_compat","global_fetch_strictly_public","workerd runtime","worker size limit","next.js runtime compatibility","database connection scoping","R2 incremental cache","Durable Objects queue","skew protection","multi-worker","custom worker","keep_names","FinalizationRegistry"]}
# OpenNext Cloudflare Adapter — Next.js on Workers Deploy Next.js applications to **Cloudflare Workers** using the OpenNext adapter (`@opennextjs/cloudflare`). The adapter takes a standard Next.js build, runs `package.json` build script, then transforms the output to run on the Workers runtime using the Node.js compatibility layer (`nodejs_compat`) — **not** the Edge runtime. ## Critical Requirements (get these wrong and the build/runtime fails) | Requirement | Value | Why | |---|---|---| | Runtime | **Node.js** (default). Remove every `export const runtime = "edge";` | Edge runtime is unsupported; OpenNext uses `nodejs_compat`. | | `compatibility_flags` | `["nodejs_compat", "global_fetch_strictly_public"]` | Node APIs + allow `fetch()` in app code. | | `compatibility_date` | **≥ `2024-09-23`**; **≥ `2025-05-05`** recommended (FinalizationRegistry) | Older dates break `FinalizationRegistry`, DOs, and more. | | Wrangler | **≥ `3.99.0`** to deploy; **≥ `4.13.0`** for `keep_names`; **≥ `4.36.0`** for stable remote bindings | Feature gates in the docs. | | Next.js | v16 all minors/patches supported; latest minors of v14 and v15; **v14 dropped Q1 2026** | Stated on the overview page. | | Worker size (gzip) | **3 MiB Free / 10 MiB Paid** (compressed only) | Hard Cloudflare limits. | **Windows:** not fully guaranteed (Next.js tooling issues). Use WSL, a Linux VM, or Linux/macOS CI. See known issue #1305. ## Disambiguation: this skill vs `nextjs` - **`nextjs` skill** → framework/App Router/Server Components/Cache Components patterns, **any platform** (Vercel, self-hosted, ...). Use for `async params`, `proxy.ts` migration, `"use cache"`. - **THIS skill (`cloudflare-nextjs`)** → deploying Next.js to **Workers** via the OpenNext adapter: `wrangler.jsonc`, `open-next.config.ts`, `getCloudflareContext`, caching tiers, bindings, skew protection, multi-worker, the Workers-specific errors. > **proxy.ts caveat (Next 16):** Next 16 renamed `middleware.ts` → `proxy.ts`, but `@opennextjs/cloudflare` does **not** recognize `proxy.ts` yet (issue #1277) — on Cloudflare, keep using `middleware.ts`. This is the one place the `nextjs` skill's guidance does NOT apply here. ## Quick Start ### New project (recommended) ```bash npm create cloudflare@latest -- my-next-app --framework=next --platform=workers ``` C3 scaffolds a Next.js app, installs `@opennextjs/cloudflare`, creates `wrangler.jsonc` + `open-next.config.ts` + `.dev.vars`, wires `package.json` scripts, and (if R2 is enabled) creates an R2 bucket for caching. ### Existing Next.js project (one command) ```bash npx @opennextjs/cloudflare migrate ``` `migrate` automates: install adapter + wrangler, create `wrangler.jsonc`/`open-next.config.ts`/`.dev.vars`, update scripts, add `public/_headers`, add `.open-next` to `.gitignore`, wire `initOpenNextCloudflareForDev()` into `next.config.ts`, and create+configure an R2 cache bucket (only if R2 is enabled on the account). <details><summary>Manual install (if you prefer not to run migrate)</summary> ```bash npm install @opennextjs/cloudflare@latest npm install --save-dev wrangler@latest ``` Then create the three files (see `references/wrangler.jsonc`, `references/open-next.config.ts`, `references/package.json`) and add the `dev`/`preview`/`deploy`/`upload`/`cf-typegen` scripts. **Pin adapter versions and audit before upgrading** — see the `dependency-upgrade` skill. </details> ### The four scripts ```jsonc // package.json { "dev": "next dev", // fast HMR via Next dev server "preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview", // build + run in workerd locally "deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy", // build + serve immediately "upload": "opennextjs-cloudflare build && opennextjs-cloudflare upload", // build + upload a version (gradual rollout) "cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts" } ``` - `dev` — fastest feedback loop; add `initOpenNextCloudflareForDev()` to `next.config.ts` so `getCloudflareContext()` works locally with simulated/remote bindings. - `preview` — runs in the **actual Workers runtime** (not Node). Always run before `deploy` to catch runtime-only issues. - `deploy` — populates the **remote** cache, then `wrangler deploy`. App serves immediately. - `upload` — populates remote cache, then `wrangler versions upload`. Does NOT serve automatically; for gradual deployments. `build`, `preview`, `deploy`, `upload` all implicitly call `populateCache` — you do not need to run it manually. ### Dev `next.config.ts` ```ts import type { NextConfig } from "next"; const nextConfig: NextConfig = { /* ... */ }; export default nextConfig; import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"; initOpenNextCloudflareForDev(); ``` ## Accessing Cloudflare Bindings — `getCloudflareContext()` **Do NOT use `process.env` for bindings.** The official API is `getCloudflareContext()` from `@opennextjs/cloudflare`. ```ts import { getCloudflareContext } from "@opennextjs/cloudflare"; export async function GET() { const { env, cf, ctx } = getCloudflareContext(); await env.MY_KV.put("foo", "bar"); return new Response(await env.MY_KV.get("foo")); } ``` **Static routes (ISR/SSG) MUST use async mode** — and be careful: secrets/local values are used during static generation. ```ts const { env } = await getCloudflareContext({ async: true }); ``` **TypeScript types:** `npm run cf-typegen` generates `cloudflare-env.d.ts` (re-run after any binding change). **Remote bindings (local dev → real resources):** stabilized in **Wrangler 4.36.0**. On older wrangler, enable via `initOpenNextCloudflareForDev({ experimental: { remoteBindings: true } })` and use the `experimental_remote` (not `remote`) key on binding options. Note: remote bindings are also used **during build**. Full patterns (D1/R2/KV/AI/Hyperdrive, Drizzle, Prisma, Stripe) → `references/bindings-and-services.md`. ## Caching — three components, three tiers OpenNext's cache has three parts: **Incremental Cache** (storage), **Queue** (dedupe/revalidate), **Tag Cache** (on-demand `revalidateTag`/`revalidatePath`). | Site profile | Incremental | Queue | Tag Cache | When | |---|---|---|---|---| | **SSG only** (no revalidation) | `staticAssetsIncrementalCache` + `enableCacheInterception: true` | none | none | Fastest option; read-only | | **Small site** (ISR/on-demand) | `r2IncrementalCache` | `doQueue` | `d1NextTagCache` | Low traffic; D1 tag cache | | **Large/high-traffic site** | `withRegionalCache(r2IncrementalCache, { mode: "long-lived" })` | `doQueue` | `doShardedTagCache({ baseShardSize: 12 })` + `purgeCache({ type: "direct" })` | DO-sharded; add cache purge if using on-demand | **Reserved binding names** (do not reuse): `ASSETS`, `WORKER_SELF_REFERENCE`, `NEXT_INC_CACHE_R2_BUCKET`, `NEXT_CACHE_DO_QUEUE`, `NEXT_TAG_CACHE_D1`, `NEXT_TAG_CACHE_DO_SHARDED`, `NEXT_CACHE_DO_PURGE`, `IMAGES`. - **Avoid Workers KV** for incremental cache — eventually consistent, can persist stale data indefinitely. - **Cache interception + PPR**: incompatible today; cache interception is NOT enabled by default and does not work with PPR. - **On-demand revalidation** requires both a Tag Cache **and** the Cache Purge component (cache purge only works on a zone/custom domain; needs `CACHE_PURGE_API_TOKEN` + `CACHE_PURGE_ZONE_ID` secrets). - **Pages Router** `res.revalidate` requires a self-reference service binding named `WORKER_SELF_REFERENCE`. - **Headers caveat**: the Worker does not run in front of static assets, so `next.config.ts` `headers()` for `public/` and immutable build files do not apply. Use `public/_headers`. Deep dive (all options, env vars, regional modes, migration from 0.6) → `references/caching.md` and `references/known-issues.md`. ## Common Integrations (condensed — full patterns in references) - **Drizzle + D1/Hyperdrive/PG**, **Prisma + D1/PG/Hyperdrive** — request-scoped clients via `cache()` from `react`; `maxUses: 1` on PG pools; `getCloudflareContext({ async: true })` for ISR/SSG; Prisma needs `previewFeatures = ["driverAdapters"]`, no output dir in `schema.prisma`, and `serverExternalPackages: ["@prisma/client", ".prisma/client"]`. → `references/bindings-and-services.md` - **Stripe** — Workers have no `node:https`; pass `httpClient: Stripe.createFetchHttpClient()`. → `references/bindings-and-services.md` - **Image optimization** — `images.binding: "IMAGES"` in `wrangler.jsonc`, **or** a custom loader (`/cdn-cgi/image/...`) for zones. `minimumCacheTTL` and `dangerouslyAllowLocalIP` are not supported; custom loader bypasses middleware and ignores `remotePatterns`. → `references/advanced.md` - **Env vars** — use Next.js `.env` files (not just `.dev.vars`); `NEXTJS_ENV` in `.dev.vars` selects the env; `--keep-vars` on deploy; secrets are write-only. → `references/dev-deploy-and-env.md` - **Custom worker** (add `scheduled`, Durable Object exports) — point `main` at your worker that re-exports the generated fetch handler. → `references/advanced.md` - **Multi-worker** (split middleware from server) — reduces per-worker memory + cold starts; **incompatible** with preview URLs, skew protection, and `@opennextjs/cloudflare deploy`. → `references/advanced.md` - **Skew protection** (preview-URL-based version matching) — `cloudflare.skewProtection.enabled`, `run_worker_first: true`, `getDeploymentId()`, env vars `CF_WORKER_NAME`/`CF_PREVIEW_DOMAIN`/`CF_WORKERS_SCRIPTS_API_TOKEN`/`CF_ACCOUNT_ID`. **Disabled for Workers with a Durable Object** (move DOs to a separate worker). → `references/advanced.md` ## Top Errors (full catalog → `references/error-catalog-extended.md`) ### 1. Worker size limit exceeded `"Your Worker exceeded the size limit of 3 MiB"` (Free) / `"10 MiB"` (Paid). Only **gzip** size counts. Free → upgrade to Paid. Paid → analyze bundle: `npx @opennextjs/cloudflare build`, then inspect `.open-next/server-functions/default/handler.mjs.meta.json` (visualize with ESBuild Bundle Analyzer); remove unused deps, use dynamic imports. ### 2. Cannot perform I/O on behalf of a different request Global DB client (e.g. `postgres`, `pg` Pool) reused across requests. Create the client **inside** the request handler (or use `cache()` from `react`), and `maxUses: 1` for PG pools. ### 3. NPM package import / "Could not resolve \<package\>" Enable `nodejs_compat`, ensure `compatibility_date ≥ 2024-09-23`. Some packages ship a `workerd` export — add them to `serverExternalPackages` in `next.config.ts` (e.g. `@prisma/client`, `.prisma/client`, `postgres`, `jose`, `react-textarea-autosize`, `@libsql/isomorphic-ws`). Or set `.env`: `WRANGLER_BUILD_CONDITIONS=""` + `WRANGLER_BUILD_PLATFORM="node"`. ### 4. SSRF (CVE-2025-6087) — versions < 1.3.0 `/_next/image` SSRF. Upgrade immediately: `@opennextjs/cloudflare@^1.3.0` (current: `^1.18.1`). ### 5. Failed to load chunk `server/chunks/ssr/<name>.js` Outdated adapter with Turbopack builds. Upgrade `@opennextjs/cloudflare` to latest, or switch to webpack (`next build` without `--turbo`). ### 6. `ReferenceError: FinalizationRegistry is not defined` `compatibility_date` too old. Set `"compatibility_date": "2025-05-05"` (or later) in `wrangler.jsonc`. ### 7. `Uncaught ReferenceError: __name is not defined` Wrangler's esbuild `keep-names` injects `__name` into generated script strings that some libs (e.g. `next-themes`) eval at runtime. Set `"keep_names": false` in `wrangler.jsonc` (requires **Wrangler ≥ 4.13.0**). You lose original function names in debugging. ### 8. "Failed to send request to R2 worker" / 403 during `populateCache remote` Account protected by Cloudflare Access blocks the `open-next-cache-populate` helper worker. Do **not** create a separate Access app for it; add a Service Auth policy (Include = Any Access Service Token) to the existing app covering `*.<account>.workers.dev`, create a service token, and export `CLOUDFLARE_ACCESS_CLIENT_ID` / `CLOUDFLARE_ACCESS_CLIENT_SECRET`. ## Known Open Bugs (live tracker) Always check the issue tracker — these are recurring at the time of writing: | # | Bug | Workaround | |---|---|---| | [#1171](https://github.com/opennextjs/opennextjs-cloudflare/issues/1171) | **v1.18.0 breaks R2 cache population** (pinned) | Pin to 1.17.x or upgrade past the fix |
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기