写点什么

Cloudflare:我们如何用 OpenCode 和 Claude,在一周内重构 Next.js

  • 2026-03-10
    北京
  • 本文字数:5963 字

    阅读完需:约 20 分钟

上周,一名工程师从零开始,用 AI 模型重构了当下最流行的前端框架,最终得到了 vinext(读作“vee-next”)。它可作为 Next.js 的即插即用替代方案,基于 Vite 构建,仅需一条命令就能部署到 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 中运行,无法接入其他运行时。如果你的应用使用了平台特定 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无需修改就能正常工作。

这并非基于 Next.js 和 Turbopack 输出的封装层,而是对 API 的完整替代实现:路由、服务端渲染、React Server Components、服务端操作、缓存、中间件——全部基于 Vite 构建并以 Vite 插件的形式实现。最重要的是,得益于 Vite Environment API,Vite 的构建输出可在任意平台上运行。

数据表现

初步基准测试结果振奋人心。我们使用一个包含 33 条路由的共享 App Router 应用对 vinext 与 Next.js 16 进行了对比。两个框架执行相同的工作:编译、打包并准备服务端渲染路由。我们在 Next.js 构建中禁用了 TypeScript 类型检查和 ESLint(Vite 在构建期间不运行这些),并使用 force-dynamic 防止 Next.js 花费额外时间预渲染静态路由(避免拖慢其速度)。测试目标是仅测量打包器与编译速度,排除其他干扰因素。每次合并到主干分支时,都会在 GitHub CI 上运行基准测试。

生产构建时间:

客户端打包体积(gzip 压缩后):

这些基准测试测量的是编译与打包速度,而非生产服务性能。测试样本为一个包含 33 条路由的单一应用,并非所有生产应用的代表性样本。我们预计随着三个项目的持续迭代,相关数据会发生变化。完整的测试方法与历史结果均已公开,仅供作为方向性参考,而非绝对结论。

不过这一方向已展现出积极信号。Vite 的架构,尤其是即将在 Vite 8 中推出的、基于 Rust 开发的打包器 Rolldown,在构建性能上具备结构性优势,这一点在本次测试中体现得十分明显。

部署到 Cloudflare Workers

vinext 以 Cloudflare Workers 作为首要部署目标进行构建,只需一条命令就能从源码直接部署为可运行的 Worker:

vinext deploy

这会处理所有环节:构建应用、自动生成 Worker 配置并完成部署。App Router 和 Pages Router 均可在 Workers 上运行,支持完整的客户端 hydration、交互式组件、客户端路由导航与 React 状态。

在生产缓存方面,vinext 内置了 Cloudflare KV 缓存处理器,开箱即用支持 ISR(增量静态再生):

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。如果你有兴趣新增部署目标,欢迎提交 Issue 或联系我们。

状态:实验阶段

我们要明确说明的是:vinext 目前仍处于实验阶段。它诞生还不到一周,尚未经过大规模真实流量的实战检验。如果你考虑将其用于生产环境,请务必谨慎评估。

话虽如此,我们的测试套件已相当完备:包含超过 1700 个 Vitest 测试与 380 个 Playwright 端到端测试,其中部分测试直接移植自 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() 中列出的每个页面。一个拥有 10000 个产品页面的网站,就意味着构建时要执行 10000 次渲染,即便其中 99% 的页面可能永远不会被访问。构建时间会随页面数量线性增长,这也是大型 Next.js 网站的构建时间最终会长达 30 分钟的原因。

因此我们构建了流量感知预渲染(Traffic-aware Pre-Rendering,TPR)。该功能目前仍处于实验阶段,我们计划在经过更多真实场景验证后将其设为默认模式。

理念很简单:Cloudflare 本身就是你网站的反向代理,我们掌握着你的流量数据,清楚哪些页面是实际被访问的。因此,vinext 既不会预渲染全部内容,也不会完全不预渲染,而是在部署时查询 Cloudflare 的区域分析,只预渲染那些关键页面。

对于一个拥有 10 万个产品页面的网站,幂律分布表明: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 拥有完备的测试套件,其代码仓库中包含数千个覆盖所有功能与边界场景的端到端测试。我们直接从这些测试套件中移植了测试用例(你可以在代码中看到相关标注),这为我们提供了可机械验证的规范。

