🍞
🍞 Next.js を OpenNext で Cloudflare Workers にデプロイする
この記事でわかること
- なぜ Pages ではなく Workers + OpenNext に移行したのか
- workerへのnextjsデプロイ方法
- OpenNext × Cloudflare の最短キャッシュ実装
- 小規模PJでの推奨構成・設定例
背景:Pagesの限界と SSR 導入
- 今回、ユーザープロフィール👥(例:/{username})などでサーバーサイドのデータ取得(Server Component の server fetch、動的パラメータ)を導入しました。これにより、静的エクスポートができないのでSSR前提で.nextを指定してのデプロイになるのですが、以下の問題が発生します。
⚠️Cloudflare Pages には単一アセット 25MBの制限⚠️
- OpenNext の Cloudflare アダプタを使えば、Next.js のビルドを Workers で実行する形へ変換でき、SSR/ISR を含む配信が可能になります。これによりキャッシュも軽量に考慮したSSRでのCloudflareデプロイが可能になります。25MBの制限関係なく!🧙
| 手法 | 特徴 | メリット | デメリット |
|---|---|---|---|
| SSG | ビルド時に静的HTML生成 | 超高速、SEOに強い | 更新に再ビルド必須 |
| ISR | SSG + 有効期限で再生成 | 高速+更新性 | 再生成の仕組みが複雑 |
| SSR | リクエストごとに生成 | 常に最新、柔軟 | レイテンシ・コスト増 |
とりあえずopennextjsでworkerにデプロイまで行う🚀
前提
- Next.js 15.x
- Cloudflare アカウントと Wrangler CLI
1. パッケージの導入
- opennextを追加します📦
# OpenNext Cloudflare adapter
bun add @opennextjs/cloudflare
2. package.json にスクリプト追加
- buildやdeployのスクリプト入れておきます。🚀
{
"scripts": {
"dev": "next dev",
"build": "next build",
"preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
"deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy"
}
}
3. wrangler.jsonc の設定
- プロジェクト直下に wrangler.jsonc を用意します。
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "my-next-app", // 書き換えてください
"main": ".open-next/worker.js",
"compatibility_date": "2025-01-01", // 互換性用のメモ 現在の日付📆に
"compatibility_flags": [
"nodejs_compat"
],
"assets": {
"directory": ".open-next/assets",
"binding": "ASSETS"
}
}
4. OpenNext 設定(ISR を使う場合)
- ISR(Incremental Static Regeneration)を使うなら、R2 バケットをキャッシュ用に用意しておきます。⚡
// open-next.config.ts ルートにおいてください。
import { defineCloudflareConfig } from "@opennextjs/cloudflare";
import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache";
export default defineCloudflareConfig({
incrementalCache: r2IncrementalCache,
});
- wrangler.jsonc に R2 バインディング
wrangler.jsonc
{
"r2_buckets": [
{
"binding": "NEXT_INC_CACHE_R2_BUCKET",
"bucket_name": "next-inc-cache"
}
]
}
- これで ISR のキャッシュが R2 に保存され、安定運用ができます。
静的アセットのキャッシュも忘れないうちにやっておきましょう
- public/配下に_headersという普通のファイル作ってください。1年間の長期キャッシュ設定
/_next/static/*
Cache-Control: public,max-age=31536000,immutable
5. デプロイ
bun run deploy
ISR (Incremental Static Regeneration)って何?
- Next.js が持つ SSG の拡張版です。
- ビルド時に静的 HTML を生成するのは同じ何ですけど、ページごとに「有効期限(revalidate 秒数)」を設定できて動的なデータ返却が可能になります。
- 有効期限が切れたページにリクエストが来たとき:
👉キャッシュ済みの古いページを即返す(ユーザーは待たされない)
👉裏で新しい HTML を生成してキャッシュを更新
👉次のユーザーからは新しい HTML を受け取れる
特徴 - メリット: 静的の速さと、更新の柔軟さを両立できる
- デメリット: 初回の再生成リクエストが遅れる場合あり。複雑なキャッシュ管理が必要
ISR OpenNext+Cloudflare Workers Cache
OpenNext + Cloudflare Workers の場合、ISR の「キャッシュ保存先」として Cloudflare の仕組みを利用します。
- Incremental Cache (R2 など) に HTML を保存
- Queue (Durable Objects) が「どのページを再生成するか」を管理
- Tag Cache (D1/DO) が revalidateTag のような任意の無効化に対応
つまり Cloudflare が「ISR の裏方倉庫と配達員」みたいな役割を果たしています。
アナロジーでまとめてみる
- SSG: 「パン屋🍞で全部のパンを朝焼いて並べておく」 → 常に速いけど品切れや更新が面倒
- ISR: 「朝焼いたパン🍞を並べつつ、◯分ごとに人気パンだけ焼き直して補充」 → 品質と効率の両立
- Cloudflare のキャッシュ: 「街中にあるパンの置き倉庫🏭」 → ユーザーに近い倉庫からすぐ配達できる
推奨構成(小規模)
- Incremental Cache:R2
wrangler.jsonc
{
"name": "<WORKER_NAME>",
"main": ".open-next/worker.js",
"compatibility_date": "2024-12-30",
"compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"],
"assets": { "directory": ".open-next/assets", "binding": "ASSETS" },
"services": [
{ "binding": "WORKER_SELF_REFERENCE", "service": "<WORKER_NAME>" }
],
// R2 incremental cache
"r2_buckets": [
{ "binding": "NEXT_INC_CACHE_R2_BUCKET", "bucket_name": "<BUCKET_NAME>" }
]
}
open-next.config.ts
import { defineCloudflareConfig } from "@opennextjs/cloudflare";
import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache";
export default defineCloudflareConfig({
incrementalCache: r2IncrementalCache,
});
R2 に Incremental Cache を置くだけでも、まずは ISR を動かせます。
Queue や Tag Cache は必要になったら導入すればOK。
"r2_buckets": [
{
"binding": "NEXT_INC_CACHE_R2_BUCKET", // 変数名
"bucket_name": "hogehoge-cache" // 新しくcache用のバケット作成
}
- 画像バケットなどと混同すると、CORS/認可/権限などがごちゃつきます。非公開にしてworkersからのみアクセスできるようにした方がいいです。
最後に
最小ステップ
Pages → Workers(OpenNext)
1. @opennextjs/cloudflare と wrangler を導入
2. wrangler.jsonc を用意(main: .open-next/worker.js、bindings など)
3. open-next.config.ts で R2/Queue/Tag Cache を設定
4. package.json に
build: next build
preview: opennextjs-cloudflare build && opennextjs-cloudflare preview
deploy: opennextjs-cloudflare build && opennextjs-cloudflare deploy
を追加
5. public/_headers で静的アセットの長期キャッシュ
6. bun run deployでリリース
Discussion