Vercel vs Cloudflare vs Netlify:多語言 Serverless API 部署完全指南
前言
在現代的 Serverless 架構中,Vercel、Cloudflare 和 Netlify 是三個主流的部署平台。雖然它們都支援多語言開發,但底層的處理機制卻截然不同。本文將詳細比較這三個平台如何處理 TypeScript、Python 和 Go 等不同語言的 API,幫助你選擇最適合的部署方案。
Vercel:基於 AWS Lambda 的多 Runtime 架構
目錄結構慣例
Vercel 對專案目錄有特定的慣例 (Conventions),主要關注以下幾個目錄:
1. api/ 目錄(最重要)
- 用途:專門放置 Serverless Functions(後端 API)
- 行為:目錄內的檔案 (
.js,.ts,.go,.py) 會被自動部署成獨立的 API - 路由:檔案路徑會自動對應到 URL,例如
api/user.ts→https://your-site.com/api/user
2. public/ 目錄
- 用途:存放靜態資源(圖片、
robots.txt、favicon.ico等) - 行為:檔案會被部署到 CDN 上,可直接透過 URL 存取
- 範例:
public/logo.png→https://your-site.com/logo.png
3. src/ 或根目錄
- 用途:存放前端框架程式碼(Next.js、React、Vue、Svelte 等)
- 行為:Vercel 會根據
package.json自動偵測框架並執行相應的 Build 指令 - 範例:Next.js 會執行
next build並處理src/pages或src/app中的路由
4. 其他目錄(utils/, lib/, components/)
- 行為:Vercel 不會直接將這些目錄轉換為路由或 API
- 用途:供
api/或前端程式碼import使用的共用模組 - 重點:未被引用的程式碼不會被打包
Build 流程:獨立打包機制
當你將程式碼推送到 Vercel 時,其 Build System 會執行以下步驟:
1. 掃描與分類
Vercel 會掃描 api/ 目錄下的每個檔案,並根據副檔名決定使用哪個 Runtime Builder:
.js/.ts→@vercel/nodeBuilder(或 Edge Runtime).py→@vercel/pythonBuilder.go→@vercel/goBuilder
2. 獨立打包(Individual Bundling)
每個 API 檔案都會被視為獨立的 Serverless Function,分別打包:
api/user.ts→ 獨立的 Node.js Lambda Functionapi/data.py→ 獨立的 Python Lambda Functionapi/process.go→ 獨立的 Go Lambda Function
3. Runtime 處理細節
Node.js/TypeScript:
# Vercel 自動執行
npm install # 或 bun install(如果偵測到 bun.lockb)
npm run build
Python:
# Vercel 自動執行(如果有 requirements.txt)
pip install -r requirements.txt
# 將 .py 檔案與依賴一起打包
Go:
# Vercel 自動執行
go get # 下載依賴
go build -o handler api/yourfile.go # 編譯成二進位檔
Bun Runtime:真正的執行環境
Vercel 是唯一提供 Bun 作為真實 Runtime 的平台(Beta):
設定方式
在 vercel.json 中啟用:
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"bunVersion": "1.x"
}
設定後,所有 Vercel Functions 和 Middleware 都會在 Bun runtime 上執行!
Bun Runtime 優勢
- ⚡ 更快的執行速度:CPU 密集型任務比 Node.js 快
- ✅ 完整 Node.js API 相容:現有 Node.js 程式碼可直接運行
- 🚀 內建工具:Bundler、Test Runner、Package Manager 一應俱全
- 📦 自動依賴安裝:Vercel 偵測到
bun.lockb會自動用bun install
三種 Runtime 選擇
Vercel 提供三種 runtime,可依需求選擇:
| Runtime | 速度 | API 支援 | Bundle 大小 | 適用場景 |
|---|---|---|---|---|
| Node.js | 🐢 一般 | ✅ 完整 Node.js | 最大 250MB | 複雜運算、完整生態系 |
| Bun | 🚀 快 | ✅ Node.js 相容 | 大 | CPU 密集型任務 |
| Edge | ⚡ 最快 | ⚠️ Web Standard 只 | 小 (1-4MB) | 低延遲全球分散 |
預設:Node.js Runtime
切換 Edge Runtime:
export const runtime = 'edge'; // 在函數中明確指定
為什麼可以混用語言?
因為 Vercel 將每個 API 檔案打包成完全獨立的微服務:
- 每個 Function 都有自己的執行環境(Node.js / Python / Go)
- Infrastructure 層面完全隔離
- 透過 Vercel Edge Network 統一路由
Cloudflare:基於 V8 的 Workerd 架構
核心差異:Single Runtime
Cloudflare Workers 和 Pages Functions 底層都運行在 workerd(Cloudflare 自研的 V8 Runtime)上:
- 不是 Node.js(沒有 libuv)
- 不是 Bun(沒有 JavaScriptCore)
- 只有 workerd(基於 V8 Isolate)
TypeScript/JavaScript:一等公民
在 Cloudflare 上,JavaScript/TypeScript 是原生支援的:
// functions/api/typescript.ts
export const onRequestGet: PagesFunction = async (context) => {
return Response.json({ message: "Hello from Cloudflare!" });
};
- 執行環境:直接在 V8 Isolate 中執行
- 冷啟動:毫秒級(因為是原生環境)
- 生態系:完全成熟,工具鏈(Wrangler)與框架(Hono、Itty-router)豐富
Python:Beta 階段的挑戰
Cloudflare Python Workers 使用 Pyodide(編譯成 WebAssembly 的 Python 解譯器):
import js
from datetime import datetime
async def on_fetch(request, env):
if request.method == "GET":
return js.Response.new(
json.dumps({"message": "Hello"}),
headers={"Content-Type": "application/json"}
)
問題點:
- 語法彆扭:需要透過
js模組與 JavaScript API 互動 - 效能問題:Pyodide Runtime 很重,冷啟動慢
- 開發體驗差:不像標準 Python Web Framework(Flask/FastAPI)
Go:需要 TinyGo + Adapter
Cloudflare Go Workers 使用 TinyGo 編譯成 WebAssembly:
import (
"github.com/syumai/workers"
"net/http"
)
func main() {
http.HandleFunc("/", handler)
workers.Serve(nil)
}
優點:
- 有
syumai/workersAdapter,將底層 JS 互操作封裝成標準net/http介面 - 寫起來像正常的 Go Web Server
缺點:
- 需要安裝 TinyGo
- Build 流程較複雜(Go → Wasm)
Bun 在 Cloudflare 上的角色
重點:Cloudflare 上沒有 Bun Runtime!
- Local 開發:可以用 Bun(
bun install、bun run dev很快) - 部署後:程式碼在
workerd中執行,不是 Bun - 相容性:只要使用 Web Standard API(
fetch、Request、Response),就沒問題 - 避免:不要使用 Bun 特有 API(
Bun.file()、Bun.serve()等)
Netlify:基於 AWS Lambda 的簡化架構
核心特性:與 Vercel 相似但更 Opinionated
Netlify Functions 同樣基於 AWS Lambda,但採用更簡化的配置方式:
目錄結構
netlify/
└── functions/
├── typescript.ts
├── python.py
└── golang.go
- Functions 目錄:固定為
netlify/functions/(可在netlify.toml設定) - 路由規則:
netlify/functions/hello.ts→/.netlify/functions/hello - 設定檔:使用
netlify.toml而非vercel.json
TypeScript/JavaScript:原生支援
import type { Context } from "@netlify/functions";
export default async (req: Request, context: Context) => {
return new Response(JSON.stringify({ message: "Hello!" }), {
headers: { "Content-Type": "application/json" },
});
};
- Runtime:Deno(Edge Functions)或 Node.js
- 開發體驗:
netlify dev提供本地開發環境 - 優勢:Modern
Request/ResponseAPI,與 Web Standards 接軌
Python:Lambda 相容層
def handler(event, context):
return {
'statusCode': 200,
'body': json.dumps({'message': 'Hello from Python'})
}
限制:
- 使用 AWS Lambda 的
handler(event, context)格式 - 本地開發可能無法完整模擬雲端環境
- 部分 Python 套件可能不相容
- 建議:需要部署到 Netlify 才能完整測試
Go:AWS Lambda Go SDK
import (
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(request events.APIGatewayProxyRequest) (*events.APIGatewayProxyResponse, error) {
return &events.APIGatewayProxyResponse{
StatusCode: 200,
Body: `{"message": "Hello from Go"}`,
}, nil
}
func main() {
lambda.Start(handler)
}
- 優勢:與標準 Go Lambda 開發一致
- Build:Netlify 自動編譯 Go 程式碼
- 效能:原生編譯,執行速度快
Bun 支援:僅限構建階段
Netlify 支援 Bun,但僅用於依賴安裝:
# netlify.toml
[build.environment]
BUN_VERSION = "1.0.0"
BUN_FLAGS = "--frozen-lockfile"
自動偵測:偵測到 bun.lockb 會自動執行 bun install
重要限制:
- ✅ 構建時:用 Bun 安裝依賴(快速)
- ❌ 執行時:Functions runtime 是 Deno(Edge)或 Node.js,不是 Bun
Netlify vs Vercel:關鍵差異
雖然都基於 AWS Lambda,但有以下不同:
| 特性 | Vercel | Netlify |
|---|---|---|
| Functions 路徑 | /api/{name} |
/.netlify/functions/{name} |
| 設定檔 | vercel.json |
netlify.toml |
| Python 體驗 | ⭐⭐⭐⭐(較佳) | ⭐⭐⭐(可用但受限) |
| TypeScript Runtime | Bun/Node.js/Edge | Deno/Node.js |
| Bun Runtime | ✅ 真實執行環境 | ❌ 僅構建時使用 |
| 生態系焦點 | Next.js 深度整合 | Jamstack 全方位支援 |
三平台對比總結
| 特性 | Vercel | Cloudflare | Netlify |
|---|---|---|---|
| 底層架構 | AWS Lambda(多 Runtime) | workerd(V8 Isolate) | AWS Lambda(Lambda 相容) |
| TypeScript/JS | ⭐⭐⭐⭐⭐(完全原生) | ⭐⭐⭐⭐⭐(完全原生) | ⭐⭐⭐⭐⭐(完全原生) |
| Python | ⭐⭐⭐⭐(穩定,但冷啟動慢) | ⭐⭐(Beta,語法彆扭) | ⭐⭐⭐(Lambda 層,受限) |
| Go | ⭐⭐⭐⭐(原生編譯,快速) | ⭐⭐⭐(需 TinyGo,但可用) | ⭐⭐⭐⭐(Lambda SDK,穩定) |
| Bun Runtime | ✅ 真實執行環境 | ❌ 無(僅本地開發) | ❌ 僅構建時使用 |
| 混用語言 | ✅ 極其容易(檔案級隔離) | ⚠️ 需要分開部署 | ✅ 容易(Lambda 層隔離) |
| 冷啟動 | 較慢(尤其 Python) | 極快(JS/TS),慢(Python) | 較慢(Lambda 特性) |
| 開發指令 | vercel dev |
wrangler dev |
netlify dev |
| 最佳用例 | Next.js + 混合語言 | 高併發 Edge JS/TS | Jamstack + Serverless |
實戰建議
選擇 Vercel 的情境
- Next.js 專案:與 Next.js 深度整合,部署體驗最佳
- 混合語言需求:需要在同一專案中使用 Python(資料處理)+ TypeScript(API)+ Go(高效能運算)
- Python 為主:已有大量 Python 程式碼需要 Serverless 化,Vercel 的 Python 支援較穩定
- 零設定需求:希望直接丟檔案就能部署,不想管 Runtime 設定
選擇 Cloudflare 的情境
- 純 TypeScript/JavaScript:專案完全使用 JS 生態系
- 高併發低延遲:需要全球 Edge 部署,毫秒級響應
- 成本敏感:Cloudflare 免費額度更高(每日 100,000 請求)
- Workers 生態系:想使用 Cloudflare D1、R2、KV 等服務
選擇 Netlify 的情境
- Jamstack 專案:靜態網站 + Serverless Functions 的組合
- 11ty/Hugo/Jekyll:使用靜態網站生成器,需要額外的 API 功能
- TypeScript/Go 為主:這兩個語言在 Netlify 上體驗良好
- 簡化部署流程:喜歡 Netlify 的 Git-based 部署和直觀的 UI
- 避免 Vendor Lock-in:Netlify 採用較標準的 AWS Lambda 格式,未來遷移較容易
混合策略
策略 1:依功能分離
- 前端 + 輕量 API:部署在 Cloudflare Pages(TypeScript)
- 重運算/特殊語言需求:單獨用 Vercel Functions(Python/Go)
- 資料庫:使用 Cloudflare D1 或 Vercel Postgres
策略 2:依語言分離
- TypeScript API:Netlify Functions(開發體驗佳)
- Python 資料處理:Vercel Functions(支援較穩定)
- Go 高效能服務:Vercel 或 Netlify(兩者都穩定)
策略 3:階段性遷移
- 初期:全部用 Netlify 快速上線(Jamstack 優勢)
- 成長期:將高流量 API 遷移到 Cloudflare Workers(效能優化)
- 成熟期:複雜邏輯用 Vercel(彈性最大)
結論
三個平台代表了 Serverless 的不同哲學:
- Vercel:「給我任何語言的程式碼,我都幫你跑起來」(Multi-Runtime 隔離架構,Next.js 最佳拍檔,唯一真實 Bun Runtime)
- Cloudflare:「用 JavaScript 寫一切,跑得飛快」(Single Runtime 極致優化,全球 Edge 部署)
- Netlify:「Jamstack + Serverless 的完美結合」(AWS Lambda 標準化,Git-based 部署流程)
快速決策指南
如果你是...
- 🚀 Next.js 開發者 → Vercel(無腦選擇)
- ⚡ 追求極致效能 → Cloudflare Workers(毫秒級冷啟動)
- 🏗️ Jamstack 愛好者 → Netlify(靜態網站 + Functions)
- 🐍 Python 重度使用者 → Vercel(支援最穩定)
- 🎯 想用 Bun Runtime → Vercel(唯一真實支援)
- 💰 預算有限 → Cloudflare(免費額度最高)
- 🔧 彈性為上 → Netlify(標準 Lambda 格式,好遷移)
最後提醒
架構沒有絕對的好壞,只有適不適合你的場景。
這三個平台都提供慷慨的免費額度,強烈建議:
- 實際部署測試專案(例如:TypeScript + Python + Go 三種 API)
- 比較開發體驗(CLI 工具、本地開發、除錯流程)
- 測試效能數據(冷啟動時間、回應速度、併發處理)
- 評估成本(依照你的預估流量計算費用)
動手實驗永遠是最好的學習方式! 🚀
延伸閱讀:
- ← Previous
FDE 小型 IDP 指南(無 K8s 篇):用自架 PaaS 打造 Vercel 級部署體驗 - Next →
需求訪談 Workflow:從 Cloud Code 到 Antigravity 的 AskUserQuestionTool 移植