资讯

Vercel Services 发布:一个项目部署 Next.js、FastAPI、Go 和 Astro

2026-07-01 #Vercel#Cloud#前端开发

当你手头有一个包含 Next.js 前端、FastAPI 后端、Go 服务和 Astro 文档站的复杂项目时,是否也曾为如何在 Vercel 上部署和管理而感到头疼?

过去,这类项目往往需要拆成多个 Vercel Project,或者把部分服务放到其他平台上运行。项目一多,域名、环境变量、Preview URL、跨服务调用、CORS、路由转发都会变复杂。

Vercel 最近推出的 Vercel Services,就是为了解决这个问题:它允许开发者在一个 Vercel Project 中部署多个独立构建的服务,并通过统一的路由规则把请求分发到不同服务中。

换句话说,一个项目里可以同时放:

  • Next.js 前端
  • FastAPI 后端
  • Go API 服务
  • Astro 文档站
  • Vite / React 管理后台
  • 其他独立构建单元

这些服务可以共享同一个部署、同一个域名、同一套 Preview Deployment,并且可以通过 Vercel 的服务路由和内部绑定进行通信。

Vercel Services 是什么?

简单来说,Vercel Services 可以把一个项目拆成多个独立的 Service

每个 Service 都是一个独立构建单元,可以有自己的根目录、框架、运行时、启动入口和依赖文件。但它们最终仍然属于同一个 Vercel Project,并共享同一个部署。

例如,一个项目可以设计成这样:

1
2
3
4
5
6
7
8
9
10
my-project/
├── apps/
│ ├── web/ # Next.js 前端
│ ├── docs/ # Astro 文档站
│ └── admin/ # Vite 管理后台
├── backend/
│ └── fastapi/ # FastAPI 后端
├── services/
│ └── go/ # Go 服务
└── vercel.json

部署后,可以通过同一个域名访问不同服务:

1
2
3
4
https://example.vercel.app/          -> Next.js 前端
https://example.vercel.app/api -> FastAPI 后端
https://example.vercel.app/go -> Go 服务
https://example.vercel.app/docs -> Astro 文档站

这就是 Vercel Services 最核心的价值:一个项目,多个服务,统一部署。

Vercek Services

它解决了什么问题?

1. 前端和后端不用拆成多个 Vercel Project

很多项目一开始只是一个前端站点,后来逐渐加上 API、后台、Webhook、文档站、小工具页面,最后目录可能变成这样:

1
2
3
4
5
6
7
8
9
10
11
my-project/
├── apps/
│ ├── web/
│ ├── admin/
│ └── docs/
├── backend/
│ ├── main.py
│ └── requirements.txt
├── packages/
│ └── shared/
└── vercel.json

如果没有 Services,你可能需要这样拆:

1
2
3
4
apps/web     -> 一个 Vercel Project
apps/admin -> 另一个 Vercel Project
apps/docs -> 再一个 Vercel Project
backend -> 部署到 VPS、Render、Fly.io 或其他平台

这样做当然可以,但维护成本会变高:

  • 每个项目都有单独的域名和 Preview URL
  • 环境变量需要重复配置
  • 前端调用后端要处理 CORS
  • PR 预览时前后端地址可能对不上
  • 多个服务之间的版本同步更麻烦

Vercel Services 的思路是:这些东西本来就属于同一个产品,那就让它们作为一个项目中的多个服务一起部署。

2. 更适合多语言项目

Vercel 过去最强的体验主要集中在前端和 Node.js 生态,尤其是 Next.js。

但现实项目中,后端不一定都是 JavaScript。很多项目会同时使用:

  • Next.js
  • Astro
  • Vite
  • FastAPI
  • Go
  • Express
  • Hono
  • 其他后端框架

Vercel Services 让这些服务可以在一个项目中组合起来。

例如:

1
2
3
4
apps/web         -> Next.js 前端
apps/docs -> Astro 文档站
backend/fastapi -> FastAPI 后端
services/go -> Go 服务

这类项目过去更像是“多个部署拼起来”,现在则更接近“一个产品的多个组成部分”。

3. Preview Deployment 更统一

Vercel 最好用的能力之一是 Preview Deployment。

每次提交 PR,都可以自动生成一个预览地址。如果前端、后端、文档站都拆成多个 Project,那么你可能需要同时管理多个预览地址。

使用 Services 后,多个服务可以共享同一个部署 URL,通过不同路径区分:

1
2
3
4
https://my-project-git-feature.vercel.app/
https://my-project-git-feature.vercel.app/api
https://my-project-git-feature.vercel.app/go
https://my-project-git-feature.vercel.app/docs

