Next.js AI 应用路由设计:页面轻一点,边界清楚一点
Next.js 很适合做 AI 生活化应用:前端体验细腻,后端接口也能放在同一个项目里。但方便也容易带来边界混乱。页面组件里直接写模型调用、API 路由里混入产品逻辑、鉴权散落各处,项目很快就会变得难维护。
我做小型 AI 应用时,会让页面轻一点,把模型调用、用量、权限和日志放到明确的服务层。独立项目不一定需要微服务,但需要清楚的目录和责任边界。
一、路由先按用户任务组织
AI 生活化产品的页面不要按技术炫技组织,而要按用户任务:聊天、回忆录、提醒、设置、导出。路由结构本身就是产品地图。
flowchart TD
A[app] --> B[chat]
A --> C[memories]
A --> D[reminders]
A --> E[settings]
A --> F[api]
F --> G[ai]
F --> H[jobs]
F --> I[billing]
页面层只负责展示和轻交互,不直接知道模型供应商细节。这样以后从一个模型切到另一个模型,不会牵动整个界面。
二、AI 调用放到服务层
把 AI 调用封装成服务,统一处理模型、超时、重试、token 统计和安全策略。
ts
export async function runGentleAssistant(input: {
userId: string;
message: string;
scenario: "chat" | "reminder" | "memory";
}) {
await assertQuota(input.userId);
const safety = await assessSafety(input.message);
const response = await callModel({
template: selectTemplate(input.scenario, safety.level),
variables: { message: input.message },
timeoutMs: 15000,
});
await recordAiUsage(input.userId, response.usage);
return response;
}
这段代码表达了边界:额度、安全、模板、模型调用、用量记录都在服务层。API route 只负责接收请求和返回结果。
三、流式输出要处理取消
AI 应用常用流式输出,但用户可能关闭页面、切换任务或点停止。服务端要能处理取消,不要继续烧 token。
ts
export async function POST(req: Request) {
const controller = new AbortController();
req.signal.addEventListener("abort", () => controller.abort());
return streamAssistantResponse({
body: await req.json(),
signal: controller.signal,
});
}
取消能力也是体验的一部分。生活化产品里,用户不该被一段正在生成的回答困住。
四、错误页面要有人话
AI 接口失败很常见:超时、限流、模型不可用、额度不足。Next.js 的错误边界要把这些情况翻译成用户能理解的状态,而不是只显示技术错误。
可以把错误分为可重试、需等待、需升级、需联系支持。界面给出对应动作。产品越温柔,越要在失败时清楚。
五、总结
Next.js 做 AI 生活化应用时,关键是边界清楚。页面按任务组织,AI 调用放服务层,流式输出支持取消,错误状态讲人话。
小项目也值得有结构。结构不是束缚,而是让产品慢慢长大时仍然保持安静。