第224章:ストリーミング表示の仕組み
この章では、「AIの返事が1文字ずつ増えていく」仕組みを、通信(ネットワーク)とReactの画面更新の両方から、ふんわり理解しちゃいます🧠💡 ※Vercel AI SDK は **SSE(Server-Sent Events)**を標準のストリーミング方式として使います。(Vercel)
1) そもそもストリーミングって何?🚰
普通の通信は「全部できてからドン!」📦 ストリーミングは「できた分からちょっとずつ送る!」📮✨
つまり…
- ✅ 待ち時間が短く感じる(体感爆速)⚡
- ✅ “考えてる感” が出て安心🙂
- ✅ 長文でも 途中から読める📖
2) Vercel AI SDKのストリーミングは何でできてるの?🧩
結論:SSE(Server-Sent Events)形式で、サーバー → ブラウザに「イベント」を流します📡 AI SDK 5 以降、これが標準になりました。(Vercel)
そして AI SDK は、ただの文字列じゃなくて 「今届いたのは何のデータ?」を区別するための Data Stream Protocol を持ってます🧠✨(AI SDK)
3) 全体の流れ(図で一発)🎬

4) “パラパラ” の正体:text-delta が連打されてるだけ 🪄
AI SDK の Data Stream Protocol では、ストリーミング中にこんなイベントが届きます👇(AI SDK)
text-start:文字ブロック開始(IDが付く)text-delta:追加の文字(これが “パラパラ”)text-end:文字ブロック終了- 最後に
data: [DONE]で終了✅
例(イメージ):
data: {"type":"text-start","id":"msg_abc"}
data: {"type":"text-delta","id":"msg_abc","delta":"Hello"}
data: {"type":"text-delta","id":"msg_abc","delta":" world"}
data: {"type":"text-end","id":"msg_abc"}
data: [DONE]
5) Reactの画面が“勝手に増える”理由😳➡️🙂
ポイントはこれだけ👇
useChatはサーバーからのストリーム(SSE)を受け取るtext-deltaが来るたびに、messages の中身を更新する- React は state が変わるたびに 再レンダリングする
- だから画面の文字が「増えて見える」✨
useChat は「ストリーミング受信→状態管理→UI更新」まで面倒見てくれるフックです。(AI SDK)
(AI SDK 5 からは “transportベース” になって、設計がけっこう今どきになってます🚌✨)(AI SDK)
6) 仕組みをもっと実感したい人向け:超ざっくりSSE読み取り(理解用)🧪
※これは「仕組みの理解用」の簡易版だよ!本番で雑にパースするのは危険⚠️ (AI SDKはちゃんと処理してくれるから、普段は不要だよ🙆♀️)
// SSEをそれっぽく読むだけの最小イメージ(理解用)
export async function readSSE(
res: Response,
onJson: (data: unknown) => void
) {
const reader = res.body?.getReader();
if (!reader) throw new Error("No response body stream");
const decoder = new TextDecoder();
let buffer = "";
while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
// SSEは「空行」で1イベント区切りのことが多い
const events = buffer.split("\n\n");
buffer = events.pop() ?? "";
for (const ev of events) {
const dataLine = ev
.split("\n")
.find((line) => line.startsWith("data:"));
if (!dataLine) continue;
const payload = dataLine.slice("data:".length).trim();
if (payload === "[DONE]") return;
onJson(JSON.parse(payload));
}
}
}
7) DevToolsで「本当に流れてる!」を確認しよう👀🔍
- ブラウザで開発者ツール(F12)🛠️
- Network タブへ🌐
- チャット送信して
/api/chatのリクエストをクリック🖱️ - Response / Preview を見ると、ストリームが追記されていくのが見えたりします✨
- ヘッダーに
text/event-stream(SSE)が付いてると「っぽい」!📌(環境により表示のされ方は差あり)
8) よくあるハマりポイント集 😭➡️😎
✅ ① 途中までしか表示されない / 一気に最後に出る
原因あるある:途中の“バッファリング”(溜めてから出すやつ)💦 SSEは「溜めずに流す」必要があるので、プロキシ・ミドルウェア・ホスティング設定で詰まることがあります🧱 AI SDK は SSE を標準にしてるので、まずは SSE前提でデバッグすると早いです。(Vercel)
✅ ② 自前バックエンドで流したけど useChat が読めない
カスタム実装で Data Stream Protocol を流すとき、x-vercel-ai-ui-message-stream: v1 が必要です。(AI SDK)
(これが無いと「それAI SDKの流儀じゃないかも…?」ってなる💭)
✅ ③ 文字以外も流れてくるの?
流れます🙆♀️
AI SDK は text-* 以外にも、任意の data-* みたいな「追加データ」もストリーミングできます。(AI SDK)
(次の章以降で“プロっぽいUI”に活きるやつ✨)
9) ミニ課題(5〜10分)📝✨
- Networkで
/api/chatを見つける🔍 - 「一括レスポンス」じゃなくて「流れてる」感があるか観察👀
- もし可能なら、レスポンスの中に
text-deltaっぽい増え方を見つける🧩 - 終わりの合図(
[DONE])があるか意識してみる✅(AI SDK)
次(第225章)へのつながり 🚀💬
ストリーミングの仕組みがわかったら、次は 実際にAIチャットボットを完成させます🎉 「パラパラ出るUI」をちゃんと気持ちよく作っていこうね☺️✨