メインコンテンツへスキップ
kt-tech.blog

【設計】Cloudflare Workers→Pages出戻り記 — OpenNextのTTFBが遅すぎた話

設計6分で読めます

この記事でわかること

  • Cloudflare Pages(CDN直接)と Workers(Worker経由)で TTFB にどれだけ差が出たかの実測値
  • 「SSG が使える = 速い」とは限らない理由
  • Pages → Workers → Pages と戻すときに実際に必要だった作業

Next.js App Router / Cloudflare へのデプロイ経験。なおこれは 2026年3月時点の判断で、現在は next-on-pages が非推奨・Pages がメンテナンスモードになっています(本文冒頭の注記を参照)

📌 概要: Cloudflare Pages(Edge Runtime)の制約が厳しくてOpenNext経由でCloudflare Workersに移行したが、TTFBが3-6秒と遅すぎてPagesに出戻りした判断記録。それぞれのメリット・デメリットと、移行・出戻りの具体的手順を残します。

注意

これは 2026年3月時点の判断記録です。現在は前提が変わっています。

  • @cloudflare/next-on-pages は非推奨になり、Cloudflare は OpenNext アダプタへの移行を案内しています
  • Cloudflare Pages は事実上メンテナンスモードで、新機能は Workers 側にのみ入ります

つまり、この記事の結論(Pages に戻す)は現在の推奨とは逆です。ただし、下記の計測値と「SSG が使える = 速いとは限らない」という学びは、どちらを選ぶにしても使えるはずです。これから新規で選ぶなら Workers + OpenNext を検討してください。

はじめに

Notion APIをCMSとして使う技術ブログをCloudflare Pagesで運用していたが、Edge Runtimeの制約に悩まされていた。

@opennextjs/cloudflareを使えばWorkers上でNode.js互換モードで動き、SSGも使えると知り、移行を決意。しかし結果的にはPagesに戻すことになった。

1. なぜWorkersに移行したか

Pages (Edge Runtime) の制約

  • export const runtime = 'edge' が全動的ルートに必須
  • crypto, fs, path 等のNode.js APIが使えない
  • @notionhq/clientcrypto依存で動かない
  • cheerio等のNode.js依存パッケージも動かない
  • generateStaticParams()が使えず、SSG不可

Workers (OpenNext) の魅力

  • Node.js互換モードでnpmパッケージがそのまま動く
  • generateStaticParams() + SSGが使える
  • ISRもサポート

これは移行するしかない、と思った。

2. Workers移行でやったこと

セットアップ

Bash
npm install @opennextjs/cloudflare wrangler esbuild

設定ファイル

TypeScript
// open-next.config.ts
import { defineCloudflareConfig } from '@opennextjs/cloudflare';
export default defineCloudflareConfig({});

そして wrangler.toml の設定:

TOML
# wrangler.toml
name = "my-blog"
main = ".open-next/worker.js"
compatibility_date = "2025-03-14"
compatibility_flags = ["nodejs_compat"]

SSG対応

generateStaticParams()で全ページを静的生成し、ビルド時に全記事のHTMLを事前生成。

有料プランが必要

Workers無料プランはCPU時間10ms制限。Next.jsのSSRはそれを超えるため、$5/月の有料プランにアップグレード。

3. Workersの問題点 — TTFBが遅すぎた

計測結果

ページ Workers (OpenNext) 期待値
TOP 3.2s <0.5s
記事詳細 5.8s <1s
記事一覧 4.1s <1s

SSGで全ページを静的生成しているはずなのに、TTFBが3-6秒。

原因分析

  • WorkersはSSG生成済みHTMLもWorker経由で返す(CDN直接ではない)
  • Workerのコールドスタート時間がかかる
  • Notion APIのレート制限でビルド中に503エラーが多発
  • 結果的にSSGとして機能しない記事が多数あった
ポイント
この2つは分けて考える必要があります。上2つは Workers のアーキテクチャの話ですが、下2つは「ビルド時に Notion API が 503 を返し、そもそも SSG が成立していなかった」という別の問題です。後者はリトライやビルド時のレート制御で改善できた可能性があり、「Workers だから遅い」と断定するにはここを切り分けるべきでした

⚠️ 教訓: SSGが使える = 速い、とは限らない。Workersは静的ファイルもWorker経由で返すため、CDNから直接返すPagesより遅くなることがある。

4. Pagesに戻した手順

コード変更

  1. 全動的ルートに export const runtime = 'edge' を追加
  2. generateStaticParams() を全削除(Edge Runtimeと非互換)
  3. @opennextjs/cloudflare, esbuild を削除
  4. @cloudflare/next-on-pages を再インストール
  5. open-next.config.ts, wrangler.toml を削除
  6. Next.js 16→15.1.0にダウングレード(v16はTurbopack強制でEdgeビルド非互換)

インフラ変更

  1. Cloudflare Workersスクリプトを削除
  2. 新規Pagesプロジェクトを作成
  3. DNSのCNAMEレコードをPages向けに変更
  4. Pagesにnodejs_compatフラグと環境変数を設定
  5. CI/CDをPagesデプロイに更新

5. Pages出戻り後のTTFB

ページ Workers Pages + Cache Rule
TOP 3.2s 0.07s
記事詳細 5.8s 0.064s
記事一覧 4.1s 0.073s

Pages + CDN Cache Ruleの組み合わせでWorkersより圧倒的に速くなった。

6. 結論: どちらを選ぶべきか

要件 Pages Workers (OpenNext)
静的サイトのTTFB CDN直接 △ Worker経由
SSRのTTFB ○ + Cache Rule △ コールドスタート遅い
Node.js API ❌ 使えない 使える
SSG ❌ Edgeと非互換 対応
npmパッケージ互換性 △ 制約あり 高い
コスト 無料 ○ $5/月
CDNキャッシュ Cache Ruleで強力 △ 制御しづらい

個人ブログ・コンテンツサイト: Pages + Cache Ruleがおすすめ。CDNから直接返却されるため圧倒的に速い。

複雑なアプリケーション: Workers (OpenNext)が向く。Node.js APIやISRが必要な場合。

Tips

  • Pagesでの最大の弱点「SSGが使えない」はCache Ruleで補える。 実質的に同じ効果が得られる
  • Workersの有料プラン($5/月)は解約しても期間終了まで使える。
  • DNSのCNAME変更後はネガティブキャッシュ(最大30分)に注意。 携帯や別のDNSを使うユーザーからはアクセスできない時間帯がある

参考リンク

まとめ

  • OpenNextはNode.js互換性が魅力だが、Worker経由のTTFBがボトルネックになる
  • PagesはCDN直接返却のため静的コンテンツが圧倒的に速い
  • SSGがなくてもCache Ruleで実質的に同じ効果が得られる
  • 「とりあえずSSGにしたい」だけのために Workersに移行するのは危険
  • 移行前に実際のTTFBを計測して判断することが大事

更新履歴

  1. 本文に残っていた誤字を修正(效果→効果)。「この記事でわかること」「対象読者」を概要プロパティへ移動。関連記事へのリンクを参考リンクに追加。
  2. next-on-pages の非推奨化と Pages のメンテナンスモード化を冒頭に注記。TTFB 遅延の原因を「Workers の構造」と「Notion API の 503」に切り分け。誤字修正