阅读视图

发现新文章,点击刷新页面。

MiniMax 发布 M2.7,Agent 开始走向自我进化

我正在开发 DocFlow,它是一个完整的 AI 全栈协同文档平台。该项目融合了多个技术栈,包括基于 Tiptap 的富文本编辑器、NestJs 后端服务、AI 集成功能和实时协作。在开发过程中,我积累了丰富的实战经验,涵盖了 Tiptap 的深度定制、性能优化和协作功能的实现等核心难点。

如果你对 AI 全栈开发、Tiptap 富文本编辑器定制或 DocFlow 项目的完整技术方案感兴趣,欢迎加我微信 yunmz777 进行私聊咨询,获取详细的技术分享和最佳实践。

如果你对 AI全栈 感兴趣,也欢迎添加我微信,我拉你进交流群

3月18日,MiniMax 发布新一代 Agent 旗舰大模型 M2.7。如果只看表面,这像是一次常规的模型升级。但从公开信息来看,M2.7 真正值得关注的,不只是分数更高、能力更强,而是它首次对外展示了一条更具代表性的技术路线,也就是"模型自我进化"。

根据 3 月 18 日公开报道,M2.7 通过构建 Agent Harness 体系,让模型深度参与自身训练与优化流程。在部分研发场景中,这套机制已经可以承担 30% 到 50% 的工作量,并在内部评测集上带来约 30% 的效果提升。这个表述背后释放出的信号很明确,AI 正在从"回答问题的模型"迈向"能够参与迭代自身能力的系统"。

这次发布最重要的,不只是性能提升

过去很长一段时间,行业讨论大模型,重点往往集中在参数规模、训练成本、推理速度以及 benchmark 排名上。但 Agent 时代的竞争逻辑已经开始变化。真正决定模型价值的,越来越不是单点能力,而是它能不能进入真实工作流,承担连续任务,并在执行过程中形成可积累、可复用、可优化的闭环。

M2.7 这次最大的不同,就在于它不再只是研发流程中的被优化对象,而开始成为研发流程中的参与者。

所谓 Agent Harness,可以把它理解为围绕 Agent 构建的一整套执行、反馈、优化机制。模型不只是完成任务,还会进入任务分解、流程回放、错误暴露、策略修正和样本反馈等环节。这样做的意义不在于概念新,而在于它把模型能力提升从"一次性训练结果"推进到了"持续演化过程"。

换句话说,过去我们更熟悉的是"训练一个更强的模型",而 M2.7 想展示的是"让模型参与把自己变得更强"。

工程能力,已经开始逼近一线水位

从公开成绩来看,M2.7 在工程场景上的表现是这次发布的另一大看点。

根据当日披露数据,M2.7SWE-bench Pro 上取得了 56.22% 的成绩。这个指标之所以重要,是因为它衡量的不是简单补全代码,而是真实软件工程环境中的问题理解、代码修改、上下文追踪和任务闭环能力。能在这个测试里打出有竞争力的成绩,说明模型已经不只是"会写代码",而是更接近"能参与工程"。

与此同时,M2.7VIBE-ProTerminal Bench 2 等更接近真实研发流程的测试中也有突出表现。公开说法中提到,它已经能够支持端到端项目交付与复杂系统理解。这一点比单个 benchmark 分数更值得重视,因为真实企业环境看重的从来不是一道题做对,而是模型能否在复杂上下文里持续完成任务。

从研发团队视角看,这意味着 Agent 的角色正在发生变化。它不再只是辅助写一段函数、解释一条报错,而是开始承担更完整的工作单元,比如理解项目结构、分析系统依赖、处理跨文件修改,甚至在终端和工程环境中完成连续操作。

如果这个趋势持续下去,开发团队对 AI 的期待也会随之改变。未来最有价值的模型,不一定是最会答题的那个,而是最能稳定交付结果的那个。

办公场景,开始成为另一条主战线

除了工程能力,M2.7 在办公场景上的提升也非常值得注意。

公开信息显示,它在 GDPval-AA 上取得了 1495 的 ELO 得分,并被描述为开源最高。同时,模型在 Office 文档处理、多轮编辑、复杂内容整理等任务上的表现也有明显增强。

这背后其实说明了一件事,MiniMax 对 M2.7 的定位,并不是单纯的代码模型,而是更偏向通用生产力 Agent。它既要能进入开发流程,也要能进入知识工作和协作流程。因为在真实企业场景里,研发、产品、运营、文档、汇报、分析并不是割裂存在的,大家需要的是一个能够跨场景接手任务的系统,而不是一个只能在单点场景里亮眼的模型。

从这个角度看,办公能力的提升并不是"附加项",而是 Agent 真正走向大规模落地的必要条件。

为什么“自我进化”这四个字值得单独拎出来看

这次发布里,最值得继续观察的,仍然是"模型自我进化"这条路线。

过去行业谈 Agent,经常会关注几个关键词,比如工具调用、长任务拆解、环境感知、记忆能力、多智能体协作。这些能力当然都很重要,但如果只停留在"会不会调用工具"这一层,Agent 的上限其实并不高。

更深的问题在于,当模型已经能完成任务之后,它能不能利用任务执行过程反过来优化自己。

如果答案是可以,那么大模型的发展路径就会发生结构性变化。未来领先的,不只是训练出一个更强基础模型的公司,而是能建立一套完整演化系统的公司。模型做任务,任务产反馈,反馈进入优化,优化再反哺下一轮任务执行。这样的闭环一旦跑顺,AI 的进步速度就不再完全依赖人工标注和传统训练流程,而会更多来自系统自身在真实世界里的持续学习能力。

这也是 M2.7 这次发布最有想象空间的地方。它传递的已经不是简单的"又一个更强模型来了",而是 Agent 正在从工具形态向系统形态迁移。

这次发布意味着什么

M2.7 目前已经在 MiniMax Agent 与开放平台上线。对开发者来说,这意味着相关能力不再只是实验室概念,而是已经开始进入可调用、可接入、可验证的产品阶段。对行业来说,这次发布的意义可能也不止于一次模型升级。

它更像一个明确信号,AI 竞争正在从"谁的模型更会说"进入"谁的系统更会做"。而在"会做"之后,下一个更关键的问题就是,谁能最先构建出真正有效的自我演化闭环。

如果说过去的大模型更像工具,那么 M2.7 想证明的是,Agent 正在变成系统。再往前一步,它甚至可能变成一种具备持续自我改进能力的数字生产力基础设施。

这或许才是 3 月 18 日这场发布最值得被记住的地方。

从爆红到被嫌弃,MCP 为什么开始失宠了

我正在开发 DocFlow,它是一个完整的 AI 全栈协同文档平台。该项目融合了多个技术栈,包括基于 Tiptap 的富文本编辑器、NestJs 后端服务、AI 集成功能和实时协作。在开发过程中,我积累了丰富的实战经验,涵盖了 Tiptap 的深度定制、性能优化和协作功能的实现等核心难点。

如果你对 AI 全栈开发、Tiptap 富文本编辑器定制或 DocFlow 项目的完整技术方案感兴趣,欢迎加我微信 yunmz777 进行私聊咨询,获取详细的技术分享和最佳实践。

