2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ローカルでは動くのに本番で壊れる — 初めてのVercelデプロイで詰まる5つの地雷とClaude Codeへの聞き方

2
Posted at

「ローカルの npm run dev では完璧に動いていたのに、Vercel にデプロイした瞬間、画面が真っ白になった」

初めて自分のアプリをインターネットに公開しようとした未経験者が、ほぼ全員が一度は通る瞬間です。最近は「週末2日で家計簿アプリを作って Vercel で公開してみた」系の記事も増えて、"作って公開する" ハードルはどんどん下がっています。でも実際に自分でデプロイボタンを押すと、チュートリアルには載っていない小さな地雷を踏みます。しかもそのエラー、ローカルでは一度も出なかったやつです。

この記事は「デプロイ前のチェックリスト」ではありません。環境構築や .gitignore・環境変数の基本設定は前に別記事(Next.js+Supabaseアプリを初めてVercel公開する時の4大つまずきと最小の直し方)に書いたので、そちらに譲ります。

ここでは一歩進んで、実際にデプロイして「詰まった瞬間」に、エラー文をどう Claude Code に渡して抜けるかを実況します。各地雷を「症状 → 実際に出るエラー文 → AIへの聞き方(プロンプト) → 最小の直し方」の順で並べました。前提スタックは Next.js(App Router)+ Supabase + Vercel。未経験がこの構成で人生初のデプロイをする想定です。


地雷1: ローカルでは動くのに、Vercel のビルドで落ちる

いちばん最初にぶつかるのがこれです。手元では npm run dev がずっと緑だったのに、Vercel のデプロイログが赤くなって止まる。

出るエラーはだいたいこの2種類です。

Failed to compile.

./app/tasks/page.tsx:12:44
Type error: Property 'titl' does not exist on type 'Task'. Did you mean 'title'?

  12 |   {tasks.map((t) => <li key={t.id}>{t.titl}</li>)}
     |                                            ^
Module not found: Can't resolve '@/components/taskList'

なぜローカルでは気づけないのか。 理由は2つあります。

  1. next dev(開発サーバー)は型エラーがあっても動き続けますが、next build(本番ビルド)は型チェックで止まります。つまり手元で TypeScript の赤い波線を無視していると、Vercel で初めて表面化します。
  2. macOS / Windows のファイルシステムは大文字小文字を区別しませんが、Vercel(Linux)は区別しますTaskList.tsxtaskList と import してもローカルは通り、Vercel だけ Module not found になります。

Claude Code にはこう貼ります。エラーは省略せず全文を渡すのがコツです。

Vercel のデプロイでビルドが失敗しました。
ローカルの `npm run dev` では動いています。
以下が Vercel のビルドログの全文です。
考えられる原因を3つ、確認する順番つきで挙げてください。

(ここに赤いログを丸ごと貼る)

そして根本の対策は、ローカルで本番と同じビルドを一度走らせること。体感では、ビルドエラーの多くはこれで push 前に潰せます。

# push する前に、本番と同じビルドを手元で再現する
npm run build

「dev で動く」と「build が通る」は別物、と体で覚えるのがこの地雷の卒業条件です。


地雷2: ビルドは成功したのに、開くと真っ白

ビルドログは緑。デプロイ成功。URL を開いたら……真っ白。何も出ない。エラーページですらない。これも定番です。

まず F12 でブラウザのコンソールを開きます。だいたいこのどちらかが出ています。

Error: supabaseUrl is required.
Error: Hydration failed because the server rendered HTML didn't match the client.

パターンA: クライアント側の環境変数が undefined

Supabase のクライアントをブラウザから使うとき、環境変数に NEXT_PUBLIC_ を付け忘れると、本番で undefined になって落ちます。ローカルでは .env.local が効いていて気づけません。

// ❌ ブラウザからは undefined になる
import { createBrowserClient } from '@supabase/ssr'

export const supabase = createBrowserClient(
  process.env.SUPABASE_URL!,      // NEXT_PUBLIC_ が無い
  process.env.SUPABASE_ANON_KEY!,
)
// ✅ ブラウザに渡す値は NEXT_PUBLIC_ を付ける
export const supabase = createBrowserClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
)

さらに見落としがちなのが、Vercel 側に環境変数を足したあとは再デプロイが必要という点。環境変数を追加しただけでは既存のビルドには反映されません。Vercel の管理画面で該当デプロイを Redeploy してください。

パターンB: ハイドレーションエラー

new Date()Math.random()localStorage をレンダー中に読むと、サーバーとブラウザで結果がズレて真っ白になります。Claude Code にはこう聞きます。

Vercel にデプロイしたら画面が真っ白で、コンソールに次のエラーが出ています。
`Error: Hydration failed because the server rendered HTML didn't match the client.`
Next.js App Router を使っています。
このエラーが出やすいパターンを挙げて、どこを直せばいいか教えてください。

「直して」と丸投げする前に「出やすいパターンを挙げて」と聞くと、自分のコードのどこが該当するかを自分で照合できるので、次から同じ罠を避けられます。


地雷3: ログインした瞬間、localhost に飛ばされる

Supabase 認証を入れたアプリでよくあるのがこれ。本番でログインボタンを押すと、なぜか http://localhost:3000 に飛ばされる、あるいはログイン画面に戻ってループする。

