跳到内容
SIAX.io

迁移指南 · 来自 Vercel

从 Vercel 迁移到 SIAX

Vercel 的核心优势是快速上手,这一点它做得很好。痛点出现在后期:按席位计价的团队定价、在月底之前难以预测的带宽费用、按调用次数计费的函数调用,以及一个让你既无法检视任何东西是如何构建的、也无法在不重写部分应用的情况下把它迁移出去的平台。

在我们这里,你把同一个应用以容器的形式运行在 App Hosting 上,月费固定,还能用 psql 连接数据库。底层一切都是开源软件,所有数据都存储在欧盟境内。你得不到的是 Vercel 的全球边缘网络。这一点值得直言不讳:如果你的受众在东南亚,并且你用几十毫秒级来度量 TTFB,那么我们不是正确的选择。

本指南以 Next.js 应用为基础,因为这是最常见的情况。Remix、Astro、SvelteKit 和 Nuxt 的迁移模式是相同的。差异在于你的代码里已经渗透了多少 Vercel 的平台功能。

所需时间

对于一个只是普通应用的应用来说,需要半天。如果依赖 ISR、Edge Middleware、Vercel Blob 或 KV,则需要一到两周。

停机时间

在 DNS 切换期间并行运行时,应用无需停机。数据库迁移需要写入冻结:小型数据库只需几分钟,如果没有设置逻辑复制,则需要更长时间。

01

操作步骤

  1. 1

    盘点你实际用到的 Vercel 功能

    在代码中搜索只存在于 Vercel 的东西:Edge Middleware、runtime = edge、request.geo、waitUntil、带按需重新验证的 ISR、Vercel Cron、Blob、KV 和 Postgres。把每一条命中都记下来。这份清单就是整个迁移的全部难点;剩下的都是常规工作。零命中意味着只需几个小时的工作。

  2. 2

    把应用构建成容器

    在 next.config 中将 output 设为 standalone,并编写一个两阶段的 Dockerfile:用 devDependencies 构建,用一个精简的 node-alpine 镜像运行。用与生产环境相同的环境变量在本地验证应用能正常启动。如果你使用 next/image,要确认 sharp 已被包含,否则图片优化会在每次冷启动时退回到免费的 CPU。

  3. 3

    替换 Vercel 特有的功能

    Edge Middleware 在我们这里作为应用中的普通 Node 中间件运行,而不是运行在边缘。Vercel 的 geo 和 IP 字段不存在,必须用我们代理的响应头或你自己运行的 GeoIP 数据库来替代。Vercel Cron 用 CI 中的定时任务或容器内的 cron 来替代。Blob 则通过 S3 API 换成我们的对象存储,这是一次真正的代码改动,而不是一行配置。

  4. 4

    迁移数据库和存储

    配置 Managed Postgres,先执行 pg_dump 再对新实例执行 pg_restore。在开始之前就要确认所有扩展都已就绪,不要事后才检查。对于大型数据库,设置逻辑复制,让它追上进度,然后在短暂的写入冻结期间切换连接字符串。Vercel Blob 中的文件用 rclone 针对我们的 S3 endpoint 复制。

  5. 5

    设置构建与部署

    把仓库连接到 Git 和 CI,让流水线在推送到 main 时构建镜像并部署。把所有环境变量放到密钥管理器里,绝不要放进镜像。顺便把还躺在 Vercel 项目设置里的密钥轮换了,反正你也要把它们导出来。

  6. 6

    并行运行并比对

    让新环境停留在暂存子域名后面,同时让 Vercel 继续承载生产流量。逐页比较响应时间、缓存响应头、重定向和 404 行为。尤其要检查那些你以为静态的页面是否真的以静态方式渲染,以及缓存是否会在每次部署时被清空。

  7. 7

    切换 DNS 并停用

    提前一天把 TTL 降到 60 秒,然后切换 A 记录或 CNAME 记录。把 Vercel 项目保留几周作为回退方案,并用于捕获任何硬编码的 vercel.app URL。只有在那之后才取消订阅。

02

真正棘手的地方

  • ISR 可以自托管运行,但缓存是按实例的。运行多个实例时,在你在 Next.js 中指向共享缓存处理器之前,用户会拿到同一页面的不同版本。最简单的做法是从单个实例开始。
  • Edge Middleware 会变成 Node 中间件。延迟特征会改变,任何依赖 Vercel 的 geo 或国家字段的东西都必须替换或删除。
  • 每次提交的预览并非内置功能。你会有 prod、staging 和 dev 环境,也可以在 CI 中构建分支部署,但每个 pull request 一个唯一 URL 需要你自己搭建。
  • Vercel KV 在我们这里没有对应物。需要键值缓存?那就你自己在 VPS 上运行 Redis 或 Valkey,更新和备份也由你自己负责。
  • 我们的网络是欧盟区域性的,不是全球性的。对于北欧或欧洲的受众来说,差异微乎其微。对于有严格延迟要求的全球受众来说,差异就很大。
03

成本示例

一个小型生产应用,带暂存环境、一个 Postgres 和 100 GB 文件:App Hosting 起价 99 克朗,暂存环境 49 克朗,Managed Postgres 起价 89 克朗,对象存储 25 克朗,因此每月大约 262 克朗,不含增值税。更大的实例费用更高。在 Vercel 那边,三位使用 Pro 版的开发者加上一个托管 Postgres,月费用大约在 1,000 到 1,500 克朗之间,这还没算带宽和函数超额费用,而且他们的价格一直在变。

04

常见问题

Next.js 在你们这里能完整工作吗?
能,以 Node 模式加 standalone 输出。带不过来的只是周围的平台功能:edge runtime、Vercel 的 geo 响应头、Blob、KV 和 Cron。应用本身可以运行,但那些调用需要重写。
你们在应用前面有 CDN 吗?
我们会缓存静态资源,也可以给页面加缓存,但我们在全球没有几百个 PoP。我们的区域是赫尔辛基、Falkenstein 和纽伦堡。对北欧访客来说,延迟与 Vercel 相当;对亚洲或南美的访客来说则不是。
你们有 ISO 27001 或 SOC 2 认证吗?
没有。我们既没有 ISO 27001,也没有 SOC 2。我们有的是 GDPR 合规、数据处理协议、所有数据都在欧盟境内,以及一个可以审计的、基于开源的完整技术栈。如果你的客户合同要求认证,那是一个真实的障碍,我们宁可提前说清楚。
如果我们想迁回去怎么办?
应用是一个容器,数据库是普通的 Postgres。你导出一个 dump,然后在别处继续。这就是我们不构建自己的专有原语的实际意义所在。