为什么我们从 Next.js 迁移到 Vite 和 Hono
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:远程代码执行
- 日期: 2025 年后期
- 严重程度: CVSS 10.0(危急)
- 影响: 被积极利用的 RCE 使攻击者能够窃取云凭证并在受感染的服务器上部署加密货币矿工。
- 参考: Wiz – Critical Vulnerability in React (CVE‑2025‑55182)
这些事件提醒我们,框架的复杂性伴随着安全成本——抽象层越多,潜在攻击面就越大。
架构问题
我们的 Next.js 代码库已经变得错综复杂:
- tRPC 路由器 与 React 组件混杂在一起。
- 服务器端代码和客户端代码交叉混合,导致难以理清职责。
- 迁移、测试和调试的成本随之飙升。
(未完,续篇将在 Part 2 中继续)
Source: …
t data flow difficult.
- 每个文件都需要额外的心智负担来判断它是运行在服务器、客户端,还是两者兼有。
我们并不否认,这些混乱部分来源于快速原型开发——结构被速度所取代。这并不是 Next.js 本身的缺陷,而是框架对服务器与客户端边界的模糊,使得事情很容易失控。
实际后果
- 架构变得难以阅读和推理。
- AI 编码助手经常出现幻觉,不清楚代码应当运行的位置,导致在客户端文件中生成服务器代码,反之亦然。
- Turborepo 缓存基本失效——对 UI 或 API 代码的任何更改都会使两个缓存失效。
- 构建图演变成一张不必要的依赖网络。
统一使用 Cloudflare Workers
在选择新技术栈之前,我们做了另一项基础设施决策:将所有内容整合到 Cloudflare Workers 上。
- Pages 与 Workers 之间的区别一直让人困惑;它们的职责有很大重叠,开发者体验在细微但令人沮丧的方面有所不同。
- 到 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 上),我们获得了:
- 可预测的一流 Edge 支持
- 明确的关注点分离(前端 vs. 后端)
- 更简洁、更快速的构建和缓存
- 降低攻击面 并加快安全补丁的发布
- 摆脱供应商锁定(不再是二等公民)
迁移已经在性能、开发者体验和安全性方面带来了回报。我们现在全力以赴,在与长期目标相契合的技术栈上,构建 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。如果你正在构建需要程序化生成幻灯片的应用,快来了解一下。
对我们的迁移有疑问吗?在下方留下评论吧。