Ian Chou's Blog

Vercel vs Cloudflare vs Netlify:多語言 Serverless API 部署完全指南

前言

在現代的 Serverless 架構中,Vercel、Cloudflare 和 Netlify 是三個主流的部署平台。雖然它們都支援多語言開發,但底層的處理機制卻截然不同。本文將詳細比較這三個平台如何處理 TypeScript、Python 和 Go 等不同語言的 API,幫助你選擇最適合的部署方案。

Vercel:基於 AWS Lambda 的多 Runtime 架構

目錄結構慣例

Vercel 對專案目錄有特定的慣例 (Conventions),主要關注以下幾個目錄:

1. api/ 目錄(最重要)

2. public/ 目錄

3. src/ 或根目錄

4. 其他目錄(utils/, lib/, components/

Build 流程:獨立打包機制

當你將程式碼推送到 Vercel 時,其 Build System 會執行以下步驟:

1. 掃描與分類

Vercel 會掃描 api/ 目錄下的每個檔案,並根據副檔名決定使用哪個 Runtime Builder:

2. 獨立打包(Individual Bundling)

每個 API 檔案都會被視為獨立的 Serverless 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 優勢

  1. 更快的執行速度:CPU 密集型任務比 Node.js 快
  2. 完整 Node.js API 相容:現有 Node.js 程式碼可直接運行
  3. 🚀 內建工具:Bundler、Test Runner、Package Manager 一應俱全
  4. 📦 自動依賴安裝: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 檔案打包成完全獨立的微服務

Cloudflare:基於 V8 的 Workerd 架構

核心差異:Single Runtime

Cloudflare Workers 和 Pages Functions 底層都運行在 workerd(Cloudflare 自研的 V8 Runtime)上:

TypeScript/JavaScript:一等公民

在 Cloudflare 上,JavaScript/TypeScript 是原生支援的:

// functions/api/typescript.ts
export const onRequestGet: PagesFunction = async (context) => {
  return Response.json({ message: "Hello from Cloudflare!" });
};

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"}
        )

問題點

  1. 語法彆扭:需要透過 js 模組與 JavaScript API 互動
  2. 效能問題:Pyodide Runtime 很重,冷啟動慢
  3. 開發體驗差:不像標準 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)
}

優點

缺點

Bun 在 Cloudflare 上的角色

重點:Cloudflare 上沒有 Bun Runtime!

Netlify:基於 AWS Lambda 的簡化架構

核心特性:與 Vercel 相似但更 Opinionated

Netlify Functions 同樣基於 AWS Lambda,但採用更簡化的配置方式:

目錄結構

netlify/
└── functions/
    ├── typescript.ts
    ├── python.py
    └── golang.go

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" },
  });
};

Python:Lambda 相容層

def handler(event, context):
    return {
        'statusCode': 200,
        'body': json.dumps({'message': 'Hello from Python'})
    }

限制

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)
}

Bun 支援:僅限構建階段

Netlify 支援 Bun,但僅用於依賴安裝

# netlify.toml
[build.environment]
  BUN_VERSION = "1.0.0"
  BUN_FLAGS = "--frozen-lockfile"

自動偵測:偵測到 bun.lockb 會自動執行 bun install

重要限制

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 的情境

  1. Next.js 專案:與 Next.js 深度整合,部署體驗最佳
  2. 混合語言需求:需要在同一專案中使用 Python(資料處理)+ TypeScript(API)+ Go(高效能運算)
  3. Python 為主:已有大量 Python 程式碼需要 Serverless 化,Vercel 的 Python 支援較穩定
  4. 零設定需求:希望直接丟檔案就能部署,不想管 Runtime 設定

選擇 Cloudflare 的情境

  1. 純 TypeScript/JavaScript:專案完全使用 JS 生態系
  2. 高併發低延遲:需要全球 Edge 部署,毫秒級響應
  3. 成本敏感:Cloudflare 免費額度更高(每日 100,000 請求)
  4. Workers 生態系:想使用 Cloudflare D1、R2、KV 等服務

選擇 Netlify 的情境

  1. Jamstack 專案:靜態網站 + Serverless Functions 的組合
  2. 11ty/Hugo/Jekyll:使用靜態網站生成器,需要額外的 API 功能
  3. TypeScript/Go 為主:這兩個語言在 Netlify 上體驗良好
  4. 簡化部署流程:喜歡 Netlify 的 Git-based 部署和直觀的 UI
  5. 避免 Vendor Lock-in:Netlify 採用較標準的 AWS Lambda 格式,未來遷移較容易

混合策略

策略 1:依功能分離

策略 2:依語言分離

策略 3:階段性遷移

  1. 初期:全部用 Netlify 快速上線(Jamstack 優勢)
  2. 成長期:將高流量 API 遷移到 Cloudflare Workers(效能優化)
  3. 成熟期:複雜邏輯用 Vercel(彈性最大)

結論

三個平台代表了 Serverless 的不同哲學:

快速決策指南

如果你是...

最後提醒

架構沒有絕對的好壞,只有適不適合你的場景。

這三個平台都提供慷慨的免費額度,強烈建議:

  1. 實際部署測試專案(例如:TypeScript + Python + Go 三種 API)
  2. 比較開發體驗(CLI 工具、本地開發、除錯流程)
  3. 測試效能數據(冷啟動時間、回應速度、併發處理)
  4. 評估成本(依照你的預估流量計算費用)

動手實驗永遠是最好的學習方式! 🚀


延伸閱讀