本文へ移動
verified onnext@16.3.3react@19
最終検証日 2026-08-27
Next.js道場

ブラウザに何が届くのか

Server Component のコードはブラウザに届きませんが、Client Component へ渡した props は表示していなくても全部届きます。

#送られるのは「結果」であって「コード」ではない

Server Component を書いても、そのコードはブラウザに届きません。届くのは、サーバーで描画した結果です。

具体的には2つ送られます。

HTML            最初の表示に使う
RSC ペイロード  React が画面を組み立て直すための、木構造のデータ

RSC ペイロードには、コンポーネントの構造と、境界を越えた props の値が入っています。開発者ツールのネットワークタブや、ページのソースから読めます。

#境界を越えた props は、表示していなくても届く

ここが実務でいちばん重要です。

// app/admin/page.tsx(Server Component)
export default function Page() {
  const key = process.env.ADMIN_KEY   // NEXT_PUBLIC_ は付いていない
  return <Table apiKey={key} />       // ← 越えた
}

このコードをビルドすると、成果物の中に ADMIN_KEY の値がそのまま入ります。 画面に表示していなくても入ります。

このサイトでは、これを説明で済ませていません。この問題は、実際に Next.js 16.3.3 でビルドして、成果物に値が含まれることを毎回確かめています。

#NEXT_PUBLIC_ が守るもの、守らないもの

よくある誤解が「NEXT_PUBLIC_ を付けていないから安全」です。

何が起きるか
NEXT_PUBLIC_ を付けるその環境変数がクライアント側のバンドルに埋め込まれる
付けない埋め込まれない
自分で props として渡す付けていなくても届く

NEXT_PUBLIC_ が制御しているのは「変数の埋め込み」だけです。自分の手で境界を越えさせた値は、その対象外です。仕組みが守ってくれるのはここまでで、あとは書いた人の責任になります。

#使っていないプロパティも届く

受け取る側が読まなくても、渡したオブジェクトの中身は全部運ばれます。

const user = await getUser()      // { id, name, passwordHash, ... }
return <Profile user={user} />    // Profile は name しか使わない

これでも passwordHash は届きます。型で { name: string } と宣言しても関係ありません。型は実行時には消えているので、何も削りません。

ORM が返した行をそのまま渡すのが危ない、というのはこの意味です。

#越えなければ残らない

逆に、境界を越えなければ値は残りません。

export default async function Page() {
  const key = process.env.ADMIN_KEY
  const rows = await load(key)      // サーバーの中で使い切る
  return <div>{rows.length}</div>   // 渡すのは件数だけ
}

これは実際に確かめて、成果物に値が含まれないことを確認しています。

安全なのは「使ったこと」ではなく「渡さなかったこと」です。

#実務での書き方

1. 秘密はサーバーの中で使い切る

API キーが要るなら、その呼び出しごとサーバー側に置き、外へ出すのは結果だけにします。

2. 渡す形を明示的に組み立てる

const row = await db.user.findFirst()

const user = {
  id: row.id,
  name: row.name,
}

return <Profile user={user} />

面倒に見えますが、これ1つでシリアライズのエラーと情報漏れの両方が防げます。

3. レビューで見る場所を1つに絞る

「Client Component に渡している props に、見せてはいけないものが無いか」だけを見ればよくなります。境界がはっきりしているほど、確認は速く終わります。

#確認のしかた

自分のページで確かめたいときは、ビルドした成果物を検索するのが確実です。

next build
grep -r "確かめたい文字列" .next/server/app

ブラウザで確かめるなら、ページのソースを表示して同じ文字列を探します。開発者ツールを開かない利用者には見えませんが、見ようと思えば誰でも見られるという前提で設計してください。

理解できたか試す

では、このコードはどうなりますか。

ADMIN_KEY は NEXT_PUBLIC_ が付いていない環境変数です。この値はブラウザから読めますか。

この問題を解くこのテーマの問題 3