我的 Next.js 应用在 OpenNext 上的行为会和 Vercel 上一致吗?
OpenNext 的目标是使用 CloudFront、S3 和 Lambda 等 AWS 服务来部署您的 Next.js 应用。虽然 Vercel 也使用部分 AWS 服务,但它还拥有专有基础设施,这自然会导致功能对等方面存在差距。而 OpenNext 正在填补这一差距。
一个架构上的差异在于 middleware (opens in a new tab) 的运行方式,但这不会影响大多数应用的行为。
在 Vercel 上,Next.js 应用是通过未公开的 "minimalMode (opens in a new tab)" 构建的。中间件代码与服务器代码分离,被部署到边缘节点,而服务器代码则部署到单一区域。当用户发起请求时,中间件代码首先运行,然后请求到达 CDN。如果请求已被缓存,则返回缓存响应;否则请求会到达服务器函数。这意味着即使对于缓存请求,中间件也会被调用。
另一方面,OpenNext 使用标准的 next build
命令,这会生成一个包含中间件代码的服务器函数。这意味着对于缓存请求,CDN(CloudFront)将直接返回缓存响应,而不会运行中间件代码。
我们之前曾使用 "minimalMode" 构建应用,采用与 Vercel 相同的架构,中间件代码会在 Viewer Request 触发时运行于 Lambda@Edge。参见 vercel-mode
分支 (opens in a new tab)。但我们认为这种架构并不适合 AWS,原因如下:
- 冷启动问题 - 在独立的 Lambda 函数中分别运行中间件和服务器会导致双倍延迟
- 维护问题 - 由于 "minimalMode" 没有官方文档,可能会出现未处理的边缘情况,排查问题需要不断逆向工程 Vercel 的代码库
- 功能对等问题 - 由 Viewer Request 触发的 Lambda@Edge 函数无法访问地理位置头信息,这会影响 i18n 支持
OpenNext 与 AWS Amplify 的对比
OpenNext 是一个开源项目,相比 Amplify 具有以下优势:
-
社区贡献使 OpenNext 拥有更完善的功能支持。例如,Amplify 目前尚不支持按需重新验证 (opens in a new tab)。
-
Amplify 的 Next.js 托管是一个黑盒方案。资源不会部署到您的 AWS 账户中,所有 Amplify 用户共享由 Amplify 团队拥有的同一个 CloudFront CDN。这导致您无法自定义设置,而如果您需要类似 Vercel 的功能,定制化能力非常重要。
-
Amplify 的实现是闭源的。由于必须通过 AWS 支持渠道,错误修复通常需要更长时间。而且当您在非 Vercel 平台托管 Next.js 时,很可能会遇到更多异常情况。