如果你对 AI全栈 感兴趣,也欢迎添加我微信,我拉你进交流群

MCP 出生时,被捧得很高。

2024 年 11 月,Anthropic 发布"模型上下文协议",几乎所有 AI 开发者社区都在讨论这件事。它的定位很诱人,要成为大模型和外部工具之间通信的"通用标准",有点像当年 HTTP 对 Web 的意义。一时间,MCP server 满天飞,各种集成教程、开源实现层出不穷。

但时间只过了一年多。

上周,Perplexity 的联合创始人兼 CTO Denis Yarats 在内部表示,他们正在放弃 MCP,转而改用 APICLI。这个消息扩散出来后,引发了一波讨论,但讨论的内容不是"为什么",而是"早该如此"。

Y Combinator 的总裁兼 CEO Garry Tan 甚至直接说了一句话:"MCP sucks。"

MCP 的问题从来都不是技术实现不够好

很多人对 MCP 的质疑,停留在"不稳定"、"认证烦"这些体感上的抱怨。这些问题确实存在,但它们只是表象。MCP 真正的困境,是一个结构性问题。

MCP 的工作方式是,把工具的名称、描述、参数结构(Schema)以及使用示例,全部注入到 Agent 的上下文窗口里。Agent 读完这些信息,再决定要调用哪个工具。

这个设计在工具数量少时还可以接受。但你一旦接入 10 个服务,每个服务有 5 个工具,光是工具定义本身就已经烧掉了几千个 token。Agent 还没开始干活,上下文就已经塞满了一半。

上下文窗口是 Agent 最宝贵的资源,它决定了 Agent 能看见多少对话历史,能保留多少工作记忆,能有多大的推理空间。MCP 的代价,是把这个资源拿来"列菜单"。

面对这个问题,现有的出路只有三条:

  • 一次性加载所有工具,接受推理性能下降
  • 限制接入工具数量,接受 Agent 能力边界收窄
  • 构建动态工具加载机制,接受额外的延迟和复杂度

三条路都不好走。这不是"实现质量"的问题,而是协议设计本身的代价。

除此之外,日常使用中的痛点也不少。MCP server 启动失败是家常便饭,有时重试能解决,有时必须推倒重来。接入多个服务就要在每个服务上重新认证一遍。权限管理也只有"允许"和"不允许"两档,没有办法把某个工具限制为只读,也没有办法约束它可以传什么参数。

CLI 是更好的答案,不是因为它新,而是因为它够旧

工程师 Eric Holmes 写过一篇文章,观点直接:MCP 没有带来任何实际价值,LLM 完全可以自己搞懂怎么用 CLI

这话有点刺,但它说的是实情。

大模型在训练时看过海量的 man 手册、Stack Overflow 回答和 GitHub 上的 Shell 脚本。它们对 CLI 的理解,远比对某个 MCP server 的理解深得多。给它一个命令行工具和一份文档,它就能上手,不需要特殊适配。

CLI 在几个关键点上,比 MCP 天然占优。

第一是可调试性。当 Claude 对 Jira 执行了一个出乎意料的操作,你可以直接跑同一条 jira issue view 命令,看看它看到了什么。输入一致,输出一致,没有谜团。但 MCP 的调用只发生在 LLM 的对话内部,出问题了只能去翻复杂的 JSON 传输日志。

第二是可组合性。这是 CLI 的核心竞争力。你可以用 jq 过滤数据,用 grep 串联逻辑,把输出重定向到文件。这不只是方便,很多时候这是唯一可行的路。MCP 没有这个能力,你要么把完整数据塞进上下文,要么在 server 端自己写过滤逻辑,两种方式都在用更多的精力换取更差的结果。

第三是认证。CLI 复用的是系统级别的认证体系,这套东西已经经过几十年的打磨。MCP 需要你重新为每个工具搭一遍认证流程。

这件事说明了什么

Perplexity 放弃 MCP,以及其他工具陆续移除 MCP 支持,这件事背后有一个更值得思考的信号。

给 AI 构建工具链,不需要发明一套新的协议。AI 需要的工具,和人类需要的工具,在很多时候是同一套。最好的工具是对人类和机器都好用的工具。

CLI 存在了几十年,设计上一直遵循一个哲学,每个工具做好一件事,然后把工具组合起来解决复杂问题。这套哲学放到 Agent 身上,依然成立。

MCP 想构建一个更"现代"的抽象层,但它解决的问题,现有工具已经解决得够好了。在不需要额外抽象的地方强行加一层,带来的只有额外的成本和复杂度。

当然,MCP 不会完全消失。在某些特定场景,比如需要强类型 Schema、有严格访问控制要求的企业内部系统,它依然有它的位置。但作为"AI 工具集成的通用标准",这个定位恐怕很难站稳了。

参考:

2026 年前端 Agent 框架选型:Mastra 与 LangChain 该怎么选

我正在开发 DocFlow,它是一个完整的 AI 全栈协同文档平台。该项目融合了多个技术栈,包括基于 Tiptap 的富文本编辑器、NestJs 后端服务、AI 集成功能和实时协作。在开发过程中,我积累了丰富的实战经验,涵盖了 Tiptap 的深度定制、性能优化和协作功能的实现等核心难点。

如果你对 AI 全栈开发、Tiptap 富文本编辑器定制或 DocFlow 项目的完整技术方案感兴趣,欢迎加我微信 yunmz777 进行私聊咨询,获取详细的技术分享和最佳实践。

如果你对 AI全栈 感兴趣,也欢迎添加我微信,我拉你进交流群

2026 年的前端圈卷出了新高度,AI Agent 已是各类 Web 应用的标配。官网智能客服、内部任务助手、产品内的搜索与推荐,都绕不开一件事:用哪个框架把大模型和工具串起来。不少团队会在 LangChain.js 和 Mastra 之间反复纠结,架构评审时也常为此争论。

两者没有绝对优劣,差别主要在"设计哲学"和"业务场景"的匹配度。Mastra 像为前端量身定制的厨师刀,刀刃顺手、切菜切肉都轻松;LangChain.js(尤其是 LangGraph.js)则像重型瑞士军刀,刀锯镊子开瓶器齐全,能应付各种复杂场景,代价是重量和复杂度都更高。下文从 2026 年技术生态出发做一次对比,并配上代码与图示,方便你理清思路、少走弯路。

为什么前端选型会卡在这两个框架上

前端接大模型、做 Agent,本质是三件事:把用户输入送给 LLM、根据输出决定下一步(是否调工具、是否多轮对话)、再把结果还给用户。不同框架在这三条链路上的抽象程度和侧重点差异很大。一类把"循环调工具、拼消息"全包在内部,对外只暴露"发消息、拿回复",你几乎不用关心内部调了几轮工具;另一类把节点、边、状态都暴露给你,自己搭图,灵活性高,但概念和代码量都上去,得先建立"图"的思维才能写得顺手。

