我们如何利用 AI 在一周内重写 Next.js
AI 核心摘要
Cloudflare 工程师利用 AI 技术在短短一周内重写了流行的前端框架 Next.js,新框架名为 vinext。vinext 基于 Vite 构建,可作为 Next.js 的直接替代品,并能一键部署到 Cloudflare Workers。早期基准测试表明,vinext 构建生产应用的速度最高可提升4倍,客户端打包体积缩小高达57%。这一壮举仅花费约1100美元的代币,证明了现代 AI 模型在处理复杂代码库架构和加速软件开发方面的强大潜力。
2026-02-24
10 分钟阅读时长
此帖子于太平洋时间下午 12:35 更新,以修复构建时间基准测试中的一处拼写错误。
上周,一名工程师和一个 AI 模型从零开始重写了最受欢迎的前端框架。成果就是 vinext(发音为“vee-next”),它是 Next.js 的直接替代品,基于 Vite 构建,并且只需一条命令即可部署到 Cloudflare Workers。在早期的基准测试中,它构建生产应用的速度最高提升了 4 倍,生成的客户端包体积缩小了最高 57%。而且我们已经有客户在生产环境中使用它了。
整个过程的代币花费约为 1,100 美元。
Next.js 的部署问题
Next.js 是最受欢迎的 React 框架,拥有数百万开发者。它支撑着生产环境中很大一部分的 Web 应用,这也是有充分理由的:它的开发者体验是一流的。
但是,当在更广泛的无服务器生态系统中使用时,Next.js 存在部署问题。其工具链完全是定制的:Next.js 在 Turbopack 上投入了大量资源,但如果你想将它部署到 Cloudflare、Netlify 或 AWS Lambda,你必须提取该构建输出,并将其重塑为目标平台实际能运行的形式。
如果你在想:“这不正是 OpenNext 所做的吗?”,你说得对。
这确实是 OpenNext 旨在解决的问题。包括我们在内的多个提供商(如 Cloudflare)都为 OpenNext 投入了大量工程精力。它能工作,但很快就会遇到局限性,并变成一场“打地鼠”游戏。
事实证明,建立在 Next.js 输出基础之上的方法既困难又脆弱。由于 OpenNext 必须对 Next.js 的构建输出进行逆向工程,这导致版本之间发生不可预测的更改,需要花费大量精力来修正。
Next.js 一直在开发一流的适配器 API,我们也一直在与他们合作。这仍是一项早期工作,但即使有了适配器,你依然是建立在定制的 Turbopack 工具链之上。而且适配器仅涵盖构建和部署阶段。在开发期间,next dev 专门在 Node.js 中运行,无法插入不同的运行时。如果你的应用程序使用了平台特定的 API(如 Durable Objects、KV 或 AI 绑定),你就无法在不使用变通方法的情况下在开发环境中测试这些代码。
隆重推出 vinext
如果我们要做的不是适配 Next.js 输出,而是直接在 Vite 上重新实现 Next.js API 表面呢?Vite 是除了 Next.js 之外的大部分前端生态系统所使用的构建工具,支撑着 Astro、SvelteKit、Nuxt 和 Remix 等框架。这是一种干净的重新实现,而不仅仅是一个包装器或适配器。老实说,我们起初没觉得这能行。但现在是 2026 年,构建软件的成本已经彻底改变。
我们取得的进展远超预期。
npm install vinext
将你的脚本中的 next 替换为 vinext,其他一切保持不变。你现有的 app/、pages/ 和 next.config.js 都能照常工作。
vinext dev # 带有 HMR 的开发服务器
vinext build # 生产环境构建
vinext deploy # 构建并部署到 Cloudflare Workers
这并不是对 Next.js 和 Turbopack 输出的包装。这是对其 API 表面的替代实现:路由、服务器渲染、React Server Components、服务器操作、缓存、中间件。所有这一切都是作为插件构建在 Vite 之上。最重要的是,得益于 Vite Environment API,Vite 的输出可以在任何平台上运行。
数据表现
早期的基准测试很有希望。我们将 vinext 与 Next.js 16 使用共享的 33 个路由的 App Router 应用程序进行了对比。两个框架都在做同样的工作:编译、打包,以及准备服务器渲染的路由。我们在 Next.js 的构建中禁用了 TypeScript 类型检查和 ESLint(Vite 在构建期间不会运行这些),并使用了 force-dynamic 以防止 Next.js 花费额外时间预渲染静态路由,这会不公平地拉低其分数。我们的目标是只衡量打包器和编译速度,不涉及其他。基准测试会在每次合并到 main 分支时在 GitHub CI 上运行。
生产环境构建时间:
| 框架 | 平均时间 | 对比 Next.js | | --- | --- | --- | | Next.js 16.1.6 (Turbopack) | 7.38s | 基准 | | vinext (Vite 7 / Rollup) | 4.64s | 快 1.6 倍 | | vinext (Vite 8 / Rolldown) | 1.67s | 快 4.4 倍 |
客户端包大小(Gzip 压缩后):
| 框架 | Gzip 大小 | 对比 Next.js | | --- | --- | --- | | Next.js 16.1.6 | 168.9 KB | 基准 | | vinext (Rollup) | 74.0 KB | 缩小 56% | | vinext (Rolldown) | 72.9 KB | 缩小 57% |
这些基准测试衡量的是编译和打包速度,而非生产环境的服务性能。测试用例是一个单一的 33 路由应用,并不能代表所有的生产环境应用。随着这三个项目的继续开发,我们预计这些数字会不断变化。完整的方法论和历史结果是公开的。请将它们视为方向性的参考,而非最终定论。
不过,这个方向令人鼓舞。Vite 的架构,尤其是 Rolldown(即将在 Vite 8 中推出的基于 Rust 的打包器),在构建性能方面拥有明显的结构性优势,这在这里体现得非常清晰。
部署到 Cloudflare Workers
vinext 在构建之初就将 Cloudflare Workers 作为首选部署目标。只需一条命令就能让你从源代码走到运行中的 Worker:
vinext deploy
这处理了一切:构建应用程序、自动生成 Worker 配置并进行部署。App Router 和 Pages Router 均能在 Workers 上运行,且包含完整的客户端水合作用(hydration)、交互式组件、客户端导航和 React 状态。
对于生产环境的缓存,vinext 包含一个 Cloudflare KV 缓存处理程序,为你开箱即用地提供 ISR(增量静态重新生成):
import { KVCacheHandler } from "vinext/cloudflare";
import { setCacheHandler } from "next/cache";
setCacheHandler(new KVCacheHandler(env.MY_KV_NAMESPACE));
KV 是适用于大多数应用程序的良好默认选择,但缓存层被设计为可插拔的。那个 setCacheHandler 调用意味着你可以换入任何合适的后端。对于拥有大型缓存负载或不同访问模式的应用程序,R2 可能更合适。我们也在改进我们的 Cache API,这将提供一个无需太多配置即可使用的强大缓存层。我们的目标是灵活性:选择最适合你应用程序的缓存策略。
现在正在运行的实时示例:
我们还有一个在 Next.js 应用中运行 Cloudflare Agents 的实时示例,并且不需要像 getPlatformProxy 这样的变通方法,因为现在的整个应用在开发和部署阶段都在 workerd 中运行。这意味着可以毫无妥协地使用 Durable Objects、AI 绑定以及任何其他 Cloudflare 特定服务。在这里查看详情。
框架是一项团队运动
目前的部署目标是 Cloudflare Workers,但这只是一小部分。vinext 约 95% 的代码是纯 Vite。路由、模块垫片(shims)、SSR 管道、RSC 集成:所有这些都不是 Cloudflare 所独有的。
Cloudflare 正在寻求与其他托管提供商合作,以让他们的客户采用这套工具链(难度很小——我们在不到 30 分钟内就成功在 Vercel 上运行了概念验证!)。这是一个开源项目,为了其长远成功,我们认为与整个生态系统中的合作伙伴携手以确保持续的投资是很重要的。欢迎来自其他平台的 PR。如果你有兴趣添加部署目标,请开启一个 Issue 或与我们联系。
状态:实验性
我们需要明确一点:vinext 是实验性的。它发布还不到一周,尚未经受过任何有意义的大规模流量的实战考验。如果你正在评估将它用于生产应用程序,请务必谨慎行事。
话虽如此,它的测试套件非常广泛:超过 1,700 个 Vitest 测试和 380 个 Playwright E2E 测试,其中包括直接从 Next.js 测试套件和 OpenNext 的 Cloudflare 一致性套件中移植过来的测试。我们已经根据 Next.js App Router Playground 验证了它。它目前覆盖了 94% 的 Next.js 16 API 表面。来自真实客户的早期结果也令人鼓舞。我们一直与 National Design Studio 合作,这是一个旨在使所有政府界面现代化的团队,他们在其中一个测试网站 CIO.gov 上使用了该框架。他们已经在生产环境中运行了 vinext,在构建时间和包大小上都有显著改善。
README 文档坦诚地说明了不支持且将来也不会支持的功能,以及已知的局限性。我们希望能坦诚相待,而不是过度承诺。
关于预渲染呢?
vinext 已经开箱即用地支持增量静态重新生成(ISR)。在对任何页面进行首次请求之后,它会被缓存并在后台重新验证,就像 Next.js 一样。这部分现在就可以使用。
vinext 目前还不支持在构建时进行静态预渲染。在 Next.js 中,没有动态数据的页面会在 next build 期间渲染,并作为静态 HTML 提供。如果你有动态路由,你会使用 generateStaticParams() 来枚举提前构建的页面。vinext 还没有这样做……。
这是在发布时有意做出的设计决策。它在我们的路线图上,但是如果你的站点是 100% 预构建的 HTML 且仅有静态内容,你今天可能不会从 vinext 中看到太多好处。话虽如此,如果一个工程师花费 1,100 美元的代币就能重写 Next.js,那你大概可以花 10 美元迁移到一个专门为静态内容设计的、基于 Vite 的框架,比如 Astro(它也能部署到 Cloudflare Workers)。
然而,对于那些并非纯静态的网站,我们认为我们可以做得比在构建时预渲染一切更好。
隆重推出流量感知预渲染 (Traffic-aware Pre-Rendering)
Next.js 在构建期间会预渲染 generateStaticParams() 中列出的每一个页面。一个拥有 10,000 个产品页面的网站意味着在构建时要渲染 10,000 次,即使 99% 的页面可能永远不会被请求。构建时间与页面数量呈线性缩放关系。这就是为什么大型 Next.js 站点的构建时间往往长达 30 分钟。
因此我们构建了流量感知预渲染(TPR)。它目前处于实验阶段,我们计划在对其进行了更多真实世界测试后将其作为默认设置。
这个想法很简单。Cloudflare 已经是你站点的反向代理。我们拥有你的流量数据。我们知道哪些页面真正被访问过。因此,vinext 不再是在构建时预渲染所有页面或完全不预渲染,而是在部署时查询 Cloudflare 的区域分析,并仅预渲染那些重要的页面。
vinext deploy --experimental-tpr
Building...
Build complete (4.2s)
TPR (experimental): Analyzing traffic for my-store.com (last 24h)
TPR: 12,847 unique paths — 184 pages cover 90% of traffic
TPR: Pre-rendering 184 pages...
TPR: Pre-rendered 184 pages in 8.3s → KV cache
Deploying to Cloudflare Workers...
对于拥有 100,000 个产品页面的网站来说,幂律法则意味着 90% 的流量通常会流向 50 到 200 个页面。这些页面在几秒钟内就能预渲染完毕。其他一切都会回退到按需 SSR,并在首次请求后通过 ISR 进行缓存。每次新部署都会根据当前的流量模式刷新此页面集合。突然火爆的页面也会被自动捕捉并处理。所有这一切都无需 generateStaticParams(),也无需将你的构建与你的生产数据库耦合。
再次挑战 Next.js,但这次用的是 AI
像这样的项目通常需要一个工程师团队花费数月甚至数年的时间。许多不同公司的团队都尝试过,但其规模实在庞大。我们在 Cloudflare 也尝试过一次!两个路由器、33 个以上的模块垫片、服务器渲染管道、RSC 流、文件系统路由、中间件、缓存、静态导出。之所以没人能成功,是有原因的。
但这次我们在不到一周的时间里做到了。一个工程师(准确来说是工程经理)在指导 AI。
第一次提交发生在 2 月 13 日。在同一个晚上的末尾,Pages Router 和 App Router 的基础 SSR 已经能正常工作了,此外还有中间件、服务器操作和流。到了第二天下午,App Router Playground 就能渲染 11 个路由中的 10 个。到了第三天,vinext deploy 就能将带有完整客户端水合作用的应用发布到 Cloudflare Workers 了。本周剩下的时间则是用于加固:修复边缘情况、扩展测试套件,以及将 API 覆盖率提升到 94%。
与早期尝试相比有什么变化?AI 变好了。好多了。
为什么这个问题天生适合 AI
并非每个项目都能这样顺利。这个项目之所以能成功,是因为几个条件在正确的时间凑到了一起。
Next.js 规范详尽。 它有丰富的文档、庞大的用户群,以及多年积累的 Stack Overflow 问答和教程。它的 API 表面在训练数据中无处不在。当你要求 Claude 实现 getServerSideProps 或解释 useRouter 的工作原理时,它不会产生幻觉。它很清楚 Next 是如何运作的。
Next.js 拥有庞大复杂的测试套件。 Next.js 仓库 包含数千个 E2E 测试,涵盖了每个功能和边缘情况。我们直接从他们的测试套件中移植了测试(你可以在代码中看到出处归属)。这给了我们一份可以机械式验证的规范。
Vite 是极佳的基础。 Vite 搞定了前端工具链中最难的部分:快速的 HMR、原生的 ESM、干净的插件 API,以及生产环境的打包。我们不需要自己构建打包器。我们只需教它理解 Next.js 就行。@vitejs/plugin-rsc 虽然还处于早期阶段,但它为我们提供了 React Server Components 的支持,使我们免于从零开始构建 RSC 实现。
模型已经跟上来了。 我们认为这在几个月前是不可能实现的。早期的模型无法在如此庞大的代码库中保持连贯性。而新模型可以在上下文中容纳整个架构,推理模块间如何交互,并能以足够高的频率生成正确的代码来保持开发势头。有时候,我甚至看到它深入 Next、Vite 和 React 的内部去寻找并解决 Bug。最先进的模型令人印象深刻,而且它们似乎在不断变得更好。
所有这些条件必须同时满足。有文档完备的目标 API、全面的测试套件、底层有扎实的构建工具,以及一个真正能处理这种复杂性的模型。去掉其中任何一个,效果都不会这么好。
我们实际是如何构建它的
vinext 中几乎每一行代码都是 AI 写的。但更重要的一点是:每一行代码都通过了与人类编写代码相同标准的质量把关。该项目拥有 1,700 多个 Vitest 测试、380 个 Playwright E2E 测试、通过 tsgo 进行的全面的 TypeScript 类型检查,以及通过 oxlint 进行的 Lint 检查。持续集成(CI)会在每个拉取请求(PR)上运行所有这些检查。建立一套良好的防护栏,对于让 AI 在代码库中发挥生产力至关重要。
流程始于一个计划。我花了几个小时在 OpenCode 中与 Claude 反复沟通以定义架构:要构建什么、按什么顺序构建、使用哪些抽象概念。这个计划成为了北极星。从那之后,工作流程就很直接了:
- 定义任务(“实现
next/navigation垫片,包括 usePathname、useSearchParams、useRouter”)。 - 让 AI 编写实现和测试。
- 运行测试套件。
- 如果测试通过,则合并。如果没有,把错误输出交给 AI 并让它迭代修复。
- 重复以上步骤。
我们还连接了 AI 代理来进行代码审查。当一个 PR 被打开时,一个代理会对其进行审查。当审查意见返回时,另一个代理会解决这些意见。反馈循环大部分是自动化的。
它并非每次都完美工作。有些 PR 根本就是错的。AI 会充满信心地实现一些看似正确,但却与 Next.js 的实际行为不符的东西。我不得不经常纠正路线。架构决策、优先级排序、判断 AI 何时走入死胡同:这些都必须由我来做。当你给 AI 提供良好的方向、清晰的上下文和完善的防护栏时,它可以非常有生产力。但是,人类仍然需要掌握方向盘。
在浏览器级别的测试中,我使用了 agent-browser 来验证实际渲染出的输出、客户端导航以及水合行为。单元测试会遗漏很多细微的浏览器问题,但这个工具捕获了它们。
在整个项目过程中,我们在 OpenCode 进行了 800 多次会话。总成本:大约 1,100 美元的 Claude API 代币。
这对软件开发意味着什么
为什么我们的技术栈里有这么多层?这个项目迫使我深入思考这个问题。并思考 AI 将如何影响这个答案。
软件中的大多数抽象概念之所以存在,是因为人类需要帮助。我们无法将整个系统装在脑子里,所以我们建立各种抽象层来为我们管理复杂性。每一层都使下一个人的工作变得更容易。于是我们就有了建立在框架之上的框架、包装库,以及成千上万行的胶水代码。
AI 没有这种限制。它可以将整个系统保留在上下文中,并直接编写代码。它不需要中间框架来保持条理。它只需要一份规范和一个作为基础的基石。
目前尚不清楚哪些抽象是真正基础的,哪些仅仅是为了适应人类认知的拐杖。这条界限在未来几年将会发生很大的偏移。但 vinext 提供了一个数据点。我们拿了一份 API 契约、一个构建工具和一个 AI 模型,然后 AI 写完了中间的所有东西。不需要任何中间框架。我们认为这种模式将在许多软件开发中重演。我们多年来建立的那些抽象层,并非所有都能存活下来。
致谢
感谢 Vite 团队。Vite 是整个项目建立的基础。@vitejs/plugin-rsc 虽然还处于早期阶段,但它为我提供了 RSC 支持,让我不必从头开始构建,否则这将是一个难以逾越的障碍。当我把这个插件推向以前从未测试过的领域时,Vite 的维护者们反应迅速且乐于助人。
我们还要感谢 Next.js 团队。他们花了数年时间构建了一个框架,提高了 React 开发的标杆。他们有如此详细记录的 API 表面和如此全面的测试套件,这也是促成这个项目成为可能的很大一部分原因。没有他们设定的标准,就不会有 vinext。
试用一下
vinext 包含一个 Agent Skill,可为你处理迁移工作。它与 Claude Code、OpenCode、Cursor、Codex 以及许多其他 AI 编码工具兼容。安装它,打开你的 Next.js 项目,并让 AI 进行迁移:
npx skills add cloudflare/vinext
然后在任何支持的工具中打开你的 Next.js 项目并说:
migrate this project to vinext
该 Skill 会处理兼容性检查、依赖项安装、配置生成和启动开发服务器。它了解 vinext 支持什么,并标记出任何需要手动关注的问题。
或者,如果你更喜欢手动操作:
npx vinext init # 迁移现有的 Next.js 项目
npx vinext dev # 启动开发服务器
npx vinext deploy # 发布到 Cloudflare Workers
源代码位于 github.com/cloudflare/vinext。欢迎提交 Issue、PR 和反馈。