
【設定・環境構築】OpenNext でNext.js SSGサイトをCloudflare Workersにデプロイする完全ガイド
[toc]
はじめに
-
Cloudflare PagesでNext.jsサイトを運用していたが、Edge Runtime制約が厳しくなった
-
microCMSからNotion APIへの移行に伴い、Node.jsランタイムが必要になった
-
@cloudflare/next-on-pagesはEdge Runtime必須で制約が多い
-
OpenNext(@opennextjs/cloudflare)を使えばNode.js互換でCloudflare Workers上でNext.jsが動く
この記事でわかること
-
OpenNextのセットアップ手順
-
SSG(Static Site Generation)対応の設定
-
wrangler.toml の詳細設定
-
GitHub ActionsによるCI/CD構築
-
Workers有料プランが必要な理由
対象読者
-
Cloudflare WorkersでNext.jsを動かしたい方
-
Cloudflare PagesのEdge Runtime制約に困っている方
-
Next.jsのSSGサイトをCloudflareにデプロイしたい方
1. なぜOpenNextか
@cloudflare/next-on-pages の制約
@cloudflare/next-on-pagesはCloudflare Pages向けのアダプターだが、以下の制約がある:
-
Edge Runtime必須: すべてのルートが
export const runtime = 'edge'を要求される -
Node.js APIが使えない:
crypto,fs,path等のNode.jsモジュールが利用不可 -
npm パッケージの制約: Node.js APIに依存するパッケージ(@notionhq/client, cheerio等)が動かない
OpenNextのアプローチ
@opennextjs/cloudflareはCloudflare WorkersのNode.js互換モードを活用し、Next.jsをほぼそのまま動かす。
-
Node.js APIが使える(crypto, Buffer等)
-
npm パッケージの互換性が高い
-
ISR / SSG / SSR すべてサポート
2. セットアップ
インストール
npm install @opennextjs/cloudflare
npm install -D wrangler
# esbuildの明示的インストールが必要
npm install -D esbuild
open-next.config.ts
import { defineCloudflareConfig } from '@opennextjs/cloudflare';
export default defineCloudflareConfig({});
wrangler.toml
#:schema node_modules/wrangler/config-schema.json
name = "kt-tech-blog"
main = ".open-next/worker.js"
compatibility_date = "2025-03-14"
compatibility_flags = ["nodejs_compat"]
[assets]
directory = ".open-next/assets"
binding = "ASSETS"
# KVはISRキャッシュに使用
[[kv_namespaces]]
binding = "NEXT_CACHE_WORKERS_KV"
id = "your-kv-namespace-id"
package.json のスクリプト更新
{
"scripts": {
"build": "opennextjs-cloudflare",
"dev": "next dev",
"deploy": "opennextjs-cloudflare && wrangler deploy",
"preview": "opennextjs-cloudflare && wrangler dev"
}
}
3. SSG対応
generateStaticParamsで全ページパスを生成
SSGでは、ビルド時に全ページのパスを静的に生成する必要がある。
// src/app/blogs/[blogId]/page.tsx
export async function generateStaticParams() {
const allBlogs = await getAllBlogs(); // Notion APIから全記事取得
return allBlogs.map((blog) => ({
blogId: blog.id,
}));
}
ビルドワーカー数を1に制限
Notion APIにはレート制限(3リクエスト/秒)があるため、ビルド時の並列度を制限する。
// next.config.js
module.exports = {
experimental: {
workerThreads: false,
cpus: 1, // ビルドワーカー数を1に制限
},
};
API呼び出し間隔の制御
// libs/notion.ts
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
export async function getAllBlogs(): Promise<Blog[]> {
const pages = [];
let cursor: string | undefined;
do {
const response = await notion.dataSources.query({
data_source_id: DATABASE_ID,
start_cursor: cursor,
});
pages.push(...response.results);
cursor = response.next_cursor ?? undefined;
await delay(350); // 350ms間隔でAPI呼び出し
} while (cursor);
return pages.map(pageToBlog);
}
4. CI/CD — GitHub Actions
ワークフロー定義
# .github/workflows/deploy.yml
name: Deploy to Cloudflare Workers
on:
push:
branches: [main]
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- name: Build with OpenNext
run: npx opennextjs-cloudflare
env:
NOTION_TOKEN: ${{ secrets.NOTION_TOKEN }}
NOTION_DATABASE_ID: ${{ secrets.NOTION_DATABASE_ID }}
- name: Deploy to Cloudflare Workers
run: npx wrangler deploy
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
Worker Secretsの同期
ランタイムで使用する環境変数はWorker Secretsに設定する必要がある。
# Worker Secretsに環境変数を設定
echo "your-notion-token" | npx wrangler secret put NOTION_TOKEN
echo "your-database-id" | npx wrangler secret put NOTION_DATABASE_ID
echo "your-ga-id" | npx wrangler secret put NEXT_PUBLIC_GA_ID
5. Workers有料プランが必要
無料プランの制約
Cloudflare Workers無料プランにはCPU時間10msの制限がある。Next.jsのSSRレンダリングはこの制限を大幅に超えるため、無料プランでは動作しない。
エラー例
Error 1102: Worker exceeded CPU time limit
有料プラン($5/月)
Workers Paid プラン($5/月)にアップグレードすると:
-
CPU時間: 10ms → 30秒
-
リクエスト数: 10万/日 → 1000万/月
-
Workers KV: 読み取り10万/日 → 1000万/月
個人ブログの規模であれば$5/月で十分運用可能。
Tips
esbuildの明示的インストールが必要。OpenNextのビルドプロセスで使用されるが、peer dependencyとして自動インストールされないことがあるgetAllBlogsで全記事取得する際はdelay関数を挟むwrangler devでローカルプレビューする際は.dev.varsファイルに環境変数を設定するまとめ
-
OpenNextを使えばCloudflare Workers上でNext.jsがNode.js互換で動作する
-
SSG対応はgenerateStaticParamsで全パスを生成し、ビルドワーカー数を制限する
-
CI/CDはGitHub Actions + wrangler deployで簡単に構築可能
-
Workers有料プラン($5/月) が必須。無料プランのCPU 10ms制限では動かない
-
Worker Secretsの設定を忘れると503エラーが大量発生するので注意
最新記事
- 【設定・環境構築】OpenNext でNext.js SSGサイトをCloudflare Workersにデプロイする完全ガイド
2026/3/19
- 【実装】Notion calloutブロックをNext.jsでカラフルなUIコンポーネントとして表示する
2026/3/19
- 【トラブルシューティング】Cloudflare Pages → Workers 移行で遭遇したEdge Runtime問題集
2026/3/19
- 【実践】Next.js 13→16メジャーアップグレードの全記録 — 破壊的変更と対応策
2026/3/19
- 【自動化】Gemini Imagen APIでブログのeyecatch画像を自動生成してR2にアップロードする
2026/3/19
- 【実装】Notion APIでブログシステムを構築する(Next.js 13 App Router × SDK v5)
2026/3/19
- 【移行ガイド】microCMSからNotion APIへブログCMSを完全移行する
2026/3/19
- 【トラブルシューティング】本番デプロイで遭遇した問題と解決策まとめ
2026/3/15
- 【環境構築】Next.js × Cloudflare Workers の本番環境を一から構築する
2026/3/15
- 【設定・環境構築】Neon → Prisma Postgres 移行とローカル開発環境の構築
2026/2/26


