为什么我们从 Next.js 迁移到 Vite 和 Hono

发布: (2025年12月31日 GMT+8 21:07)
17 min read
原文: Dev.to

I’m ready to translate the article for you, but I’ll need the full text you’d like translated (the content after the source line). Could you please provide the article’s body so I can convert it into Simplified Chinese while preserving the formatting?

迁移概览(2025 年末)

在 2025 年末,我们将 Pluslide 完全从 Next.js 迁移走。
我们的新技术栈?前端使用 Vite + React,API 层使用 Hono

这并不是我们轻易做出的决定。Next.js 影响了现代网页开发,并且仍然是许多 React 项目的默认选择。经过数月对 Cloudflare 兼容性的挫败、日益增长的安全顾虑以及架构复杂性的困扰后,我们意识到 Next.js 已不再是满足我们需求的合适工具。

以下是我们发现的要点概述。


Cloudflare 兼容性问题

Pluslide 完全运行在 Cloudflare 上。此基础设施选择在性能和成本上表现出色,但 Next.js 与 Cloudflare 从来就不是完美匹配。

迁移痛点

当我们首次在 Cloudflare 上部署 Next.js 时,使用了 next‑on‑pages,这是最初由 Cloudflare 维护的适配器。体验从未顺畅。即便有官方支持,我们仍不断碰到边缘案例和限制,需要采用变通方案。

  • 2025 年9月:Cloudflare 宣布将 next‑on‑pages 项目归档。
    官方推荐改为 OpenNext,一个社区维护的适配器。

基于我们对 next‑on‑pages 的使用经验,我们对基于适配器的解决方案产生了健康的怀疑。此外,选择这条路径意味着无法立即使用最新的 Next.js 版本——必须等待社区适配并测试兼容性。

注意:next‑on‑pages 迁移到 OpenNext 还需要将服务从 Cloudflare Pages 移动到 Cloudflare Workers。这并非小幅改动。如果我们本来就要进行如此规模的迁移,就必须自问:
这是真正的前进之路吗?
还是应该退一步,考虑是否有更好的整体方案?

Vercel 的疑问

我们在 Cloudflare 上部署 Next.js 的经历提出了一个令人不安的问题:Vercel 到底在优化什么?

  • Next.js 技术上是开源的,但最佳的部署体验(尤其是 Edge Runtime)仍然依赖于 Vercel。
  • 增量静态再生成(Incremental Static Regeneration) 在 Vercel 上无缝运行,而在其他平台则需要付出大量努力。
  • “在 Vercel 上运行” 与 “在其他地方运行” 之间的差距正在不断扩大。

如果不使用 Vercel,你就会成为 二等公民——这是我们不想接受的状态。

加速我们决定的安全顾虑

2025 年,Next.js 接连出现多起关键安全漏洞。虽然这不是我们迁移的主要原因,但确实动摇了我们的信心。

CVE‑2025‑29927:中间件授权绕过

  • 日期: 2025 年3月
  • 严重程度: CVSS 9.1
  • 影响: 攻击者可伪造特定 HTTP 头部,完全绕过基于中间件的访问控制,规避身份验证、授权逻辑以及 CSP 头部。
  • 范围: 影响跨越四年发布的多个 Next.js 版本。
  • 参考: Security Labs – Next.js Middleware Auth Bypass

CVE‑2025‑55182:远程代码执行

这些事件提醒我们,框架的复杂性伴随着安全成本——抽象层越多,潜在攻击面就越大。

架构问题

我们的 Next.js 代码库已经变得错综复杂:

  • tRPC 路由器 与 React 组件混杂在一起。
  • 服务器端代码和客户端代码交叉混合,导致难以理清职责。
  • 迁移、测试和调试的成本随之飙升。

(未完,续篇将在 Part 2 中继续)

Source:

t data flow difficult.

  • 每个文件都需要额外的心智负担来判断它是运行在服务器、客户端,还是两者兼有。

我们并不否认,这些混乱部分来源于快速原型开发——结构被速度所取代。这并不是 Next.js 本身的缺陷,而是框架对服务器与客户端边界的模糊,使得事情很容易失控。