LangChain 从 Python 生态长出来,后有 langchain-js,再后来复杂编排催生了 LangGraph,面向任意语言和部署环境的通用编排,概念多、集成广,前端只是消费端之一。文档里会反复出现 Runnables、LCEL、RunnableSequence、RunnablePassthrough 以及各种 @langchain/xxx 包,学习路径会先经过"什么是 Runnable、reducer、checkpointer"这一串概念。Mastra 则从 TypeScript 和现代前端框架出发,默认你在用 Next.js、Nuxt 等全栈框架,API 和类型系统都围着前端习惯转,包名和概念更收敛,文档集中在"在 React、Server Actions 里怎么用",很少逼你先学一整套编排术语。

选型归根结底就两点:团队和产品更接近"通用 AI 编排"还是"前端优先的轻量 Agent"。前者偏向后端或全栈做复杂系统,愿意为灵活性和生态付学习成本;后者偏向前端或小团队在现有 Web 应用里快速接一层智能,希望少概念、少依赖、快上线。

如下图所示。

20260314114857

两种哲学一目了然:一侧是前端优先的轻量体验,一侧是通用编排与生态。

Mastra 的定位与优势

Mastra 从诞生起就面向 TypeScript 和现代前端框架(Next.js、Nuxt 等),针对前端痛点,主打开发者体验(DX)。

TypeScript 原生与类型安全

端到端类型推导做得很好:Agent 的输入、输出和工具调用参数在 IDE 里都有完整类型提示和自动补全,不必手写类型转换或 as 断言。工具用 zod 或 TypeScript 类型定义入参,框架自动生成模型可用的 schema 并做运行时校验。例如在 createTool 里写 inputSchema: z.object({ location: z.string() }),调用时入参即被推断为 { location: string },返回值与 outputSchema 对齐,和现有基于 zod 的表单校验、API 契约也容易打通。

轻量且贴合全栈框架

部署在 Vercel、Cloudflare Workers 等 Serverless 或 Edge 上时,Mastra 的冷启动和边缘兼容性通常更好。没有 LangChain 那套 Runnables、LCEL 等抽象层,依赖树干净,打包体积可控,不必为"跑通一个带工具的 Agent"拉满 @langchain/core@langchain/openai@langchain/langgraph 等一长串包。在 Next.js 的 Server Action、Route Handler 里直接调 Mastra Agent,心智负担小,和现有数据流(表单、状态、API)易对齐,也方便和 React Server Components、流式 SSR 配合。

心智负担低

API 贴近前端数据流直觉:发一段消息、拿一段回复、必要时调几个工具。Mastra 把 LLM 调度、工具解析和流式输出包起来,用简单异步函数或 React 友好接口暴露,不必理解"图、节点、条件边、reducer",会写 createToolnew Agent、会调 generate 或流式方法就能跑通,适合作为团队第一个 Agent 项目的起点。

适合的场景小结

Mastra 特别适合这几类情况:

  • Agent 主要是 Web 应用的辅助功能(智能搜索、客服助手、简单数据总结或表单建议),且深度绑定 Next.js、React 生态。
  • 团队以前端或全栈为主,不想引入过重后台架构,希望快速迭代上线,同时要类型安全和良好调试体验。
  • 对依赖体积、冷启动和 Edge 兼容性敏感,不想为用不到的能力背上整座 LangChain 生态。

LangChain.js 与 LangGraph 的定位与优势

到 2026 年,单纯用 LangChain 搞复杂 Agent 已不够用,实际在评估的往往是 LangGraph.js,它是处理复杂、有状态、多 Agent 协作时的常用方案。

生态系统覆盖广

冷门向量库、大模型厂商、各种外部 API,LangChain 生态里大多已有现成集成。Pinecone、Weaviate、Qdrant、Chroma、自建 REST、OpenAI、Anthropic、Cohere、国产大模型,以及 Tavily、SerpAPI 等,多数有官方或社区的 @langchain/xxx 包。公司内有老旧系统、私有模型或特定协议时,也容易在现有集成上做薄封装,复用 LangChain 的 Runnable、消息格式和工具约定,快速对接大量外部依赖时能省下不少适配和调试时间。

状态机与图逻辑(LangGraph)

需要"循环思考、多路分支、人类介入(Human-in-the-loop)"的复杂工作流时,LangGraph 的图架构能精确控制节点流转。节点是处理单元(一次 LLM 调用、工具执行或人工审核),边是状态转移(固定边或条件边)。状态可持久化到 checkpointer,刷新或断线重连后从断点继续,适合多轮任务和多人协作,也是 Mastra 目前不直接提供的部分。

过度抽象的代价

学习曲线陡:Runnables、Chains、Tools、Nodes、Edges、Annotation、reducer、checkpointer 等概念交织,新手易迷路。实现"用户问一句、模型调一次工具再回答"这种简单功能,也要先理解状态结构、写 agent 与 tools 节点、配条件边和普通边再 compile,代码量明显多于"Agent 配置 + 一次 generate"。报错常来自链式调用的某一层,堆栈里是 LangChain 内部的 Runnable 名,前端背景的开发者需要时间习惯"从图的角度想问题"。LangGraph 的 TypeScript 类型虽完整,但状态是运行时用 Annotation 和 reducer 拼出来的,和 Mastra 那种"工具入参即 zod schema、一眼能看出类型"的体验比,心智负担更大。

适合的场景小结

LangChain、LangGraph 更适合这几类情况:

  • 核心业务就是复杂 AI 系统:多 Agent 协作、长时运行异步任务、或需精准控制"思考中断与恢复"。
  • 集成需求多且杂,要接内部老旧系统或非常小众的向量库、模型接口。
  • 要对底层 Prompt、重试、记忆(Memory)做深度定制,甚至改框架默认行为。

核心能力对比

用一张表概括两个方向在关键维度上的差异,细节在前后文展开。

维度 Mastra LangChain.js / LangGraph
设计核心 极致 DX、原生 TS、轻量化 复杂编排、状态管理、大生态
学习曲线 平缓,熟悉 TS 即可快速上手 陡峭,需理解大量框架专属概念
调试体验 堆栈清晰,贴合前端习惯 多层抽象,报错有时难以定位
多 Agent 支持,更适合简单链式交互 极强,循环与状态打断控制完善
生态与集成 精选集成,覆盖主流工具 海量集成,几乎覆盖常见基础设施
依赖与体积 包少、体积小,Edge 友好 多包组合,体积与冷启动略大

Mastra 通常只需 @mastra/core 加模型适配(如 OpenAI),LangChain 则常需 @langchain/core@langchain/openai(或其它模型包)、@langchain/langgraph,再接向量库或 RAG 还会多几个包,在 Serverless 冷启动和 Edge 里更敏感一些。

如下图所示。

20260314115005

从设计重心到依赖体积,一张图能看清两边差异。下面用两段代码对比同一需求的实现方式,再给出选型决策说明。

用代码感受两种 API 风格

同一需求"做一个能查天气的对话 Agent",在 Mastra 和 LangGraph 里写出来的代码量和抽象层次差很多,看一遍再想选型会直观不少。

Mastra:工具 + Agent 几行搞定

在 Mastra 里用 createTool 定义工具的入参(zod)、描述和执行函数,创建 Agent 时把工具挂上去即可。调用时直接 agent.generate() 或流式接口,不用关心"模型要不要调工具、调完要不要再推理",框架内部处理。

