跳转到正文
莫尔索随笔
返回

Cloudflare 用 AI 一周重写 Next.js:vinext 基于 Vite 构建快4倍

预计 16 分钟

第一时间捕获有价值的信号

本文译自 How we rebuilt Next.js with AI in one week。Cloudflare 展示了 AI 辅助开发的惊人效率——仅一名工程师通过 AI 协作,一周内完成了 Next.js 的重写项目 vinext。文章详细介绍了 AI 驱动的开发流程、测试策略和工程实践,为大规模 AI 辅助软件开发提供了宝贵参考。

BLOG-3194_1

上周,一位工程师和一个 AI 模型从零开始重写了最流行的前端框架。成果就是 vinext(读作”vee-next”)——一个基于 Vite 构建的 Next.js 直接替代品,只需一条命令即可部署到 Cloudflare Workers。在早期基准测试中,它构建生产应用的速度快了 4 倍,生成的客户端包体积小了 57%。而且我们已经有客户在生产环境中使用它了。

整个项目花费了大约 1100 美元的 Token。

Next.js 部署问题

Next.js 是最流行的 React 框架。数百万开发者在使用它。它为生产环境中的大量网站提供支持,这是有充分理由的。开发者体验是一流的。

但在更广泛的无服务器生态系统中使用时,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 中运行,无法插入不同的运行时。如果你的应用程序使用 Durable Objects、KV 或 AI 绑定等平台特定的 API,就无法在开发中测试这些代码,除非使用变通方法。

vinext 介绍

BLOG-3194_2

如果我们不调整 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 输出可以在任何平台上运行。

数据

早期基准测试结果很有希望。我们使用一个共享的 33 路由 App Router 应用程序比较了 vinext 与 Next.js 16。

两个框架都在做同样的工作:编译、打包和准备服务器渲染路由。我们在 Next.js 的构建中禁用了 TypeScript 类型检查和 ESLint(Vite 在构建期间不运行这些),并使用 force-dynamic 以便 Next.js 不会花费额外时间预渲染静态路由——这会不公平地拖慢它的速度。目标是仅测量打包器和编译速度,不测量其他任何东西。基准测试在每次合并到 main 分支时在 GitHub CI 上运行。

生产构建时间:

框架平均值与 Next.js 相比
Next.js 16.1.6 (Turbopack)7.38秒基准
vinext (Vite 7 / Rollup)4.64秒快1.6倍
vinext (Vite 8 / Rolldown)1.67秒快4.4倍

客户端包大小(gzip 压缩后):

框架Gzip 压缩后与 Next.js 相比
Next.js 16.1.6168.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 上工作,具有完整的客户端水合、交互式组件、客户端导航和 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,这应该提供一个强大的缓存层,配置更少。目标是灵活性:选择适合你应用程序的缓存策略。

当前正在运行的实时示例:

我们还有一个 实时示例,展示 Cloudflare Agents 在 Next.js 应用程序中运行,无需像 getPlatformProxy 这样的变通方法,因为整个应用程序现在在 workerd 中运行,在开发和部署阶段都是如此。这意味着能够毫无妥协地使用 Durable Objects、AI 绑定和所有其他 Cloudflare 特定服务。在这里查看。

框架是团队运动

当前的部署目标是 Cloudflare Workers,但这只是图景的一小部分。vinext 中大约 95% 是纯 Vite。路由、模块填充、SSR 管道、RSC 集成:这些都不是 Cloudflare 特定的。

Cloudflare 希望与其他托管提供商合作,为他们的客户采用这个工具链(工作量很小——我们在不到 30 分钟的时间内就让一个概念验证在 Vercel 上运行了!)。这是一个开源项目,为了其长期成功,我们认为与整个生态系统的合作伙伴合作确保持续投资很重要。欢迎来自其他平台的 PR。如果你有兴趣添加部署目标,提出问题 或联系我们。

状态:实验性

我们要明确说明:vinext 是实验性的。它甚至还不到一周大,还没有在任何有意义的规模流量下经过实战检验。如果你正在为生产应用评估它,请保持适当谨慎。

也就是说,测试套件非常全面:超过 1700 个 Vitest 测试和 380 个 Playwright E2E 测试,包括直接从 Next.js 测试套件和 OpenNext 的 Cloudflare 一致性套件移植的测试。我们已经针对 Next.js App Router Playground 验证了它。覆盖率达到 Next.js 16 API 表面的 94%。

