CLAUDE LABEN
FORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられていますFORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられています
記事一覧/Claude Code
Claude Code/2026-04-21上級

Claude Code で Next.js × Cloudflare Workers の本番運用を乗り越える — バンドルサイズ危機からエッジキャッシュ設計まで、実際に詰まった場所と解決策を全公開

Next.js アプリを Cloudflare Workers で運用するとき、Claude Code は単なるコード補完ツール以上の存在になります。62 MiB バンドル制限・エッジキャッシュ設計・Content Split Architecture など、実運用で詰まった問題と解決策を完全公開。

Claude Code198Next.js7Cloudflare Workers14本番運用36トラブルシューティング37パフォーマンス最適化

プレミアム記事

「デプロイが通りません。理由がわかりません。」

Next.js アプリを Cloudflare Workers に乗せて本番運用している方なら、一度は経験があるのではないでしょうか。Vercel や AWS とは違う独特のランタイム制約、バンドルサイズ制限、エッジ環境での fs 不可……。これらは公式ドキュメントに書いてあっても、実際に踏んでみるまで「なぜこれが問題になるのか」が腑に落ちにくいのです。

私がこのサイト(Claude Lab)を Cloudflare Workers で運用し始めてから数ヶ月が経ちました。その間、Claude Code に助けてもらいながら乗り越えてきた本番トラブルをすべてお話しします。「公式ドキュメントには載っていないが、実運用で確実に踏む罠」を中心に、Claude Code との具体的なやりとりも含めて再現しています。


Cloudflare Workers 上で Next.js を動かすとは何が特殊なのか

まず前提を整理させてください。Vercel や Netlify で Next.js を動かすのとは、根本的に実行環境が違います。

Cloudflare Workers は V8 アイソレート上で動く JavaScript ランタイムです。Node.js API(特に fspathchild_process)が使えない、バンドルサイズに 62 MiB の上限がある、コールドスタートは高速だが実行時間に制約がある——これらの制約は、Next.js のエコシステムが「当たり前」として前提にしているものと相性が悪い部分があります。

OpenNext(@opennextjs/cloudflare)はその橋渡しをするアダプターですが、「動く」と「安定して動く」の間にはかなりの距離があります。

Claude Code はその距離を埋めるときに、単なるコード生成ツール以上の役割を果たします。具体的な理由は後で説明しますが、要は「制約を理解したうえで代替実装を提案できる」ところが強みです。


危機1:バンドルサイズが 62 MiB を超えてデプロイが壊れた

最初に直面した大きな壁です。

ある日を境に wrangler deploy が次のエラーで失敗するようになりました。

Error: Script startup exceeded CPU time limit.
Worker exceeded memory limit after assets traversal.

さらに詳しく調べると、wrangler.toml の assets チェックで:

⛔ Total asset size exceeds the 62 MiB limit.

原因は明白でした。記事数が増えるにつれて src/generated/articles.json が肥大化し、それがバンドルに含まれていたのです。

Claude Code との問題解決セッション

Claude Code に状況を伝えると、まず確認するよう言われたのが articles.json のサイズでした。

# Claude Code が最初に走らせたコマンド
ls -lh src/generated/articles.json
du -sh .next/
 
# 出力例
-rw-r--r--  1 user  staff   58M Apr 10 09:14 src/generated/articles.json

記事のHTMLコンテンツがすべて JSON に入っていたのが問題でした。Claude Code は数秒考えた後、こう提案しました。

articles.json にはメタデータだけを残して、HTML コンテンツは public/content/articles/{locale}/{category}/{slug}.html に個別ファイルとして出力する設計に切り替えましょう。Workers ASSETS バインディング経由でそのファイルを読み取る仕組みにすれば、バンドルサイズの問題を回避できます」

これが Content Split Architecture の発想です。

実装:generate-content.mjs の改修

scripts/generate-content.mjs を以下の方向で書き直しました。

// generate-content.mjs(Content Split Architecture 対応版)
 
import { remark } from 'remark'
import remarkRehype from 'remark-rehype'
import rehypeStringify from 'rehype-stringify'
import { unified } from 'unified'
import fs from 'fs/promises'
import path from 'path'
import matter from 'gray-matter'
 