下面示例定义了一个查天气工具和一个使用该工具的 Agent。工具入参用 z.object 声明,execute 的返回值与 outputSchema 一致,整条链路在 IDE 里都有类型推导。示例使用 OpenAI 当前主力模型 gpt-5.4,实际项目里可通过环境变量配置 API Key。

import { createTool } from "@mastra/core/tools";
import { Agent } from "@mastra/core/agent";
import { z } from "zod";

const getWeather = createTool({
  id: "get_weather",
  description: "根据城市名称查询当前天气,适合回答天气相关提问",
  inputSchema: z.object({
    location: z.string().describe("城市名称,如北京、上海"),
  }),
  outputSchema: z.object({ summary: z.string(), temp: z.number().optional() }),
  execute: async ({ location }) => {
    // 实际项目里这里调和风、OpenWeather 等 API
    return { summary: `${location} 晴`, temp: 22 };
  },
});

const weatherAgent = new Agent({
  id: "weather-agent",
  name: "天气助手",
  instructions: "你是天气助手,用 get_weather 查天气并简洁回复用户。",
  model: "openai/gpt-5.4",
  tools: { getWeather },
});

// 在 Next.js Route Handler 或 Server Action 里直接调用
const result = await weatherAgent.generate("北京今天天气怎么样?");
console.log(result.text);

在 Next.js 的 Route Handler 里暴露成 API 时,导入 weatherAgent,对请求体里的消息调 generate 或流式方法即可,不必再写状态机或图。

LangGraph:显式建图与状态

在 LangGraph 里,要先定义状态结构(例如消息列表)、再定义"agent"节点(调用模型、可能产生 tool_calls)和"tools"节点(执行工具并返回 ToolMessage),最后用边把节点串起来,并加上"是否继续调工具"的条件边。模型用 LangChain 的 ChatOpenAI 接 OpenAI 最新模型,工具用 bindTools 绑定,循环由图的拓扑自然形成。

下面这段示例用 StateGraph 定义了一个单 Agent、带一个天气工具的最小图。状态里只有 messages,agent 节点读最后一条用户消息并调用模型,若返回 tool_calls 则路由到 tools 节点,执行完再回到 agent,直到模型不再调工具为止。可与上面 Mastra 示例对照,体会"图"和"状态"的显式写法。

import { StateGraph, Annotation, END } from "@langchain/langgraph";
import { ChatOpenAI } from "@langchain/openai";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
import { HumanMessage, AIMessage, BaseMessage } from "@langchain/core/messages";
import { ToolNode } from "@langchain/langgraph/prebuilt";

const model = new ChatOpenAI({
  model: "gpt-5.4",
  apiKey: process.env.OPENAI_API_KEY,
});

const getWeather = tool(
  async (input: { location: string }) => `${input.location} 晴,22℃`,
  {
    name: "get_weather",
    description: "根据城市名称查询当前天气",
    schema: z.object({ location: z.string() }),
  },
);

const modelWithTools = model.bindTools([getWeather]);
const toolNode = new ToolNode([getWeather]);

const AgentState = Annotation.Root({
  messages: Annotation<BaseMessage[]>({
    reducer: (left, right) => left.concat(right),
    default: () => [],
  }),
});

async function agentNode(state: typeof AgentState.State) {
  const response = await modelWithTools.invoke(state.messages);
  return { messages: [response as AIMessage] };
}

function shouldContinue(state: typeof AgentState.State): "tools" | "end" {
  const last = state.messages[state.messages.length - 1] as AIMessage;
  return last.tool_calls?.length ? "tools" : "end";
}

const graph = new StateGraph(AgentState)
  .addNode("agent", agentNode)
  .addNode("tools", toolNode)
  .addEdge("tools", "agent")
  .addConditionalEdges("agent", shouldContinue, { tools: "tools", end: END })
  .compile();

const result = await graph.invoke({
  messages: [new HumanMessage("北京今天天气怎么样?")],
});
console.log(result.messages[result.messages.length - 1]);

同样实现"用户问天气、模型调工具、再回复":Mastra 是"Agent + tools 配置 + 一次 generate",LangGraph 是"状态注解 + 两节点 + 条件边 + compile"。前者适合快速落地和前端集成,后者适合加人工审核、多 Agent 分支、断点续跑等复杂控制。示例中 LangGraph 使用 gpt-5.4,API Key 建议从环境变量 OPENAI_API_KEY 读取。

选型决策思路

可以按"产品形态、团队基因、集成与定制需求"三条线问自己,再对照上文对比。决策主线就一条:先看 Agent 是"应用的核心"还是"应用里的辅助能力"。核心场景(多 Agent、长任务、状态中断与恢复、大量冷门集成或深度定制)更倾向 LangGraph;辅助能力(Next/React 为主、快速迭代、极重 TypeScript 与 DX)更倾向 Mastra。不必二选一,也可以简单对话用 Mastra、复杂管线用 LangGraph,按模块边界拆。

如下图所示。

20260314115134

从"核心还是辅助"出发,到倾向 LangGraph 或 Mastra(或两者组合)的决策路径。

更偏向选 Mastra 的情况

  • 产品形态上,Agent 主要作为 Web 应用的辅助功能(智能搜索、客服助手、简单数据总结等),且深度绑定 Next.js、React 生态。
  • 团队以前端、全栈为主,不想引入过重的后台架构,希望快速迭代、快速上线。
  • 你非常看重 TypeScript 的类型安全和开发体验,对臃肿依赖和难以排查的报错比较排斥。

更偏向选 LangChain / LangGraph 的情况

  • 产品形态上,核心业务就是一个复杂的 AI 系统,例如多 Agent 协作、长时间运行的异步任务、或需要精准控制思考中断与恢复。
  • 集成需求多且杂,需要连接内部各种老旧系统,或使用非常小众的向量数据库、模型接口。
  • 需要对底层 Prompt、重试、Memory 等做深度定制,甚至改动框架默认行为。

结合业务场景做更细的取舍

光看框架特性不够,最终要落到"这个 Agent 具体负责什么"上。下面四类典型场景方便对号入座,每类对应不同复杂度和集成需求,选错框架要么大材小用,要么后期自己造轮子。

如下图所示。

20260314115312

四类场景与推荐方向的对应关系。

场景一:官网或产品里的智能客服、搜索建议

用户在一页里问几句,要即时、简洁的回复,必要时查文档或知识库。流程短、状态简单,不需要多 Agent 博弈或断点续跑,前端发一条消息、收一条(或流式)回复,至多一两轮工具调用。这类需求 Mastra 的轻量 API 和 TypeScript 体验很顺手,一个 Agent 配几个工具、在 Route Handler 里调 generate 就能上线;用 LangGraph 容易杀鸡用牛刀,要先建图、理解条件边和状态,对只想做一个会查文档的客服的团队来说性价比不高。

场景二:内部工具里的"多步任务助手"

例如用自然语言帮用户订会议室、填工单、查数据并生成报告。步骤多,有时要人工确认或回退(如"是否确认提交工单"),状态要在多轮请求间保持,甚至支持"离开页面再回来从断点继续"。这类需求用 LangGraph 的状态图和 checkpointer 更自然:节点对应步骤或人工介入,边上挂条件判断,状态持久化后刷新或重连都能恢复。用 Mastra 也能做,但分支和人工介入一多,就得自己维护"当前步骤、待确认项、历史结果",等于在业务层再造状态机,不如直接用图建模,让框架负责持久化。