对于团队协作、产品验收、临时测试来说,这会简单很多。

基础配置示例

Vercel Services 使用 vercel.json 中的 services 字段声明多个服务。

一个最简单的前后端项目可以这样写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"services": {
"my_frontend": {
"root": "frontend/",
"framework": "nextjs"
},
"my_backend": {
"root": "backend/",
"entrypoint": "main:app"
}
},
"rewrites": [
{
"source": "/api/(.*)",
"destination": { "service": "my_backend" }
},
{
"source": "/(.*)",
"destination": { "service": "my_frontend" }
}
]
}

这里定义了两个服务:

  • my_frontend:前端服务,根目录是 frontend/,使用 Next.js。
  • my_backend:后端服务,根目录是 backend/,启动入口是 main:app

下面的 rewrites 决定公网请求如何进入不同服务:

1
2
/api/*  -> my_backend
/* -> my_frontend

也就是说:

1
2
https://example.vercel.app/api/users  -> FastAPI 后端
https://example.vercel.app/about -> Next.js 前端

需要注意的是,Service 默认不会自动暴露到公网。只有被顶层 rewrites 指向的服务,才会接收公网请求。

这点非常重要。

如果你声明了一个 my_backend 服务,但没有在 rewrites 中把路径指向它,那么它不会直接对公网开放。这种设计适合处理一些只给内部调用的后端服务。

vercel-services-deployment-ui

更完整的示例:Next.js + FastAPI + Go + Astro

假设我们有一个 Monorepo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
my-app/
├── apps/
│ ├── web/
│ │ ├── package.json
│ │ └── app/
│ └── docs/
│ ├── package.json
│ └── src/
├── backend/
│ └── fastapi/
│ ├── main.py
│ └── requirements.txt
├── services/
│ └── go/
│ ├── main.go
│ └── go.mod
└── vercel.json

我们希望:

1
2
3
4
/        -> Next.js 前端
/api/* -> FastAPI 后端
/go/* -> Go 服务
/docs/* -> Astro 文档站

那么 vercel.json 可以这样写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{
"services": {
"web": {
"root": "apps/web",
"framework": "nextjs"
},
"api": {
"root": "backend/fastapi",
"entrypoint": "main:app"
},
"go_service": {
"root": "services/go",
"entrypoint": "main.go"
},
"docs": {
"root": "apps/docs",
"framework": "astro"
}
},
"rewrites": [
{
"source": "/api/(.*)",
"destination": { "service": "api" }
},
{
"source": "/go/(.*)",
"destination": { "service": "go_service" }
},
{
"source": "/docs/(.*)",
"destination": { "service": "docs" }
},
{
"source": "/(.*)",
"destination": { "service": "web" }
}
]
}

这段配置的核心逻辑很清晰:

1
2
3
4
/api/*   交给 FastAPI
/go/* 交给 Go 服务
/docs/* 交给 Astro 文档站
其他路径 交给 Next.js 前端

注意,rewrites 的顺序很重要。更具体的路径应该放在前面,例如 /api/(.*)/go/(.*)/docs/(.*);兜底的 /(.*) 应该放在最后。

否则所有请求都可能先被前端服务接走。

配置字段说明

services

services 用于声明当前项目中的多个服务。

每个 key 都是一个服务名,例如:

1
2
3
4
5
6
7
{
"services": {
"web": {},
"api": {},
"docs": {}
}
}

这些服务名之后可以在 rewrites 或服务间调用配置中使用。

root

root 指定该服务所在的目录。

例如:

1
2
3
4
5
6
7
{
"services": {
"web": {
"root": "apps/web"
}
}
}

这表示 web 服务的代码位于 apps/web 目录下。

framework

framework 用于指定服务使用的框架。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
{
"services": {
"web": {
"root": "apps/web",
"framework": "nextjs"
},
"docs": {
"root": "apps/docs",
"framework": "astro"
}
}
}

如果不写,Vercel 会尝试自动识别框架。但对于复杂 Monorepo 项目,显式指定通常更稳定。

entrypoint

entrypoint 通常用于后端服务,指定应用启动入口。

FastAPI 常见写法类似:

1
2
3
4
5
6
7
8
{
"services": {
"api": {
"root": "backend/fastapi",
"entrypoint": "main:app"
}
}
}

其中 main:app 通常表示:

1
main.py 文件中的 app 对象

Go 服务可以根据项目结构指定入口,例如:

1
2
3
4
5
6
7
8
{
"services": {
"go_service": {
"root": "services/go",
"entrypoint": "main.go"
}
}
}

实际写法需要根据项目结构和 Vercel 支持的运行方式调整。

rewrites

rewrites 是 Services 模式里非常重要的一部分。

它决定公网请求会被路由到哪个 Service。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
{
"rewrites": [
{
"source": "/api/(.*)",
"destination": { "service": "api" }
},
{
"source": "/(.*)",
"destination": { "service": "web" }
}
]
}

这表示:

1
2
/api/*  -> api 服务
其他路径 -> web 服务

没有被 rewrites 暴露的服务,默认不会接收公网请求。

这和传统的“每个服务自动挂一个公开路径”不太一样。Vercel Services 更像是先声明服务,再通过统一的顶层路由表决定哪些服务对外开放。

服务之间如何通信?

除了通过公网路径访问,Services 之间也可以通过内部方式通信。

这适合一些不希望直接暴露给公网的服务。

例如,你可能有:

1
2
3
web       -> Next.js 前端
api -> 对外 API
worker -> 内部任务服务

worker 不需要公开 URL,只需要被 api 调用。这种情况下,就可以让它作为内部服务存在,而不是给它配置公网 rewrite。

这种设计的好处是:

  • 减少公网暴露面
  • 避免无意义的外部路由
  • 更适合拆分后台能力
  • 让项目结构更接近真实的微服务或模块化后端

当然,对于个人项目来说,不一定需要一开始就拆这么细。普通项目可以先从 web + api 两个服务开始。

它不是 Docker Compose

需要注意的是,Vercel Services 并不等于 Docker Compose。

Docker Compose 更像是在一台服务器或容器环境中编排多个长期运行的服务,例如:

1
2
3
4
5
web
api
postgres
redis
worker

它通常负责启动多个容器,并让这些容器在同一个网络环境中长期运行。

而 Vercel Services 更偏向于 Vercel 平台上的多服务构建与路由组织。它适合部署 Web 应用、API 服务、前端项目和轻量后端,但并不是让你在 Vercel 上直接运行一整套传统服务器环境。

如果你的项目依赖:

  • 长期运行的数据库
  • Redis
  • 队列
  • 后台常驻进程
  • 自定义守护进程
  • 复杂内网服务发现
  • 完整 Docker Compose 生态

那仍然需要使用外部托管服务,或者选择 VPS / Docker / Kubernetes 等更传统的部署方式。

不过,Vercel Services 确实让 Vercel 更接近“一个产品部署多个组成部分”的形态。对于不想自己维护服务器的人来说,这已经覆盖了很多常见场景。

适合哪些项目?

Vercel Services 很适合这些场景。

Monorepo 项目

例如:

1
2
3
4
5
6
apps/web
apps/admin
apps/docs
packages/ui
packages/db
backend/api

如果你已经在使用 pnpm workspace、Turborepo、Nx 或类似结构,Services 会很适合。

前后端分离项目

例如:

1
2
frontend/
backend/

前端用 Next.js,后端用 FastAPI、Go 或其他框架。

以前这类项目在 Vercel 上不够自然,现在可以通过 Services 放在一个 Project 内。

多个后台服务

有些项目可能不只是一个 API:

1
2
3
4
services/auth
services/payment
services/webhook
services/image

它们可以分别通过不同路径公开:

1
2
3
4
/auth
/payment
/webhook
/image

也可以只让部分服务公开,其他服务保持内部访问。

静态站点 + 后台接口

比如:

1
2
apps/site      -> Astro / Vite / Hexo 构建后的静态站
backend/api -> Python / Node.js API

对于个人项目、工具站、轻量 SaaS、文档站 + API 的组合,这个功能会很有吸引力。

总结

Vercel Services 的意义在于,它让 Vercel 从“一个项目部署一个框架”更进一步,变成 一个项目可以承载多个框架、多个服务

对于现代 Web 项目来说,这个变化非常实用。

过去我们经常需要在多个 Vercel Project、多个域名、多个 Preview URL 之间来回切换。现在,前端、后端、管理后台、文档站、工具页都可以作为一个项目里的多个服务统一部署。

它尤其适合:

  • Monorepo
  • 前后端分离项目
  • Python + JavaScript 混合项目
  • Go + Next.js 混合项目
  • 多框架应用
  • 个人工具站
  • 小型 SaaS
  • 静态站点 + API 的组合

如果你一直想把一个复杂项目整理成更清晰的部署结构,Vercel Services 值得关注。

它不是 Docker Compose 的替代品,也不是所有项目都必须使用的新能力。但对于已经开始变复杂的前端项目、个人工具站和轻量全栈应用来说,它确实让 Vercel 的部署模型更完整了。

参控

评论
分享

评论