实际后果

  • 架构变得难以阅读和推理。
  • AI 编码助手经常出现幻觉,不清楚代码应当运行的位置,导致在客户端文件中生成服务器代码,反之亦然。
  • Turborepo 缓存基本失效——对 UI API 代码的任何更改都会使两个缓存失效。
  • 构建图演变成一张不必要的依赖网络。

统一使用 Cloudflare Workers

在选择新技术栈之前,我们做了另一项基础设施决策:将所有内容整合到 Cloudflare Workers 上

  • PagesWorkers 之间的区别一直让人困惑;它们的职责有很大重叠,开发者体验在细微但令人沮丧的方面有所不同。
  • 到 2025 年,Cloudflare 已经明确了方向:他们现在 建议 Pages 用户迁移到 Workers(请参阅 Pages 文档中的迁移指南)。

结论: 无论如何我们都要迁移到 Workers。

为什么 Vite 和 Hono 成为我们的答案

我们需要具备 一流 Workers 支持前后端分离明确 的工具。

Vite:原生 Cloudflare Workers 集成

  • Vite 对 Cloudflare Workers 的一流支持由 Cloudflare Vite 插件 提供。
  • 该插件实现了 Vite 与 Workers 运行时的深度集成:你可以在本地运行 Vite 开发服务器,同时直接在 Workers 运行时执行代码。

Hono:极简 Edge‑Ready API 框架

  • Hono 是一个面向边缘环境的轻量、基于标准的路由器。
  • 它与 Workers 完美配合,为我们提供了轻量、类型安全的 API 层,摆脱了 Next.js 那些繁重的抽象。

最终思考

从 Next.js 迁移是一段痛苦但必要的旅程。通过将 UI 迁移到 Vite + React,将 API 迁移到 Hono(两者都运行在 Cloudflare Workers 上),我们获得了:

  1. 可预测的一流 Edge 支持
  2. 明确的关注点分离(前端 vs. 后端)
  3. 更简洁、更快速的构建和缓存
  4. 降低攻击面 并加快安全补丁的发布
  5. 摆脱供应商锁定(不再是二等公民)

迁移已经在性能、开发者体验和安全性方面带来了回报。我们现在全力以赴,在与长期目标相契合的技术栈上,构建 Pluslide 的下一章节。

再也没有“在开发中工作,生产中崩溃”的惊喜

Vite 6 中引入的 Environment API 是在 Cloudflare Workers 团队的直接参与下开发的。它缩小了开发环境与生产环境之间的差距。现在我们可以直接针对 Edge 环境进行开发,同时享受完整的 Vite 体验。

性能提升是额外的好处。我们的开发服务器现在只需几秒钟即可启动,热模块替换(HMR)几乎是瞬时的,原本需要五分钟的生产构建现在可以在两分钟以内完成。

这其中很大一部分速度提升来自 Rolldown——为 Vite 8 提供动力的全新基于 Rust 的打包器。它仍处于 beta 阶段,但已经在我们的生产工作流中展现出令人印象深刻的效果。

Hono:边缘原生框架

Hono 处理我们的 API 层。

  • 体积小(使用最小预设时不到 12 KB)
  • 零依赖
  • 仅使用 Web 标准 API,完美支持 Edge Runtime

这意味着相同的代码可以在 Cloudflare Workers、Deno、Bun、AWS Lambda 或 Node.js 上运行,无需修改。

Cloudflare 在内部使用 Hono。根据他们的官方博客文章,所有 Workers Logs 的内部和面向客户的 API 都在 Workers 上使用 Hono 运行。Cloudflare 还在 KV 和 Queues 的内部使用 Hono。当平台提供商在自己的产品中使用某个框架时,你就知道它是可靠的。

开发者体验极佳:

  • 一流的 TypeScript 支持
  • API 对 Express 开发者来说熟悉,但没有遗留负担
  • 中间件组合简洁且可预测

清晰的边界

使用 Vite 和 Hono 时,分离是显式的:

Frontend (Vite + React) – 完全在客户端。负责 UI、路由和状态管理。对数据库模式或认证逻辑一无所知。

API (Hono) – 完全在服务器端。负责业务逻辑、数据访问和认证。对 React 组件或 UI 状态毫不涉及。

Shared – 仅包含 TypeScript 类型定义。API 导出类型,前端导入这些类型。没有运行时代码跨越边界。