场景三:多 Agent 协作(检索、生成、审核等分工)

多角色各司其职,之间有固定或动态调用关系,甚至要循环几轮才产出结果。这类编排是 LangGraph 的强项;Mastra 更适合"一个主 Agent 调若干工具"的链式交互,多 Agent 的路由和状态共享要自己写胶水代码。

场景四:向量库、模型、外部 API 集成种类多

公司内有自建向量库、多种大模型和第三方 API,希望用同一套抽象管住"检索、调用、解析"。LangChain 的集成生态在这里优势明显:Pinecone、Weaviate、Qdrant、自建 REST、各类 LLM 与 RAG 预制链和图,大多有现成包。Mastra 偏向精选常用组合,技术栈若较"非主流"(内网模型、私有协议、冷门向量库),可能要自己写适配层,把外部能力包成 Mastra 能识别的工具或模型接口。要权衡多写的适配代码是否被 Mastra 的 DX 和轻量部署抵消;若集成种类还会持续增加,直接上 LangChain 生态往往更省事。

常见误区与落地注意点

选型时容易踩的坑和落地前值得想清楚的几点,简单归纳如下。

不必纠结的两点。第一,没有"用了 Mastra 就不能用 LangChain"这回事,两者可共存,例如边缘或 BFF 用 Mastra 做轻量对话,后台用 LangGraph 做复杂管线,用 HTTP 或消息队列打通。第二,没有"LangGraph 一定比 Mastra 重"的绝对结论,重的是你要维护的图与状态逻辑;若你只需要一张简单 agent-tools 图,编译后运行时开销可接受,主要是上手成本高。

需要提前想清楚的两点。一是"先简单后复杂"时,若判断半年内会演进到多 Agent 或人机协同,可早点把复杂子流程用 LangGraph 建模,哪怕先只实现单 Agent,图结构也为后续加节点留好位置,避免以后在 Mastra 里手写状态机再迁一轮。二是"先复杂后简化"时,若团队普遍抱怨 LangChain 报错难查、概念太多,可把"单轮或短对话"抽成独立服务,用 Mastra 重写,接口不变、前端无感,逐步降维护成本。

最后,无论选哪边,都建议一开始就把"输入输出契约"(请求体格式、流式 SSE、错误码)定好,并用 TypeScript 类型或 OpenAPI 描述出来,以后换实现、做 A/B 或拆服务时,前端和网关都不必大动。

混合使用与迁移成本

不少团队会折中:简单、面向用户的 Agent 用 Mastra,部署在前端或边缘;复杂、长链路、多 Agent 的管线放后端,用 LangGraph 或 LangChain 实现,通过 API 暴露。这样既保住前端侧的开发体验和性能,又在需要复杂编排时用上 LangChain 生态。

若一开始选了 Mastra,后面业务演进到必须上状态图、多 Agent,可以只把"复杂子流程"迁到 LangGraph,用 HTTP 或消息队列和现有 Mastra Agent 对接,不必全盘重写。例如前端仍用 Mastra 做即时问答,把多步审批、长任务编排单独做成 LangGraph 服务,Mastra 在需要时调该服务 API。反过来,若一开始用 LangChain 搭了简单客服,发现维护成本高、报错难排查,可以把单轮或短对话抽成独立服务,用 Mastra 重写,逐步迁移。关键是想清楚边界(按功能、按请求路径、按团队 ownership 都行),按边界拆模块,而不是非此即彼。迁移时优先保证输入输出契约稳定(统一 JSON 请求体、流式 SSE 格式),前端或网关就不必大改。

总结与下一步

Mastra 和 LangChain(LangGraph)代表两种设计哲学:前者为前端和 TypeScript 优化,追求轻量和 DX;后者面向通用 AI 编排和复杂状态,追求生态和表达能力。没有谁一定更好,只看和你的业务场景、团队结构、集成与定制需求是否匹配。

一句话记住选型心法:Agent 是"应用里的辅助能力"、团队偏前端、要快上线,优先看 Mastra;Agent 是"业务核心"、有多 Agent、长任务、人机协同或大量冷门集成,优先看 LangGraph。两者也可组合,按模块边界拆,契约定好即可。

建议先明确两件事:当前要做的 Agent 主要负责什么(辅助功能还是核心 AI 系统),以及半年到一年内会不会出现多 Agent、长任务、复杂集成或深度定制。有了这两个问题的答案,再对照文中的对比表、决策说明和四类场景,选型会清晰很多。若你愿意说一下目前在规划的 Agent 具体负责什么业务、会接哪些系统,可以在此基础上再做一轮更细的技术栈评估和落地方案设计。文中的代码示例使用当前主流的 gpt-5.4,可直接复制后按需改模型名和 API Key 配置。

尤雨溪宣布 Vite+ 正式开源,前端工具链要大一统了

我正在开发 DocFlow,它是一个完整的 AI 全栈协同文档平台。该项目融合了多个技术栈,包括基于 Tiptap 的富文本编辑器、NestJs 后端服务、AI 集成功能和实时协作。在开发过程中,我积累了丰富的实战经验,涵盖了 Tiptap 的深度定制、性能优化和协作功能的实现等核心难点。

如果你对 AI 全栈开发、Tiptap 富文本编辑器定制或 DocFlow 项目的完整技术方案感兴趣,欢迎加我微信 yunmz777 进行私聊咨询,获取详细的技术分享和最佳实践。

如果你对 AI全栈 感兴趣,也欢迎添加我微信,我拉你进交流群

3 月 13 日深夜,尤雨溪在 X 上发了一条推文,平静地宣布了一件大事。

We are happy to announce that Vite+ is now fully open source under MIT license. Free for everyone!

20260315094604

Vite+ 以 MIT 协议全量开源,所有人免费使用。官网已经上线,地址是 viteplus.dev

如果说 Vite 8 的发布是"换了个引擎",那 Vite+ 的开源就是直接掀了桌子。它不是 Vite 的升级版,而是一个全新的物种,一个二进制文件,吃掉你整条前端工具链。

Vite+ 到底是什么

官网给出的定位很直白,"The Unified Toolchain for the Web"。

一句话来说,Vite+ 是一个统一的 Web 开发工具链,把 ViteVitestOxlintOxfmtRolldowntsdownVite Task 七个项目合并成了一个 CLI,命令叫 vp

它的野心不小。管构建,管运行时,管包依赖,管代码检查,管格式化,管测试,管打包发布,甚至管 monorepo 的任务编排。以前你需要 npmpnpmViteESLintPrettierJestnvm 各自配置、各自维护,现在一个 vp 全包了。

值得注意的是,Vite+ 是两段式设计:vp 是全局安装的命令行工具,vite-plus 是每个项目里安装的本地包。这两者协同工作,vp 负责统一入口,vite-plus 负责具体的构建逻辑。

image.png

完整命令地图

vp 的命令覆盖了开发全流程,分成几个维度来看:

启动和初始化