const CONTENT_OUTPUT_DIR = 'public/content/articles'
 
async function processArticle(locale, category, slug, mdxContent) {
  const { data: frontmatter, content } = matter(mdxContent)
 
  // HTML に変換
  const vfile = await unified()
    .use(remarkParse)
    .use(remarkRehype)
    .use(rehypeStringify)
    .process(content)
 
  const html = String(vfile)
 
  // public/content/articles/{locale}/{category}/{slug}.html に出力
  const outputDir = path.join(CONTENT_OUTPUT_DIR, locale, category)
  await fs.mkdir(outputDir, { recursive: true })
  await fs.writeFile(path.join(outputDir, `${slug}.html`), html, 'utf-8')
 
  // articles.json にはメタデータのみ返す
  return {
    slug,
    category,
    title: frontmatter.title,
    description: frontmatter.description,
    date: frontmatter.date,
    level: frontmatter.level,
    premium: frontmatter.premium ?? false,
    tags: frontmatter.tags ?? [],
    highlights: frontmatter.highlights ?? [],
    author: frontmatter.author,
  }
}

変更後の articles.json のサイズは 58 MB から 1.2 MB に縮小されました。

content.ts での HTML 読み取り実装

Workers 環境では fs.readFile が使えないため、ASSETS バインディング経由でファイルを読み取ります。

// src/lib/content.ts
 
import { getCloudflareContext } from '@opennextjs/cloudflare'
 
export async function getArticleContent(
  locale: string,
  category: string,
  slug: string
): Promise<string | null> {
  try {
    const { env } = await getCloudflareContext()
    
    // ASSETS バインディングでファイルを取得
    // ⚠️ self-fetch(fetch('https://自ホスト/...'))は Workers で禁止
    const assetPath = `/content/articles/${locale}/${category}/${slug}.html`
    const response = await env.ASSETS.fetch(
      new Request(`https://dummy.internal${assetPath}`)
    )
 
    if (\!response.ok) return null
    return response.text()
  } catch (error) {
    console.error('[getArticleContent] error:', error)
    return null
  }
}

重要な落とし穴: fetch('https://claudelab.net/content/...') のように自ホストへの fetch を使うのは禁止です。Workers 環境では自己参照リクエストがタイムアウトします。必ず env.ASSETS.fetch() を使ってください。


ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
articles.json をメタデータのみに分離し、Worker バンドルを 62 MiB 制限の内側へ収める Content Split の具体的な実装手順
premium_token / article_purchases Cookie でエッジキャッシュを選択的にバイパスする cache-worker.js の設計と DEPLOY_VERSION 運用
ASSETS バインディングのインメモリキャッシュで記事 HTML の2回目以降のアクセスを高速化する getArticleContent の実測値つき実装
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

Claude Code2026-06-17
デプロイ直後に「500」と出るのに curl は 200 を返す — Next.js のエラー境界が ChunkLoadError を取り違えていた話
本番のNext.js記事ページがブラウザで「500 Internal Server Error」と表示されるのにcurlでは200。原因はサーバーではなくChunkLoadErrorとerror.tsxの誤表示でした。切り分け手順と自動リロードを組み込んだ修正を記録します。
Claude Code2026-05-28
Cloudflare Workers の 62 MiB 上限を踏んだ朝に、5,000 記事規模で組み直した Content Split アーキテクチャ
個人で 4 ブログを Cloudflare Workers + Next.js で運用していたある朝、articles.json が肥大化して Worker bundle が 62 MiB 上限を踏み、デプロイが止まりました。メタデータと HTML 本文を分離する Content Split Architecture に組み替えた具体的な実装と、切り替え 1 ヶ月で観測したビルド時間・キャッシュ効果・運用上の落とし穴を共有します。
Claude Code2026-05-22
Claude Code が書き出す MDX のフロントマターで YAML パースエラーが出る原因と対処
Claude Code に MDX 記事を量産させていると、ある日突然 YAML パースエラーで build が落ちます。ダブルクォート内のダブルクォート、引用符を含む日本語、コロンを含むタイトル — 引っかかる原因と、実運用で安定する5つの書き方を整理しました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →