🗺️

【Next.js + OpenNext】Cloudflare WorkersでSentryにソースマップを自動アップロードする

に公開

Next.js 14 を OpenNext アダプタを使って Cloudflare Workers にデプロイする構成に、Sentry (@sentry/cloudflare) を導入し、ソースマップを自動アップロードしてエラーのスタックトレースを綺麗に見るところまでやりました。
手順と、いくつかハマったところを共有します。

前提環境

  • Framework: Next.js 14 (App Router)
  • Adapter: @opennextjs/cloudflare
  • Platform: Cloudflare Workers
  • Error Tracking: @sentry/cloudflare
  • Language: TypeScript

なぜハマったか

通常、Sentry のセットアップは npx @sentry/wizard を叩けば概ね完了します。しかし、OpenNext × Cloudflare Workers の構成では以下の問題が発生しました。

  1. Release 名の不一致: ランタイム(Worker)が認識するリリースIDと、Sentry にアップロードされたソースマップのリリースIDがズレてしまい、ソースコードが復元されない。
  2. ローカルデプロイの挙動: wrangler deploy コマンドは、デフォルトではローカルにバンドルファイル(dist ディレクトリなど)を出力しません。そのため、デプロイ直後に sentry-cli でアップロードしようとしても「ファイルがない」と怒られます。
    • --dry-run をつければ出力されますが、それでは本番デプロイができません。

なのでローカルからアップロードせず、Cloudflare 側のビルド環境で行うようにしています。

1. 実装の準備

まずはコード側の設定です。
https://docs.sentry.io/platforms/javascript/guides/cloudflare/

wrangler.jsonc

Wrangler の設定ファイルです。upload_source_maps: true が必須です。
また、Sentry の初期化処理を行う sentry-worker.tsmain に指定しています。

wrangler.jsonc
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "main": "sentry-worker.ts", // エントリポイントを変更
  "name": "your-worker-name",
  "compatibility_date": "2025-10-11",
  "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"],
  "upload_source_maps": true, // 必須
  "version_metadata": {
    "binding": "CF_VERSION_METADATA"
  },
  "assets": {
    "directory": ".open-next/assets",
    "binding": "ASSETS"
  },
  // ...その他設定
}

sentry-worker.ts

OpenNext が生成した Worker を Sentry でラップするファイルです。
ここで release: env.SENTRY_RELEASE を指定します。
(CF_VERSION_METADATA.idでもよいが、のちのコマンドと揃えることが重要)

sentry-worker.ts
import * as Sentry from "@sentry/cloudflare";

// @ts-ignore
import openNextWorker from "./.open-next/worker.js";

export default Sentry.withSentry(
  (env: any) => {
    return {
      dsn: env.SENTRY_DSN,
      // ここで環境変数からリリースIDを受け取る
      // これがないとソースマップと紐付かない
      release: env.SENTRY_RELEASE, 
      tracesSampleRate: 1.0,
    };
  },
  {
    async fetch(request: Request, env: any, ctx: any) {
      // Sentryの動作確認用エンドポイント
      const url = new URL(request.url);
      if (url.pathname === "/debug-sentry") {
        throw new Error("Sentry Test Error!");
      }

      return openNextWorker.fetch(request, env, ctx);
    },
  }
);

2. package.json のスクリプト整備

「Wrangler でデプロイ(同時にリリースIDを注入)」→「ソースマップのアップロード」をチェーンさせるコマンドを作成します。

package.json
{
  "scripts": {
    "dev": "FORCE_COLOR=true next dev",
    "build": "next build",
    
    // Cloudflare Dashboardから呼ぶコマンド
    "cf:deploy": "opennextjs-cloudflare deploy -- --keep-vars --outdir dist --upload-source-maps --var SENTRY_RELEASE:$(sentry-cli releases propose-version) && npm run sentry:sourcemaps",

    // ソースマップアップロード用(Wizardが生成するものと同じ)
    "sentry:sourcemaps": "_SENTRY_RELEASE=$(sentry-cli releases propose-version) && sentry-cli releases new $_SENTRY_RELEASE --org=YOUR_ORG --project=YOUR_PROJECT && sentry-cli sourcemaps upload --org=YOUR_ORG --project=YOUR_PROJECT --release=$_SENTRY_RELEASE --strip-prefix 'dist/..' dist"
  },
  "devDependencies": {
    "@sentry/cli": "^2.58.2",
    // ...
  }
}

コマンドの解説

cf:deploy コマンドでやっていることは以下の通りです。

  1. opennextjs-cloudflare deploy ...:
    • --outdir dist: ビルド成果物とソースマップを dist ディレクトリに出力させます(Cloudflare のビルド環境ならこれが残ります)。
    • --upload-source-maps: ソースマップ生成を強制します。
    • --var SENTRY_RELEASE:$(sentry-cli releases propose-version): sentry-cli が生成したリリースID(コミットハッシュ等)を、Worker の環境変数 SENTRY_RELEASE として注入しながらデプロイします。
  2. npm run sentry:sourcemaps: 直前に生成された dist 内のソースマップを、同じリリースIDで Sentry にアップロードします。

これにより、Worker が持っている Release ID と Sentry にある Release ID が一致します。

3. Cloudflare Dashboard での設定

ローカルからコマンドを叩くのではなく、Cloudflare Workers の自動デプロイ機能(Workers Builds)を使います。

  1. Cloudflare Dashboard にログインし、対象の Worker を開きます。
  2. Settings > Build & Deploy に移動します。
  3. Build configurations を以下のように設定します。
  • Build command: npx opennextjs-cloudflare build
    • ※Next.js のビルドと OpenNext の変換。
  • Deploy command: npm run cf:deploy
    • ※デプロイ〜ソースマップアップロード。
  1. Environment variables (Settings > Variables) に以下を追加します。
    • SENTRY_AUTH_TOKEN: ビルド時に必要
    • SENTRY_DSN: DSN

4. 動作確認

設定ができたら、プッシュして Cloudflare のデプロイを走らせます。

1. デプロイログの確認

Cloudflare のデプロイログを見て、sentry-cli sourcemaps upload が成功していることを確認します。

2. Sentry での確認

Sentry の管理画面に行き、Settings > Projects > Source Maps を確認します。新しいリリースにソースマップが紐付ることを確認します。

3. 実エラーでの確認

実際にデプロイされたサイトでエラーを発生させます。
Sentry の Issue 詳細画面で、TypeScript の元のソースコードが表示されていれば成功です。

まとめ

Next.js + OpenNext + Cloudflare Workers の構成で Sentry のソースマップを扱うポイントは以下の3点でした。

  1. ローカルアップロードしない: Cloudflare Dashboard の自動デプロイフローに乗せることで、dist ディレクトリの生成とアップロードを確実に行う。
  2. Release ID の同期: wrangler deploy の引数 --var で、デプロイ時に動的にリリースIDを注入する。
  3. コマンドの集約: デプロイ・アップロードを一つの npm script にまとめ、 Dashboard の Deploy command に設定する。

Discussion