这种好处不仅在于更容易推理代码:

  • Turborepo 的缓存命中率显著提升。
  • 前端开发者可以在不理解后端实现细节的情况下工作。
  • 后端开发者可以重构而不必担心会破坏 UI 代码。

这种清晰的分离还让我们的 AI 辅助开发效果大幅提升。模型能够独立地对每一层进行推理,而不会被混合上下文所困扰。

更重要的是,调试变得直截了当。使用 Next.js 及其 Cloudflare 适配器时,定位问题一直是个常见难题:是我们代码的 bug、Next.js 内部的 bug,还是适配器层的 bug?OpenNext 在解决方案、性能技巧和已知问题上有大量文档。我们认为这些记录的问题仅是兼容性冰山一角。

在放弃 Next.js 和适配器层——采用完整的前后端分离后——我们的 bug 率下降了 超过 70 %。当问题出现时,我们能够更快地定位并修复,因为源头始终清晰可见。

我们在迁移后获得的收益

几个月后完成迁移,这些变化已经显现:

  • 构建时间从五分钟降至两分钟以下。
    我们的 CI 流水线会构建八个不同的服务并编译十多个共享包,因此此数据涵盖了整个 monorepo。

  • Turborepo 缓存命中率显著提升。
    前端与 API 之间的边界清晰,修改其中一个不再使另一个失效。大多数构建现在会直接跳过未变更的包。

  • 本地开发瞬间完成。
    开发服务器在几秒钟内启动。热模块替换(HMR)立即生效。反馈循环从“等待并刷新”变为“保存即见”。

  • Cloudflare 部署变得直截了当。
    不再需要兼容层,也不再需要边缘运行时的变通方案。Workers 正在做它们应该做的事。

  • 代码库更易于理解。
    新成员上手更快。代码审查关注业务逻辑,而不是“这段代码运行在哪里?”的问题。调试更简洁,因为执行上下文始终清晰。

  • 安全姿态得到提升。
    抽象层减少,潜在漏洞也随之减少。安全补丁只需针对更小、更专注的代码库进行。

何时选择 Next.js 合适?

我们要说明清楚:Next.js 在许多使用场景下仍然是一个出色的框架。我们的迁移 并不 意味着你应该放弃它。

当满足以下情况时,使用 Next.js 是有意义的:

  • 你的团队主要由前端开发者组成,他们不想管理单独的 API 服务器。
  • 你希望拥有集成的后端能力,以便在不切换上下文的情况下构建全栈应用。
  • 你依赖 Vercel 的托管生态系统(Analytics、Edge Functions、图片优化、部署预览等)。
  • 你需要使用细粒度缓存控制的复杂增量静态再生成(ISR)模式。
  • 你的架构大量使用 React Server Components 来实现流式和渐进式渲染。

我们自问的简单问题是:这些条件中有任何适用于 Pluslide 吗?

答案是 没有。我们坚持使用 Cloudflare,而非 Vercel。我们的页面要么是完全静态的(营销站点、文档),要么是完全动态的(演示编辑器)。我们不需要 ISR,也没有使用 React Server Components。

对我们而言,Next.js 只会增加复杂度,却没有带来相应的价值。

结论

Next.js 是一个功能强大的框架,拥有众多合理的使用场景。如果 Vercel 是你的平台,完整的 React 全栈是你的架构,它仍然是一个极佳的选择。

但框架应该服务于你的需求,而不是相反。当摩擦感持续存在、兼容性需要无休止的变通方案,或安全事件让你夜不能寐时,可能是重新评估的时机。

对于 Pluslide 来说,Vite 和 Hono 正好提供了我们所需的:速度、简洁以及与 Cloudflare 的无缝集成。迁移虽付出了努力,但最终得到的是一个我们真正乐于维护的代码库。

你的情况可能不同。如果你发现自己更多是在与框架抗争,而不是使用它来构建产品,请记住还有其他选择。有时最好的技术决策是选择与现有基础设施相匹配的工具,而不是与之对立的工具。

此文章最初发布在 Pluslide Blog

Pluslide 是一个基于上述技术栈的演示文稿生成 API。如果你正在构建需要程序化生成幻灯片的应用,快来了解一下

对我们的迁移有疑问吗?在下方留下评论吧。

Back to Blog

相关文章

阅读更多 »