命令 做什么
vp create 创建新项目(支持 app、包、monorepo 模板)
vp migrate 把现有项目迁移到 Vite+
vp env 管理 Node.js 版本
vp install 用正确的包管理器安装依赖
vp config 配置 commit hooks 和 agent 集成

日常开发

命令 做什么 替代谁
vp dev 开发服务器,即时 HMR vite dev
vp check 类型检查 + Lint + 格式化 tscESLintPrettier
vp lint 单独运行 Lint ESLint
vp fmt 单独运行格式化 Prettier
vp test 运行测试 JestVitest
vp staged 对暂存文件跑检查 lint-staged

构建和发布

命令 做什么 替代谁
vp build 生产构建 vite build
vp preview 本地预览生产构建 vite preview
vp pack 库打包 + DTS 生成 tsuptsdown
vp run monorepo 任务执行(带缓存) turboreponx

依赖管理

命令 做什么
vp add / vp remove / vp update 包管理操作
vp dedupe / vp outdated / vp why 依赖分析
vp dlx 不安装直接运行包(类似 npx
vpx 全局执行二进制

还有一个彩蛋命令,vp implode,它会把 vp 本身和所有相关数据从机器上清除干净,如果用了之后觉得不适合自己,一条命令可以走得一干二净。

官网 viteplus.dev 首页的终端示例里,用 vp create acme-web --template react-ts 创建 React + TypeScript 项目,从脚手架生成到依赖安装完成,显示耗时 1.1 秒。

性能数字很夸张

Vite+ 的底层全部用 Rust 重写,官方给出的性能对比数据:

  • 生产构建比 webpack 快 40 倍(基于 Vite 8 + Rolldown
  • OxlintESLint 快 50 到 100 倍
  • OxfmtPrettier 快 30 倍
  • 开发时 HMR 始终保持即时响应

这些数字不是 Vite+ 团队自己编的。OxlintOxfmtOxc 项目里已经跑了很久的 benchmark,社区早有验证。Vite+ 做的事是把这些分散的高性能工具统一到了一个入口。

vp check 不只是 Lint

vp check 是这个工具链里设计最有意思的命令之一,值得单独说说。

它把三件事合进一个命令:Oxfmt 负责格式化,Oxlint 负责代码检查,tsgolint 负责 TypeScript 类型检查。三个工具并行跑,比分别执行快得多。

当你在 vite.config.ts 里开启 typeCheck 选项后,vp check 还会接入 TypeScript Go 工具链做类型感知的静态分析,这是微软正在推进的下一代 TypeScript 编译器,速度比原来的 tsc 快了一个数量级。

import { defineConfig } from 'vite-plus'

export default defineConfig({
  lint: {
    options: {
      typeAware: true,
      typeCheck: true,
    },
  },
})

开启之后,一条 vp check 就能搞定格式、Lint、类型三重检查。加上 --fix 参数还能自动修复可修复的问题:

vp check        # 检查
vp check --fix  # 检查并自动修复

一个配置文件管所有

以前的前端项目,配置文件能铺满项目根目录,vite.config.ts.eslintrc.prettierrcvitest.config.tstsconfig.jsonlint-staged.config.js……

Vite+ 的做法是把所有配置收拢到一个 vite.config.ts

import { defineConfig } from 'vite-plus'

export default defineConfig({
  // 开发服务器
  server: { port: 3000 },

  // Oxlint 规则
  lint: {
    options: {
      typeAware: true,
      typeCheck: true,
    },
  },

  // Oxfmt 格式化
  fmt: { /* ... */ },

  // Vitest 测试
  test: { /* ... */ },

  // 任务编排
  tasks: { /* ... */ },

  // commit 前的暂存检查(替代 lint-staged)
  staged: {
    '*.{js,ts,tsx,vue,svelte}': 'vp check --fix',
  },

  // 库打包(替代 tsdown.config.ts)
  pack: {
    entry: ['src/index.ts'],
    dts: true,
    format: ['esm', 'cjs'],
  },
})

一个文件,一套类型提示,一个 IDE 插件搞定所有配置的智能补全。对于强迫症开发者来说,这可能比性能提升更让人兴奋。

vp env 能精细管理 Node 版本

nvm 的用户应该对这种场景很熟悉,不同项目需要不同版本的 Node,切换还容易忘。

vp env 的设计是让 nodenpm 等命令都通过 Vite+ 的 shim 来走,自动识别当前项目锁定的 Node 版本,无需手动切换。

常用命令:

vp env pin lts          # 把项目锁定到最新 LTS 版本(写入 .node-version)
vp env use 20           # 当前 shell 会话临时切换到 Node 20
vp env default lts      # 设置全局默认版本
vp env current          # 查看当前解析到的环境
vp env doctor           # 运行环境诊断,排查问题
vp env list             # 列出本地已安装的版本
vp env list-remote --lts  # 查看可安装的 LTS 版本列表

如果你不想让 Vite+ 接管 Node 版本管理,可以用 vp env off 切到"系统优先"模式,Vite+ 只在系统 Node 找不到时才接管。

现有项目怎么迁移

这是官网里最有价值的部分之一,也是原文没有覆盖到的内容。

对于已有的 Vite 项目,迁移命令是:

vp migrate

这条命令会自动完成:把各个工具的分散配置合并进 vite.config.ts,更新项目依赖,重写 vitevitest 的导入路径,更新 package.json 里的 scripts。

官方建议的迁移前准备:先升级到 Vite 8+ 和 Vitest 4.1+,了解现有的 Lint、格式化、测试配置。迁移后跑一遍验证:

vp install
vp check
vp test
vp build

有意思的一个细节,官网的迁移文档里提供了一段专门写给 AI 编码助手的 migration prompt,可以直接粘贴给 Cursor 或 Claude 来代劳整个迁移过程。这说明 Vite+ 团队在设计工具时已经把 AI 辅助开发纳入考虑了。

不止是 Vue 生态的事

Vite+ 支持的框架列表相当长,包括 ReactVueSvelteSolidAstroNuxtNext.jsRemix,官网列了超过 20 个框架。

这意味着它不是"Vue 生态的专属工具"。任何前端框架的开发者都可以用,而且迁移成本几乎为零,因为底层就是 Vite,现有的 Vite 插件理论上都能直接用。

部署方面,Vite+ 可以与 Nitro 配合,直接部署到 VercelNetlifyCloudflareRender 等平台,从 SPA 到全栈 meta 框架都有完整支持。

怎么装

macOS 或 Linux 下:

curl -fsSL https://vite.plus | bash

Windows(PowerShell)下:

irm https://vite.plus/ps1 | iex

装完就是一个独立二进制文件,不依赖 Node.js 全局安装,不需要 npm install -g。安装后打开新的终端窗口,运行 vp help 就能看到所有命令。在 CI 环境里可以用官方提供的 setup-vp Action。

运行 vp upgrade 可以更新 vp 本身到最新版本。

谁在做这件事

Vite+ 背后是 VoidZero,尤雨溪在 2024 年创立的公司,专注于 Web 工具链。核心团队成员里有几个名字值得关注:

  • 尤雨溪,Vue.jsVite 的创造者
  • LONG Yinan,Oxc 项目的核心作者,Rust 工具链领域的资深开发者
  • Christoph Nakazawa,前 Meta 工程师,Jest 的创造者

没错,Jest 的创造者现在在给 Vite+ 写测试框架。这个阵容不需要多解释。

GitHub 仓库显示,Vite+ 的代码库有 608 个 commit,62.9% 是 Rust,33.4% 是 TypeScript。目前最新版本是 v0.1.11,处于 Alpha 阶段。

Vite 本身每周 npm 下载量已达 6900 万次,GitHub 星标 78.7K,是前端构建工具的事实标准。Vitest 每周下载量也超过 3500 万。这套工具链的用户基数不需要从零积累。

商业模式

很多人关心的问题,这么大的项目,免费能持续多久?

VoidZero 的做法是,Vite+ 完全开源,MIT 协议,永久免费。公司的营收来源是另一个独立的商业产品 Void,具体形态还没公开,但大概率是面向企业的增强版或云服务。

这和 VercelNext.js 免费,平台收费)的路线类似,开源工具做增长飞轮,商业产品做营收。这条路已经被验证过了。

现阶段要注意的几点

虽然 Vite+ 的愿景很性感,但当前有几个现实问题值得正视。

第一,它现在是 Alpha 版本。v0.1.11,连 Beta 都没到,API 可能随时调整,生产环境请三思。官方文档里也明确说了,vp migrate 运行完之后大多数项目还需要手动调整,不是一键无缝。

第二,"大一统"是双刃剑。统一工具链的好处是减少配置和兼容性问题,但坏处是一旦某个模块出问题,整条链都可能受影响。以前 ESLint 出错不影响构建,以后就不好说了。

第三,生态兼容性需要时间。虽然理论上兼容 Vite 插件,但实际使用中肯定会有各种边界情况,社区插件的适配需要一个过程。

第四,包管理这块水很深。npmpnpmyarn 打了很多年,每家都有自己的 resolve 策略和 lockfile 格式,Vite+ 要在这个领域站稳脚跟,挑战不小。

这件事的意义

前端工具链的碎片化问题困扰社区很久了。一个新项目光配置工具链就要半天,node_modules 动辄几百 MB,各种工具之间的版本冲突是家常便饭。

Vite+ 的出现代表了一种趋势,用 Rust 重写性能敏感的部分,用统一的入口消除工具之间的缝隙。

类似的尝试不止 Vite+ 一家,BunDenoBiome 都在做类似的事。但 Vite+ 有一个独特优势,它站在 Vite 的肩膀上,从 ViteVite+ 的迁移路径是最短的,用户基数也是最大的。

从现在的角度来看,Alpha 阶段先关注、多试用、遇到问题提 issue 才是正确姿势。但这件事本身值得认真看待,前端工具链可能真的要变了。

2026 年 Next.js 站点的 SEO 优化指南

我正在开发 DocFlow,它是一个完整的 AI 全栈协同文档平台。该项目融合了多个技术栈,包括基于 Tiptap 的富文本编辑器、NestJs 后端服务、AI 集成功能和实时协作。在开发过程中,我积累了丰富的实战经验,涵盖了 Tiptap 的深度定制、性能优化和协作功能的实现等核心难点。

如果你对 AI 全栈开发、Tiptap 富文本编辑器定制或 DocFlow 项目的完整技术方案感兴趣,欢迎加我微信 yunmz777 进行私聊咨询,获取详细的技术分享和最佳实践。

如果你对 OpenClaw 也感兴趣,也欢迎添加我微信,我拉你进交流群

Next.js 是最流行的 React 框架,被广泛用来构建现代 Web 应用,自带不少开发者未必会用到的能力。搜索形态正在从传统搜索转向"零点击搜索",背后是 Google AI Overview、ChatGPT 等 AI 搜索产品在推动。这些平台会持续抓取站点,用元数据和内容做索引,结构清晰、易于抓取的内容更容易被引用、出现在 AI 结果里。要想在这场变化里站稳,就需要同时为人和 AI 爬虫优化页面与内容。

下面按最佳实践,从页面和内容两方面说说如何做好 SEO 与 GEO。

1. 用 Metadata API 做 SEO

元数据一直负责告诉外界页面的标题和描述。Next.js 用新的 Metadata API 取代了过去的 Head 组件,可以在服务端组件里声明,由服务端渲染输出,爬虫和社交平台抓取时拿到的就是完整、准确的标题与描述,不会出现空白或占位文案。

app/layout.tsx 或单页的 layout.tsx 里导出 metadata 对象即可。下面这段示例覆盖了站点标题模板、默认描述、搜索引擎验证、Open Graph 与 Twitter 卡片、以及规范链接。

import type { Metadata } from "next";

export const metadata: Metadata = {
  title: {
    template: "%s",
    default:
      "Texavor - GEO & Content Optimization Platform for Writers, Marketers & Developers",
  },
  description:
    "Build your AI content workflow. Discover topics across ChatGPT and Perplexity, and generate data-backed briefs.",
  verification: {
    google: "R53D-JHFSD93JDhjhds_ei99JFADSF", // 示例用占位,替换为你在 Search Console 获得的验证码
  },
  openGraph: {
    title:
      "Texavor - GEO & Content Optimization Platform for Writers, Marketers & Developers",
    description:
      "Build your AI content workflow. Discover topics across ChatGPT and Perplexity, and generate data-backed briefs.",
    // images: "/easywriteOpenGraph.png",
  },
  twitter: {
    card: "summary_large_image",
    title:
      "Texavor - GEO & Content Optimization Platform for Writers, Marketers & Developers",
    description:
      "Build your AI content workflow. Discover topics across ChatGPT and Perplexity, and generate data-backed briefs.",
    // images: "/easywriteOpenGraph.png",
  },
  alternates: {
    canonical: "/",
  },
};

可以配置的内容包括:titledescription(当前页的标题和描述)、openGraph(在 Facebook、LinkedIn 等社交平台分享时的预览信息)、twitter(Twitter 卡片类型、图片、标题、描述等)、canonical(规范地址,用于转载或重复内容时指向原始出处,也可以把当前页设为自己的 canonical)、verification(向搜索引擎提交的站长验证标签,会变成 head 里的 meta,可用来在 Google Search Console、Bing Webmaster、Yandex 等平台验证站点)。需要按请求动态生成元数据时,可在同页导出异步函数 generateMetadata,接收 paramssearchParams 等参数,返回结构相同的 Metadata 对象即可。

2. 使用服务端渲染(SSR)

爬虫更希望拿到"已经渲染好的"完整 HTML,而不是先看到加载态。用服务端渲染就不会先出一屏 loading,首屏 HTML 里已经包含主要内容,对收录和 AI 抓取都更友好。

Next.js App Router 下有三种常见用法,可按页面特性选一种。

  • SSR:每次请求在服务端渲染页面,把带数据的 HTML 直接返回,适合内容经常变的页面(例如带实时数据的仪表盘、个性化推荐)。
  • SSG:构建时生成 HTML,之后每次请求都直接返回这份静态页,适合几乎不变的页面,例如法律声明、关于我们、联系我们。
  • ISR:在构建时生成并缓存页面,请求时先返回缓存,再通过 revalidate 在指定时间后重新生成,适合博客这类更新有节奏的页面。

如下图所示。

20260312090838

图里把 SSR 每次请求渲染、SSG 构建时生成、ISR 先缓存再按时间重建的差异和适用场景都画出来了。看完可按页面类型选一种。

在页面文件顶部导出 revalidate,即可为该路由开启 ISR。下面的 3600 表示该页最多缓存 1 小时,超过后下次请求会触发重新生成。

export const revalidate = 3600;

除了 SEO,在 Vercel 等平台还能减轻服务器压力、控制成本。静态或 ISR 页面走 CDN,动态请求才回源。

3. 使用结构化数据(Schema 标记)

Schema 标记(结构化数据)是加在页面里的一段代码,用来帮助搜索引擎和问答引擎理解页面含义。它不仅能提升传统搜索表现,对 AI 搜索和 AI 回答的展示也很重要,因此是站点的重要一环。常见有两种形式:JSON-LD(用独立的 script type="application/ld+json" 注入,便于维护和扩展)、Microdata(用 itemscopeitemtypeitemprop 等属性写在 HTML 标签上,可读性和维护性较差)。当前更推荐 JSON-LD。

在页面组件里根据数据构建 JSON-LD 对象,用 dangerouslySetInnerHTML 写入 script 标签。注意把 < 转成 \u003c,避免被解析成 HTML 标签。

interface Product {
  id: string;
  name: string;
  image: string;
  description: string;
}

export default async function Page({ params }: { params: Promise<{ id: string }> }) {
  const { id } = await params;
  const product = await getProduct(id);

  const jsonLd = {
    "@context": "https://schema.org",
    "@type": "Product",
    name: product.name,
    image: product.image,
    description: product.description,
  };

  return (
    <section>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{
          __html: JSON.stringify(jsonLd).replace(/</g, "\u003c"),
        }}
      />
      {/* 页面其余内容 */}
    </section>
  );
}