原因はほぼ Supabase 側の URL 設定です。Dashboard → Authentication → URL Configuration で、

  • Site URL を本番URL(https://your-app.vercel.app)に変更
  • Redirect URLs に本番URLを追加

これで直ります。詳しい設定手順とコード側の emailRedirectTo の扱いは前回のデプロイ記事にまとめたので、ここでは「localhost に飛んだら真っ先に Supabase の URL 設定を疑う」とだけ覚えてください。


地雷4: 本番だけ「Application error: a server-side exception」

画面いっぱいにこの一文だけが出るパターン。

Application error: a server-side exception has occurred while loading
your-app.vercel.app (see the server logs for more information).

これは Next.js が本番ではエラーの中身を隠すために出す汎用ページです。開発中なら真っ赤なスタックトレースが見えますが、本番では「詳細はサーバーログを見て」としか言ってくれません。だから初見だと手も足も出ない。

正解は、案内どおりサーバーログを見に行くこと。Vercel の管理画面で該当デプロイを開き、**Logs(Runtime Logs)**タブを見ます。多いのは、

  • サーバー専用の環境変数(SUPABASE_SERVICE_ROLE_KEY など)を Vercel に登録し忘れている
  • Server Component / Server Action の中で実行時エラーが起きている

ログの本文が取れたら、そのまま Claude Code に渡します。

本番(Vercel)でページを開くと
`Application error: a server-side exception has occurred` と出ます。
ローカルでは出ません。Vercel の Runtime Logs には以下が出ていました。

(ランタイムログを貼る)

Server Component で Supabase を使っています。
原因の候補と、確認する手順を教えてください。

「本番だけ落ちる」ときは、経験上たいてい環境変数のスコープ(サーバー用の設定漏れ/クライアント用との混同)が原因です。ログという一次情報を取りに行けるようになると、AIへの質問も一気に的確になります。


地雷5: APIキーがブラウザに丸見えになっている

最後は事故りやすいやつ。NEXT_PUBLIC_ を付けた環境変数は、ビルド時にブラウザ向けのコードに焼き込まれます。つまり、公開したアプリを開いて開発者ツールを見れば、誰でもその値を読めます。

Supabase の anon key はこれで問題ありません(公開される前提で、RLS で守るキーだからです)。危険なのは、service_role キーをうっかりクライアントで使ってしまうケース。

// ❌ 絶対NG: service_role をブラウザに出す = DB全権限が漏れる
const admin = createClient(
  url,
  process.env.NEXT_PUBLIC_SERVICE_ROLE!,  // NEXT_PUBLIC_ を付けた時点で公開
)

service_roleServer Component / Server Action / Route Handler の中だけで使い、NEXT_PUBLIC_ は絶対に付けない。これが鉄則です。「公開して大丈夫なキー / ダメなキー」の線引きと RLS の話はAIが書いたコードを本番に出す前の落とし穴に詳しく書いたので、そちらもどうぞ。


エラー文を AI に渡すときの3つのコツ

地雷そのものより大事なのが、詰まった瞬間に AI からいい答えを引き出す聞き方です。これは公開デプロイに限らず一生使えます。

  1. エラーは省略せず全文貼る。 「...以下同様」で切らない。ファイルパス・行番号・スタックトレースが最大の手がかりで、AIはそこから原因を絞ります。
  2. 再現条件を1行足す。 「ローカルの dev では動く/本番だけ落ちる」の一言があるだけで、AIの当たりが劇的に良くなります。環境差が原因の地雷は、これだけで原因の当たりがぐっと良くなります。
  3. 「直して」より「原因の候補を確認順に3つ」と聞く。 いきなり修正コードをもらうと、なぜ直ったか分からないまま次で詰みます。候補を出させて自分で切り分けると、コードを読む力=自走力が残ります。

デプロイのトラブルシューティングは、じつはプログラミングと AI協働スキルを同時に鍛える最高の実戦です。エラーを読み、仮説を立て、AIに検証させ、自分で選ぶ——この往復を数回まわすと、次のアプリは驚くほどスムーズに公開できるようになります。


まとめ: 症状から逆引きするデプロイ地雷マップ

症状 まず疑う所 AIに渡すもの
ローカルは動くのに Vercel でビルド失敗 npm run build をローカルで再現/型・import の大文字小文字 ビルドログ全文
ビルド成功なのに真っ白 クライアント環境変数(NEXT_PUBLIC_)/ハイドレーション コンソールのエラー全文
ログイン後 localhost へ飛ぶ・ループ Supabase の Site URL / Redirect URLs 遷移先URLと設定画面
本番だけ Application error Vercel の Runtime Logs/サーバー用env の設定漏れ ランタイムログ全文
APIキーがブラウザに見える NEXT_PUBLIC_ の付けすぎ/service_role の誤用 該当のenv名とコード

「ローカルで動く」と「世界に公開できる」の間には、この5つくらいの段差があります。でも一つずつは、エラー文を落ち着いて AI に渡せば必ず抜けられるレベルのものです。デプロイは上級者だけの特権ではなく、AIと一緒なら未経験の最初の一歩に十分向いています。真っ白な画面で固まったら、まずコンソールを開いて、その一文をコピーするところから始めてみてください。


未経験者向けの講座を運営しています

未経験から Next.js + Supabase + Claude Code で Webアプリを公開するまで を、全20セッションで体系化した教材です。今日の記事のような「詰まったらAIに聞いて抜ける」実戦の型を、最初のアプリ公開までまるごと伴走します。

※ Qiita 読者の方には易しすぎる内容だと思います。未経験の知り合いへの紹介や、社内研修・後輩育成の参考としてどうぞ。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?