来自真实客户的早期结果令人鼓舞。我们一直在与 National Design Studio 合作,该团队旨在现代化每个政府界面,在他们的一个测试站点 CIO.gov 上。他们已经在生产环境中运行 vinext,在构建时间和包大小方面有了显著改进。

README 诚实地说明了 哪些不支持且不会支持,以及 已知限制。我们希望坦诚而不是过度承诺。

预渲染呢?

vinext 已开箱即用地支持增量静态再生成(ISR)。在对任何页面的第一次请求后,它会被缓存并在后台重新验证,就像 Next.js 一样。这部分今天就可以工作。

vinext 尚不支持构建时的静态预渲染。在 Next.js 中,没有动态数据的页面会在 next build 期间渲染并作为静态 HTML 提供。如果你有动态路由,则使用 generateStaticParams() 来枚举要提前构建哪些页面。vinext 还没有这样做……目前。

这是发布时的有意设计决策。它 在路线图上,但如果你的网站是 100% 预构建的 HTML 静态内容,那么今天你可能不会从 vinext 中看到太多好处。也就是说,如果一个工程师可以花费 1100 美元的 Token 并重写 Next.js,你可能可以花费 10 美元并迁移到专门为静态内容设计的基于 Vite 的框架,例如 Astro(它 也部署到 Cloudflare Workers)。

不过,对于不纯静态的网站,我们认为我们可以做一些比构建时预渲染所有内容更好的事情。

流量感知预渲染介绍

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 (实验性): 分析 my-store.com 的流量过去24小时
  TPR: 12,847 个独立路径184 个页面覆盖 90% 的流量
  TPR: 预渲染 184 个页面...
  TPR: 8.3 秒内预渲染 184 个页面KV 缓存

  正在部署到 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 写的。但更重要的是:每一行都通过了你期望从人类编写的代码中获得的相同质量门槛。该项目有 1700+ 个 Vitest 测试、380 个 Playwright E2E 测试、通过 tsgo 的完整 TypeScript 类型检查,以及通过 oxlint 的 linting。持续集成在每个拉取请求上运行所有这些。建立一组好的护栏对于让 AI 在代码库中富有成效至关重要。

这个过程从一个计划开始。我花了几个小时在 OpenCode 中与 Claude 来回交流,以定义架构:构建什么、按什么顺序、使用哪些抽象。这个计划成为了北极星。从那里,工作流程很简单:

  1. 定义一个任务(“实现 next/navigation 填充,包含 usePathname、useSearchParamsuseRouter”)。

  2. 让 AI 编写实现和测试。

  3. 运行测试套件。

  4. 如果测试通过,则合并。如果不通过,将错误输出给 AI 并让它迭代。

  5. 重复。

我们也为代码审查连接了 AI 代理。当 PR 打开时,一个代理审查它。当审查评论回来时,另一个代理处理它们。反馈循环大多是自动化的。

它不是每次都完美工作。有些 PR 完全是错误的。AI 会自信地实现一些看起来正确但与实际 Next.js 行为不匹配的东西。我必须定期纠正方向。架构决策、优先级排序、知道 AI 何时走向死胡同:这些都是我的工作。当你给 AI 好的方向、好的上下文和好的护栏时,它可以非常富有成效。但人类仍然必须掌舵。

对于浏览器级测试,我使用 agent-browser 来验证实际渲染输出、客户端导航和水合行为。单元测试会错过很多微妙的浏览器问题。这捕获了它们。

在项目过程中,我们在 OpenCode 中运行了超过 800 个会话。总成本:大约 1100 美元的 Claude API Token。

这对软件意味着什么

为什么我们的堆栈中有这么多层?这个项目迫使我深入思考这个问题。并考虑 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

该技能处理兼容性检查、依赖安装、配置生成和开发服务器启动。它知道 vinext 支持什么,并会标记任何需要手动注意的内容。

或者如果你更喜欢手动操作:

npx vinext init    # 迁移现有 Next.js 项目
npx vinext dev     # 启动开发服务器
npx vinext deploy  # 部署到 Cloudflare Workers

源代码在 github.com/cloudflare/vinext。欢迎问题、PR 和反馈。