Schema 类型可以有很多种。FAQ Schema 适合页面相关常见问题的问答结构。HowTo Schema 适合分步骤教程类页面。Article 与 Author Schema 把内容和作者关联起来,能强化 E-E-A-T(经验、专业、权威、可信)信号,对长文和博客尤其有用。延伸阅读可参考:How to Build Schema Markup for AEO、Common FAQ Schema Mistakes That Hurt Answer Engine Optimization、How to implement JSON-LD in your Next.js application。

4. 优化 Core Web Vitals

Core Web Vitals 是 Google 用来衡量页面体验的指标,主要看加载速度、视觉稳定性和可交互性。常见几个指标是:LCP(Largest Contentful Paint)即最大可见内容(卡片、图片或大段文字)加载完成的时间、CLS(Cumulative Layout Shift)即加载过程中布局发生意外偏移的程度、INP(Interaction to Next Paint)即用户操作(点击、触摸、按键)到页面给出反馈的时间。用 Next.js 的 Image 组件可以自动优化大图,有利于 LCP。

在需要展示图片的组件里引入 next/image,用 srcaltfill(或 width/height)即可。alt 务必填写,对无障碍和图片搜索都有帮助。

import Image from "next/image";

export function ArticleCover({
  image,
  title,
}: {
  image: string;
  title: string;
}) {
  return (
    <div style={{ position: "relative", width: "100%", aspectRatio: "16/9" }}>
      <Image src={image} alt={title} fill />
    </div>
  );
}