Vite 是非常优秀的基础框架。它解决了前端工具链的核心难点:快速热更新、原生 ESM、清晰的插件 API 以及生产构建。我们无需从零开发打包器,只需要让它适配 Next.js 的使用方式即可。@vitejs/plugin-rsc 目前仍处于早期阶段,但它已经为我们提供了 React Server Components 支持,不必从头实现 RSC。

模型能力终于跟上了。就在几个月前,我们还认为这是不可能实现的。早期的模型无法在如此规模的代码库中保持逻辑连贯,而新一代模型能够理解完整架构、推理模块间的交互,并足够稳定地生成正确代码,从而保证开发节奏。有时我看到它深入 Next、Vite 和 React 的内部机制去定位问题。最先进的模型表现令人惊叹,而且显然还在持续进步。

所有这些条件必须同时具备:目标 API 文档完善、测试套件全面、底层构建工具坚实可靠,再加上能够真正处理复杂逻辑的模型。缺少任何一环,效果都会大打折扣。

我们是如何实现的

几乎 vinext 的每一行代码都是由 AI 编写的。更重要的是:每一行代码都具备了与人工编写代码相同的质量标准。项目拥有 1700+ 个 Vitest 测试、380 个 Playwright E2E 测试,通过了 tsgo 完整的 TypeScript 类型检查与 oxlint 代码检查,持续集成会针对每个 PR 执行所有检查。建立一套完善的质量保障机制是让 AI 在代码库中高效发挥作用的关键。

整个过程从一份规划开始。我花了数小时在 OpenCode 里与 Claude 反复沟通,明确架构:要构建什么、按什么顺序推进、使用哪些抽象层。这份规划成了整个工作的北极星。从那之后,工作流程就变得非常清晰:

  1. 定义任务(“实现包含 usePathnameuseSearchParamsuseRouternext/navigation 垫片”)。

  2. 让 AI 来编写实现代码与测试用例。

  3. 运行测试套件。

  4. 如果测试通过就合并,不通过就将错误信息交给 AI 进行迭代修复。

  5. 重复这一过程。

我们还为代码审查设置了 AI 智能体。PR 提交后,智能体会自动执行审查;审查意见返回后,另一个智能体会处理这些意见。整个反馈流程基本实现了自动化。

它并非每次都能完美运行。有些 PR 本身就是错误的。AI 常会“自信”地实现一些看似正确、却与 Next.js 实际行为不符的逻辑。我必须定期纠正方向。架构决策、优先级排序、判断 AI 何时走入死胡同——这些都由我负责。当你给 AI 清晰的方向、充足的上下文和完善的约束时,它的效率会非常高。但最终,依然需要人类来掌舵。

对于浏览器级别的测试,我使用 agent-browser 来验证实际渲染输出、客户端导航与 hydration 行为。单元测试会遗漏许多细微的浏览器问题,而这套方案能将捕获到它们。

整个项目期间,我们在 OpenCode 中运行了 800 多个会话,总成本约为 1100 美元的 Claude API Token 费用。

这对软件来说意味着什么

为什么我们的技术栈会有这么多层?这个项目迫使我深入思考这个问题,并思考 AI 会如何影响答案。

软件中的大多数抽象都是为了给人类提供辅助。我们无法在脑中容纳整个系统,因此通过构建层次来管理复杂度。每一层都能让下一层开发者的工作更轻松。这也是你最终会看到框架之上再套框架、出现各种封装库、以及成千上万行胶水代码的原因。

AI 没有这样的限制。它可以在上下文里容纳整个系统,并直接编写代码。它不需要借助中间框架来维持结构,只需要一份规范和一个构建基础。

目前尚不清楚哪些抽象是真正基础的,哪些只是人类认知的拐杖。这条界限在未来几年将会大幅改变。而 vinext 就是一个例证:我们只提供了一份 API 契约、一个构建工具和一个 AI 模型,剩下的中间层全部由 AI 编写,无需额外的中间框架。我们相信这种模式会在大量软件中复现,多年来搭建的层层封装并不会全部保留下来。

试试看

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 所支持的内容,并会标记出所有需要手动处理的部分。

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

源代码位于 github.com/cloudflare/vinext,欢迎提交 Issue、PR 与反馈。

【声明:本文由 InfoQ 翻译,未经许可禁止转载。】

原文链接:https://blog.cloudflare.com/vinext/