You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js 14仿ChatGPT实现API流式渲染遇问题求助

Next.js 14 Turbo 实现 DeepInfra API 流式文本渲染方案

核心问题分析

你之前的方案报错,本质是违反了 Next.js 14 的边界规则:服务器端函数/组件无法访问客户端的状态更新函数(setContent),同时直接在客户端暴露 API Key 存在安全风险。正确的做法是通过Route Handler 作为中间层处理服务器端 API 请求,客户端通过流式响应接收数据并实时更新状态。


分步实现方案

1. 创建服务器端 Route Handler

在 app/api/chat/route.js 中编写服务器端逻辑,隐藏 API Key 并转发流式响应:

import { NextResponse } from 'next/server';

export async function POST(request) {
  const { prompt } = await request.json();
  const API_KEY = process.env.DEEPINFRA_KEY;

  try {
    const response = await fetch('https://api.deepinfra.com/v1/openai/chat/completions', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${API_KEY}`,
      },
      body: JSON.stringify({
        model: "lizpreciatior/lzlv_70b_fp16_hf",
        messages: [{ role: "user", content: prompt }],
        max_tokens: 20,
        stream: true,
      }),
    });

    // 直接转发 DeepInfra 的流式响应给客户端
    return new NextResponse(response.body, {
      headers: {
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive',
      },
    });
  } catch (error) {
    return NextResponse.json({ error: error.message }, { status: 500 });
  }
}

2. 重构客户端 Chat 组件

修改 app/components/Chat.js,通过原生 ReadableStream 处理流式响应并实时更新状态:

"use client";

import { useState, useEffect } from "react";

const Chat = () => {
  const [content, setContent] = useState("");

  useEffect(() => {
    const fetchStream = async () => {
      try {
        const response = await fetch('/api/chat', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({ prompt: "Hello, I am a human. What are you?" }),
        });

        if (!response.ok) throw new Error('请求失败');
        if (!response.body) throw new Error('无响应内容');

        const reader = response.body.getReader();
        const decoder = new TextDecoder();
        let done = false;

        while (!done) {
          const { value, done: readerDone } = await reader.read();
          done = readerDone;
          if (value) {
            const chunk = decoder.decode(value, { stream: true });
            // 拆分并处理 SSE 格式的消息
            const lines = chunk.split('\n').filter(line => line.trim() !== '');
            for (const line of lines) {
              if (line.startsWith('data: ')) {
                const data = line.slice(6);
                if (data === '[DONE]') continue;
                try {
                  const json = JSON.parse(data);
                  const newContent = json.choices[0].delta.content;
                  if (newContent) {
                    // 累加内容实现打字机效果
                    setContent(prev => prev + newContent);
                  }
                } catch (e) {
                  console.error('解析 chunk 失败:', e);
                }
              }
            }
          }
        }
      } catch (error) {
        console.error('流式请求出错:', error);
        setContent('加载响应失败,请重试');
      }
    };

    fetchStream();
  }, []);

  return (
    <div>
      <h1>{content}</h1>
    </div>
  );
};

export default Chat;

关键优化点

  1. 安全隔离:API Key 仅在服务器端使用,避免暴露给客户端
  2. 流式处理:用原生 ReadableStream 和 TextDecoder 解析 SSE 响应,实现实时内容累加
  3. 状态更新逻辑:将 setContent(newContent) 改为累加式更新,模拟 ChatGPT 的打字效果
  4. 错误处理:添加请求失败、解析失败的异常捕获,提升用户体验

内容的提问来源于stack exchange,提问作者HelloToxicity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 00:35:39