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

【設定・環境構築】Next.js アプリを OpenNext で Cloudflare Workers にデプロイする

設定・環境構築5分で読めます

この記事でわかること

  • OpenNext(@opennextjs/cloudflare)で Next.js を Workers 向けにビルドする手順
  • wrangler.jsonc の書き方と nodejs_compat_v2 で何が使えて何が使えないか
  • fs がない環境でファイルを読んでいた箇所の逃げ方
  • Pages と Workers をどちらにするかの判断基準(別記事との関係)

Next.js 15 以上(App Router)、Cloudflare アカウントと Workers の有効化、wrangler CLI が入っていること。

メモ
Next.js 16 (App Router) アプリを OpenNext (@opennextjs/cloudflare) を使って Cloudflare Workers にデプロイする方法を解説します。fs モジュール問題、Suspense 境界、wrangler 設定のポイントをまとめました。

はじめに

Next.js は Vercel 向けに最適化されているため、Cloudflare Workers で直接動かすことはできません。しかし OpenNext というブリッジライブラリを使うと、Next.js のビルド出力を Workers 互換に変換してくれます。

この記事では anoni アプリ(Next.js 16 / App Router)を Cloudflare Workers に移行した際の手順とハマりポイントを紹介します。

ポイント

別記事との関係について: 別記事の Cloudflare Workers→Pages出戻り記 では、このブログ自体を Workers から Pages に戻した話を書いています。矛盾しているように見えますが、対象が違います。あちらは「ほぼ静的なコンテンツサイト」で CDN 直返しの速さが勝ち、こちらは「Node.js API やセッションを使うアプリケーション」で Workers が向いています。

なお 2026 年時点では Cloudflare Pages がメンテナンスモードに入り、@cloudflare/next-on-pages も非推奨になりました。これから新規で選ぶなら、本記事の Workers + OpenNext が公式の推奨経路です。


1. OpenNext の導入

OpenNext は Next.js を Cloudflare Workers 向けにビルドするブリッジです。

Bash
bun add @opennextjs/cloudflare wrangler

設定ファイルを作成します。

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

2. wrangler.jsonc の設定

JSON
{
  "name": "anoni-dev",
  "main": ".open-next/worker.js",
  "compatibility_date": "2025-02-26",
  "compatibility_flags": ["nodejs_compat_v2"],
  "assets": {
    "directory": ".open-next/assets",
    "binding": "ASSETS"
  }
}
Tips
nodejs_compat_v2 フラグにより、Workers 上で一部の Node.js API がポリフィルされます。ただし fsnetchild_process などファイルや TCP を直接触る系は使えません。Workers にはそもそもファイルシステムがないので、ポリフィルの問題ではなく原理的な制約です。

3. fs モジュール問題の解決

キャラクタープロンプト(.md ファイル)を fs.readFileSync で読んでいた箇所がエラーになります。解決策は TypeScript の定数ファイルに変換して埋め込むことです。

TypeScript
const PROMPTS: Record<string, string> = {
  "char-a.md": `ここにプロンプト内容...`,
  "char-b.md": `ここにプロンプト内容...`,
};

export function getPrompt(fileName: string): string {
  const content = PROMPTS[fileName];
  if (!content) throw new Error(`Prompt not found: ${fileName}`);
  return content;
}
Tips
.md.ts の変換は一見不思議に見えるので、PR では「Workers には fs がない」背景を必ず記載しましょう。内容が大きい場合は、ビルド時に生成するか R2 などに置いて fetch する選択肢もあります。

4. Suspense 境界の追加

useSearchParams() を使うコンポーネントには Suspense 境界が必須です。これは Workers 固有の話ではなく、Next.js 15 以降の仕様です(ビルドが止まります)。

TypeScript
import { Suspense } from "react";

export default function ChatPage() {
  return (
    <>
      <Suspense>
        <WelcomeToast />
      </Suspense>
      <ChatPageContainer />
    </>
  );
}

5. ビルドとデプロイ

Bash
# Workers 向けビルド
npx opennextjs-cloudflare build

# デプロイ
npx wrangler deploy

Tips

メモ
OpenNext は活発に開発中です。Next.js のバージョンアップ時に互換性問題が起きる可能性があるので、OpenNext のリリースノートもチェックしましょう。
メモ
環境変数は wrangler secret put コマンドか、Cloudflare ダッシュボードの Workers 設定から追加できます。

まとめ

  • OpenNext (@opennextjs/cloudflare) を使えば Next.js App Router アプリを Workers にデプロイ可能
  • fs が使えない制約は、ファイル内容を TS 定数に変換して解決
  • useSearchParams() には Suspense 境界を忘れずに
  • nodejs_compat_v2 フラグで Node.js API の一部がポリフィルされる

更新履歴

  1. 別記事の「Workers→Pages 出戻り記」と矛盾して見えないよう、対象が違うこと(静的サイト vs アプリケーション)と、2026年時点では Workers + OpenNext が公式の推奨経路であることを冒頭に注記。コード例に入っていたプロダクト固有の名前を汎用な形に差し替え。Suspense 境界が Workers 固有ではなく Next.js 15 以降の仕様であることを明記。fs が使えない理由と他の選択肢を補足。コードブロックにファイルパスのキャプションを追加し、callout の色指定を他記事と揃えた。「この記事でわかること」「対象読者」「前提条件」を概要プロパティへ移動。

この記事のタグ