1.はじめに
本記事では、Next.jsで構築したアプリケーションを、Cloudflare Workersへデプロイする手順を解説します。
この記事で学べること
- Cloudflareのテンプレート機能を使ったNext.jsプロジェクトのセットアップ
- GITHUBと連携したCI/CD環境の自動構築
- SSG, SSR, ISRの各レンダリング方式の実装とデプロイ
私が設定でつまずいたISRに必要なR2バケットの連携方法も解説します。Vercel以外のホスティング先を探している方や、Cloudflareの無料枠を活用して構築したい方に向けて記事を書きました。
2. Next.js Framework Starter
デプロイ方法は、既存プロジェクトを使用 または Next.js Framework Starter(テンプレート)で新規プロジェクトを使用する2通りの方法があるのですが、テンプレートを使用する方が確実(ミスが減り、もし失敗した場合に原因箇所を特定しやすい)なため、今回はテンプレートで説明します。
テンプレートを使用するといきなりNext.jsの初期画面が公開(Cloudflareから自動発行されるURLで、独自ドメインの設定も可能)された状態になりますが、非公開設定もでき、GITHUB連携+CI/CDの環境もボタンのみで(設定)構築できるメリットがあります。
テンプレートにはopennextのパッケージが使用されており、このパッケージがデプロイ等に利用されています↓
-
公式サイト:
https://opennext.js.org/ -
公式サイト(スタートマニュアル):
https://opennext.js.org/cloudflare/get-started
3.前提
(2025年11月時点の情報です)
Cloudflare(https://www.cloudflare.com/ )のアカウント登録(無料)が必要です。
ただし、ISRをデプロイする場合、キャッシュ保存用のR2バケットが必要になります。R2には無料枠(月間10GBのストレージ、Aクラス操作100万回/月、Bクラス操作1000万回/月など)がありますが、利用開始にはクレジットカードの登録が必要です。小規模なプロジェクトであれば、無料枠を超えることは少ないと思います。
使用するバージョン
本記事で動作確認している主要なパッケージのバージョンは以下の通りです。
- Next.js: 15.5.3
- @opennextjs/cloudflareは現在Next.js 14および15をサポート
- @opennextjs/cloudflare: ^1.12.0
-
npm view @opennextjs/cloudflare versionsで最新版を確認できます
-
- wrangler: ^4.47.x
- 公式ドキュメントでWrangler v3.99.0以上が推奨されているため、新しいバージョンを使用します。
4.手順
Cloudflareログイン後、Next.js Framework Starterから作成
ホーム画面の左側「コンピューティングとAI」→「Workers & Pages」→ 「アプリケーションを作成」→「テンプレートを選択」→「Next.js Framework Starter」→「デプロイ」ボタンを押下する
Next.js Framework Starterのデプロイ設定
画像のようにGit アカウントを選択し(GITHUB連携。連携していない場合、連携設定画面に案内される)、プライベート Git リポジトリを作成するにチェックをいれ、作成デプロイボタンを押下します。プロジェクト名はNext.jsのプロジェクト名になります。
ビルドおよびデプロイのコマンドと詳細設定はデフォルトのままで大丈夫ですが、別プロジェクトでCloudflareとGITHUB連携している場合 かつ APIトークンは別で管理したい場合は、API トークンを新規(今回のデプロイ用)で作ることも可能です。
「作成とデプロイ」ボタンを押下後、ビルド実行中の画面に移動するので、ビルドとデプロイが完了するの待ちます。
デプロイURL確認
ビルドとデプロイが完了後、画像のように「概要」に公開URLが発行されるので、そのURLからデプロイしたNext.js初期画面が確認できます。
備考で、「デプロイ」はビルドやデプロイしたバージョン履歴の確認や変更が可能です。
「設定」は環境変数(ローカルの.envファイルで設定する値を設定する)、ビルドに使用するコマンド、URL公開や非公開(ドメインを無効)の確認や変更が可能です。
R2でバケットの作成をする
ISRを含めてNext.jsを構築する場合、キャッシュ用のバケットを作成してください。ISRを使用しない場合はこの手順を飛ばしても大丈夫です。
バケット作成は、ホーム画面の左側「ストレージとデータベース」→「概要」→ 「バケット作成」からバケット名(任意名)を入力し、「バケットを作成」を押下すれば作成できます。
GITHUBからクローン
画像のように、GITHUBに先ほどデプロイしたリポジトリがあるので、これをローカルにクローンします(クローンのやり方は省略します。)
ローカルでISRの設定をする。
incrementalCache: r2IncrementalCacheがコメントされているので有効にします↓
import { defineCloudflareConfig } from "@opennextjs/cloudflare";
import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache";
export default defineCloudflareConfig({
incrementalCache: r2IncrementalCache,
});
"r2_buckets" :[]を追記します。
"bucket_name" はR2で作成バケット名にしてください↓
/**
* For more details on how to configure Wrangler, refer to:
* https://developers.cloudflare.com/workers/wrangler/configuration/
*/ {
"$schema": "node_modules/wrangler/config-schema.json",
"name": "next-test",
"main": ".open-next/worker.js",
"compatibility_date": "2025-10-08",
"compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"],
"assets": {
"binding": "ASSETS",
"directory": ".open-next/assets"
},
"observability": {
"enabled": true
},
"upload_source_maps": true,
"r2_buckets": [
{
"binding": "NEXT_INC_CACHE_R2_BUCKET",
"bucket_name": "next-test-cache" // 作成したバケット名
}
]
}
デフォルトの設定ではISRの設定がされていないので、上記のようにISRが反映されるようファイルを修正します。ISRを使用しない場合はこの手順を飛ばしても大丈夫です。
参考にしたサイト:
https://opennext.js.org/cloudflare/get-started (公式)
https://zenn.dev/taksnr/articles/5b4108ad14fcad
ローカルでパッケージを更新して、SSG・SSR・ISRの表示ファイルを作成する
まずは、package.jsonのdependenciesやdevDependenciesのバージョンを変更します↓
{
"name": "next-test",
"version": "0.1.0",
"private": true,
"description": "Next.js app deployed on Cloudflare.",
"cloudflare": {
"label": "Next.js Framework Starter",
"products": [
"Workers"
],
"categories": [],
"preview_icon_url": "https://imagedelivery.net/wSMYJvS3Xw-n339CbDyDIA/05eee9e0-2c04-48fd-11bf-84e65f839000/public",
"preview_image_url": "https://imagedelivery.net/wSMYJvS3Xw-n339CbDyDIA/4e913a56-fd99-4372-0586-9f1364173100/preview",
"publish": true
},
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
"preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
"check": "npm run build && tsc",
"cf-typegen": "wrangler types --env-interface CloudflareEnv env.d.ts",
"lint": "next lint"
},
"dependencies": {
"@opennextjs/cloudflare": "^1.12.0",
"next": "15.5.3",
"react": "19.1.0",
"react-dom": "19.1.0"
},
"devDependencies": {
"@eslint/eslintrc": "^3.1.0",
"@tailwindcss/postcss": "^4.1.4",
"@types/node": "^24.0.4",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"eslint": "^9.27.0",
"eslint-config-next": "15.5.3",
"tailwindcss": "^4.1.1",
"typescript": "^5.8.3",
"wrangler": "^4.47.x"
}
}
公式ドキュメントには「Wrangler version 3.99.0以上を使用する必要があります」という記載があるので、wranglerのバージョンを最新に変更しました。
@opennextjs/cloudflareも最新にしないとビルド後の確認画面がエラー(以下の画像内容)になったので、こちらも最新しました。※@opennextjs/cloudflareインストールできるバージョンはnpm view @opennextjs/cloudflare versions で確認できます。
その他もできるだけ推奨または最新に変更しました。影響がない部分は適切に追記・削除・変更して大丈夫だとは思います。
package.jsonの修正が完了できたらパッケージをインストールしていきます↓
cd <クローンしたプロジェクト名>
# 既存の生成物やロックファイルを削除
rm -rf node_modules .open-next .next .wrangler package-lock.json next-env.d.ts
# npmのキャッシュをクリア
npm cache clean --force
npm install
補足: npm install時にrclone.jsに関するエラーが発生する場合があります。その際は、以下のコマンドでインストールを試みてください↓
npm install --ignore-scripts
SSG用ファイル作成します。Next.js App Routerはデフォルトで静的レンダリング(SSG)を試みるためexport const dynamic = "force-static";は厳密には不要な場合もありますが、挙動を明示するために記載しています↓
export const dynamic = "force-static"; // 明示的にSSGを指定(build時に生成)
export default async function Page() {
const time = new Date().toISOString();
return (
<main>
<h1>SSG Test Page</h1>
<p>{time}</p>
</main>
);
}
SSR用ファイル作成します。force-dynamicを指定すると、リクエスト毎にサーバーでレンダリングされます↓
export const dynamic = "force-dynamic"; // 毎回リクエスト時に生成
export default async function Page() {
const time = new Date().toISOString();
return (
<main>
<h1>SSR Test Page</h1>
<p>{time}</p>
</main>
);
}
ISR用ファイルを作成します。revalidateに秒数を指定することで、指定した時間が経過した後の次のアクセスでページが再生成(Revalidate)されます↓
export const revalidate = 60; // 1分ごとに再生成
export default async function Page() {
const time = new Date().toISOString();
return (
<main}>
<h1>ISR Test Page</h1>
<p>Last rendered: {time}</p>
</main>
);
}
preview(ローカル)でISR・SSG・SSRの表示を確認
ローカルの確認もcloudflare用のコマンドを実行して確認します↓
npm run preview
※このコマンドは時間がかかるので、通常の確認はnpm run devでして、ISRやSSGの確認をしたい場合のみnpm run previewを使用すると良いと思います。
ビルド完了後、ターミナルにURL(ポート番号)が表示されるので、それをブラウザで確認します。
- http://localhost:xxxx/ssg → リロードしても時間が変更されないか確認
- http://localhost:xxxx/ssr → リロードするごとに時間が変更されるか確認
- http://localhost:xxxx/isr → 1分ごとリロードして時間が変更されるか確認(1分未満の場合は変更されないこと)
本番環境にデプロイ
ローカル環境でISR・SSG・SSRの表示が成功したら、npm run deployでも直接反映できるみたいですが、既にGITHUBとcloudflareが連携されているので、GITHUBにpush(git push origin main)するだけデプロイが完了します。(pushの説明は省略します)
push後、cloudflareのデプロイ画面でビルドとデプロイが上記のように成功していたら、本番URLを確認します↓
- https://公開ドメイン/ssg → リロードしても時間が変更されないか確認
- https://公開ドメイン/ssr → リロードするごとに時間が変更されるか確認
- https://公開ドメイン/isr → 1分ごとリロードして時間が変更されるか確認(1分未満の場合は変更されないこと)
5.終わりに
この基盤を利用すれば、SSG・SSR・ISRを使い分けてスピードや負荷対策などができるので、小規模なアプリケーションなら、AWSやVercelよりcloudflareを使用する方が個人的にコスパが良いと思いました。