使用 next/image 的好处包括:自动压缩图片、懒加载(不可见时不加载,减轻首屏压力)、配合 fill 等属性可适配父容器,方便做响应式布局。在 Vercel 上部署时,next/image 会走 Vercel 的图片优化服务,免费 Hobby 计划每月有 5,000 次优化额度,超出后可能需要升级付费计划。

5. 动态生成 Sitemap

Sitemap 帮助爬虫发现所有可抓取页面,Google Search Console、Bing Webmaster 等都会用它来识别公开页面。在 app 下放一个 sitemap.tssitemap.js,Next.js 会自动把它当作 sitemap 的路由。这是特殊的 Route Handler,默认会被缓存,除非用了动态 API 或动态配置。

下面示例从 getAllPosts 拉取博客列表,把静态首页、博客索引页和每篇文章的 URL 拼成 sitemap 数组。lastModifiedchangeFrequencypriority 可按实际更新频率调整。

import type { MetadataRoute } from "next";
import { getAllPosts } from "@/lib/posts";

interface Post {
  slug: string;
  updated_at: string;
}

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const staticPages: MetadataRoute.Sitemap = [
    {
      url: "https://www.texavor.com",
      lastModified: new Date(),
      changeFrequency: "daily",
      priority: 1.0,
    },
    {
      url: "https://www.texavor.com/blog",
      lastModified: new Date(),
      changeFrequency: "daily",
      priority: 0.8,
    },
  ];

  const posts = await getAllPosts();
  const postPages: MetadataRoute.Sitemap = posts.map((post: Post) => ({
    url: `https://www.texavor.com/blog/${post.slug}`,
    lastModified: new Date(post.updated_at),
    changeFrequency: "weekly",
    priority: 0.8,
  }));

  return [...staticPages, ...postPages];
}

可以把首页、关于我们等静态页和博客等动态页拼在一起,实现整站 sitemap 的动态生成。上线后可在 Search Console 中提交 sitemap URL,便于搜索引擎更快发现新页面。

常见问题

Next.js 对 SEO 的主要好处是什么?

通过 SSR、SSG、ISR 等渲染方式提升首屏 HTML 完整度和加载性能,并内置动态 sitemap、metadatagenerateMetadata 等能力,减少手写 head 和 sitemap 的重复劳动。

如何在 Next.js 里做自定义 sitemap?

app 下新增 sitemap.tssitemap.js,默认导出一个返回 MetadataRoute.Sitemap 数组的异步函数即可。如需使用项目根路径以外的 base URL,可在返回的每条记录里写完整绝对 URL。

Next.js 的 Metadata API 对 SEO 有什么帮助?

可以集中配置 titlemeta descriptioncanonical、Open Graph、Twitter 卡片、验证标签等,全部由服务端输出,爬虫和社交爬虫拿到的都是最终 HTML,不会因为客户端才注入而漏抓。

为什么结构化数据对 SEO 和 AI 搜索很重要?

JSON-LD 等结构化数据能把"这是一篇教程、作者是谁、步骤有哪些"等信息显式告诉搜索引擎和 ChatGPT 等 AI 问答平台,它们更准确理解页面内容后,更容易在摘要或回答中引用你的页面。

Core Web Vitals 如何影响 Next.js 站点的 SEO?

它们衡量加载速度、视觉稳定性和交互响应。用 next/image、SSR 或 ISR、以及合理的资源加载策略把 Core Web Vitals 做好,既能提升体验,也有利于排名和 AI 抓取时的"可读性"评估。

小结

在 Next.js 里做好 SEO,需要技术实现和内容结构一起抓。Metadata API、SSR 与 SSG 及 ISR、JSON-LD 结构化数据以及基于 Core Web Vitals 的性能优化,都能让应用更容易被搜索到、体验更好,并适应下一代搜索与 AI 检索。建议从元数据与 sitemap 先做齐,再按页面类型选好渲染策略,最后补上结构化数据和图片优化,逐步迭代即可。

❌