OpenNext:自託管 Next.js 無需 Vercel(AWS、Cloudflare、VPS)
你的 Vercel 帳單在三月份到達 $847——你的 Next.js 行銷網站、40,000 次訪問、三個無伺服器函數。你打開發票明細,看著行項目堆積:頻寬超額、函數調用、圖片優化。同一網站在 AWS 上用 OpenNext 運行每月 $23。我在過去一年遷移了三個生產應用——一個年營收 $2M 的電子商務店面、一個有 8,000 活躍用戶的 SaaS 儀表板、一個代理機構組合。每次遷移耗時不到四小時。每一次都將託管成本降低了 91–97%。性能指標保持不變或改善。但 OpenNext 文檔不會告訴你的是:第一次部署會失敗,你的中間件會以微妙的方式中斷,你會花一個下午調試快取標頭。這是我在 2025 年 1 月、當我們第一張發票超過四位數時,希望我有的遷移手冊。
這不是一篇「Vercel 不好」的文章。Vercel 確實很出色。但它不再是唯一的選擇,對於許多團隊來說,它也不是正確的選擇。讓我帶你瞭解我學到的關於使用 OpenNext 自託管 Next.js 的一切——好的、醜陋的和令人驚喜的廉價。
目錄
- OpenNext 是什麼及為什麼存在
- 2026 年自託管景觀
- 部署目標:使用 SST 的 AWS
- 部署目標:Cloudflare Workers
- 部署目標:使用 Docker 的 VPS
- 成本比較:Vercel vs 自託管
- 何時離開 Vercel
- 遷移手冊
- 常見陷阱及如何避免它們
- 常見問題

OpenNext 是什麼及為什麼存在
Next.js 被設計為在 Vercel 上運行。這不是陰謀——這是架構。ISR(增量靜態再生)、中間件、圖片優化和伺服器操作等功能都有內置的 Vercel 特定實現。當你嘗試在隨機伺服器上執行 next start 時,你只能獲得 Next.js 能做的一個子集。
OpenNext 是一個開源適配器,它取你的 Next.js 構建輸出並將其轉換為可在其他平台上工作的部署包。它始於 SST 社區項目,專注於 AWS Lambda,但截至 v3(2026 年當前主要版本),它支持多個部署目標,包括 Cloudflare Workers、傳統 Node.js 伺服器等。
以下是 OpenNext 實際處理的內容:
- ISR 和重新驗證 — Vercel 使用其內部基礎設施實現的基於標籤的重新驗證系統?OpenNext 使用 AWS 上的 DynamoDB + SQS 或 Cloudflare 上的 KV 存儲重新創建它。
- 圖片優化 — Next.js 的
<Image>組件依賴於優化 API。OpenNext 打包基於 Sharp 的優化器或路由到平台特定的解決方案。 - 中間件 — 在 Vercel 上的邊緣運行。OpenNext 將其映射到 CloudFront 函數、Cloudflare Workers 或在 VPS 上運行進程。
- 伺服器操作 — 完全支持,通過適當的伺服器函數路由。
- 流和部分預渲染 — OpenNext v3.x 中的支持已大幅成熟。
OpenNext 不是什麼
它不是託管平台。它不是 CDN。它是一個構建適配器——Next.js 的輸出和你的基礎設施之間的翻譯層。你仍然需要在某個地方實際運行這個東西。
2026 年自託管景觀
生態系統自我第一次開始看這個以來已經爆炸。以下是目前的情況:
| 平台 | OpenNext 支持 | 成熟度 | 最適合 |
|---|---|---|---|
| AWS(通過 SST) | 一流 | 生產就緒 | 已經在 AWS 上的團隊 |
| Cloudflare Workers | 官方適配器 | 穩定(某些邊界情況) | 邊緣優先應用、成本優化 |
| Docker/VPS | 社區 + 官方 | 穩定 | 簡單部署、現有基礎設施 |
| Kubernetes | 社區 Helm 圖表 | 成熟中 | 企業、現有 K8s 集群 |
| Netlify | 內置(自己的適配器) | 生產就緒 | 承諾使用 Netlify 的團隊 |
| Google Cloud Run | 社區 | 實驗性 | GCP 商店 |
我親身測試並可以保證的兩條路徑是通過 SST 的 AWS 和 VPS 上的 Docker。Cloudflare 是令人興奮的新來者,每月都在變得更好。
部署目標:使用 SST 的 AWS
這是黃金路徑。SST(無伺服器堆棧)具有由 OpenNext 驅動的內置 Next.js 支持,這是大部分工程工作所在的地方。
架構概述
當你通過 SST 在 AWS 上部署 Next.js 時,以下是創建的內容:
- CloudFront 分發 — 你的 CDN,處理靜態資產和路由
- Lambda 函數 — 伺服器端渲染、API 路由、伺服器操作
- S3 bucket — 靜態資產、預渲染頁面、ISR 快取
- DynamoDB 表 — ISR 標籤映射用於重新驗證
- SQS 隊列 — 非同步重新驗證處理
- CloudFront 函數或 Lambda@Edge — 中間件執行
聽起來像是很多。確實是。但 SST 將所有內容抽象化為大約 20 行配置。
SST 配置
以下是來自我的一個生產項目的實際 sst.config.ts:
/// <reference path="./.sst/platform/config.d.ts" />
export default $config({
app(input) {
return {
name: "my-nextjs-app",
removal: input.stage === "production" ? "retain" : "remove",
home: "aws",
providers: {
aws: {
region: "us-east-1",
},
},
};
},
async run() {
const site = new sst.aws.Nextjs("Site", {
domain: {
name: "myapp.com",
dns: sst.aws.dns(),
},
warm: 5, // keep 5 Lambda instances warm
memory: "1024 MB",
environment: {
DATABASE_URL: process.env.DATABASE_URL!,
NEXT_PUBLIC_API_URL: "https://api.myapp.com",
},
});
return {
url: site.url,
};
},
});
然後部署:
npx sst deploy --stage production
首次部署耗時 8-12 分鐘(CloudFront 分發傳播)。後續部署為 2-4 分鐘。
Lambda 注意事項
Lambda 託管的最大陷阱是冷啟動。Next.js 伺服器函數並不小——根據你的依賴項,你看的是 20-80MB 的包。冷啟動範圍從 800ms 到 3 秒。
我使用的緩解措施:
- 配置的並發性 — SST 的
warm參數保持實例熱。在 $0.0000041667 每 GB 秒,保持 5 個 1GB 函數的實例熱運行成本約 $15/月。 - 較小的包 — 審計你的伺服器端依賴項。我發現一個項目在伺服器端導入
lodash,而我們只需要lodash/get。包從 68MB 縮小到 31MB。 - 區域部署 — 除非你絕對需要,否則不要為 SSR 使用 Lambda@Edge。單區域 Lambda 與 CloudFront 快取對 95% 的應用來說都很好。

部署目標:Cloudflare Workers
Cloudflare 一直在做認真的舉動。他們的 Workers 運行時現在支持足夠的 Node.js API,使得 Next.js 實際上可以在那裡運行,而且 OpenNext Cloudflare 適配器已經變得非常穩定。
使用 OpenNext Cloudflare 的設置
npm install @opennext/cloudflare
添加到你的 wrangler.toml:
name = "my-nextjs-app"
main = ".open-next/worker.js"
compatibility_date = "2025-01-01"
compatibility_flags = ["nodejs_compat_v2"]
[assets]
directory = ".open-next/assets"
binding = "ASSETS"
[[kv_namespaces]]
binding = "NEXT_CACHE_KV"
id = "your-kv-namespace-id"
構建並部署:
npx @opennext/cloudflare build
npx wrangler deploy
Cloudflare 權衡
優點:
- 沒有冷啟動 — Workers 在全球範圍內以不到 5ms 的速度啟動
- 全球邊緣預設 — 你的 SSR 在 300+ 個位置運行
- 荒謬定價 — 付費計劃上 1000 萬個請求 $5/月
缺點:
- 記憶體限制 — 免費 128MB,付費 256MB。大型 Next.js 應用可能會達到這個限制。
- CPU 時間限制 — 付費計劃 30 秒。繁重的 SSR 頁面可能是個問題。
- Node.js 兼容性差距 — 大多數東西都有效,但如果你直接使用本地 Node 模塊,如
sharp,你需要解決方法。Cloudflare 圖片可以改為處理優化。 - 某些 Next.js 功能不受支持 — 截至 2026 年初,部分預渲染支持在 Cloudflare 上仍然是實驗性的。
對於內容豐富的網站和行銷頁面,Cloudflare Workers 極具吸引力。對於具有繁重伺服器端邏輯的複雜網路應用,我仍然傾向於 AWS 或 Docker。
部署目標:使用 Docker 的 VPS
有時你只是想要一個伺服器。沒有 Lambda 函數,沒有邊緣運行時,沒有 47 個服務的架構圖。一個運行你代碼的盒子。我尊重這一點。
Dockerfile
以下是我使用的生產 Dockerfile。它是多階段的、優化的,並且實際上可以工作:
# Stage 1: Dependencies
FROM node:20-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable pnpm && pnpm install --frozen-lockfile
# Stage 2: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
RUN corepack enable pnpm && pnpm build
# Stage 3: Production
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]
關鍵:你需要在 next.config.js 中使用 output: 'standalone':
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
};
module.exports = nextConfig;
VPS 建議
我在幾個提供者上運行過這個設置:
| 提供者 | 規格 | 月成本 | 備註 |
|---|---|---|---|
| Hetzner CAX21 | 4 vCPU ARM、8GB RAM | €7.49(約 $8) | 最佳價值,EU 數據中心 |
| DigitalOcean Droplet | 2 vCPU、4GB RAM | $24 | 良好的美國覆蓋 |
| Fly.io(機器) | 2 vCPU、4GB RAM | 約 $30 | 自動擴展、全球區域 |
| Railway | 基於使用情況 | $5-50 | 最簡單的設置、Vercel 般的 DX |
| AWS EC2 t4g.medium | 2 vCPU、4GB RAM | 約 $25 | 已經在 AWS 上 |
對於直接的 Docker 部署,Hetzner 的價值好得離譜。我在 €7.49 的 Hetzner ARM 實例上運行一個 Next.js 應用,每月服務超過 200 萬次頁面瀏覽,位於 Cloudflare 免費 CDN 層後面。伺服器幾乎不費力。
使用 Docker/VPS 失去的東西
讓我們誠實地說說相比 Vercel 或 SST 設置,VPS 上的 next start 不能給你的東西:
- ISR 重新驗證很基本 — 僅文件系統快取。多個實例之間沒有分散式快取。如果你運行一個伺服器,這很好。多伺服器?你需要 Redis 或共享快取層。
- 沒有邊緣中間件 — 中間件在進程中運行,對於大多數用例來說完全沒問題。
- 圖片優化 — 通過 Sharp 工作,但你從單個源服務優化的圖片。在前面放置 Cloudflare 或 CDN。
- 沒有原子部署 — 你需要自己處理零停機部署(使用健康檢查的 Docker Compose,或反向代理如 Caddy/Traefik)。
對於 Social Animal 的大多數應用,特別是我們通過 headless CMS 開發 工作完成的無頭 CMS 構建,帶有 CDN 前面的單個 VPS 完全足夠。
成本比較:Vercel vs 自託管
讓我們談論金錢。這是基於一個 Next.js 應用的實際計費數據,進行約 500 萬次請求/月,帶有 ISR、圖片優化和中等伺服器端渲染。
| 成本因素 | Vercel Pro | Vercel Enterprise | AWS/SST | Cloudflare | Hetzner VPS |
|---|---|---|---|---|---|
| 基本平台 | $20/用戶/月 | 自定義(~$3k+/月) | $0 | $5/月 | €7.49/月 |
| 計算/請求 | $150-400/月 | 包括 | $40-80/月 | $0-15/月 | 包括 |
| 頻寬(100GB) | 包括 | 包括 | $8.50(CloudFront) | 包括 | 包括 |
| 圖片優化 | $50-200/月 | 包括 | $5-15/月(Lambda) | $5/月(CF 圖片) | 包括(Sharp) |
| ISR/快取 | 包括 | 包括 | $2-5/月(DynamoDB) | $0-5/月(KV) | $0 |
| 估計總計 | $300-700/月 | $3,000+/月 | $55-110/月 | $10-25/月 | $8-15/月 |
那些 Vercel 數字不是假設的。我看過發票。Pro 層的每個用戶定價、函數執行超額和頻寬費用對 5 人以上的團隊增加得很快。
AWS/SST 數字假設中等流量與配置的並發性。Cloudflare 的定價真的很荒謬——除非你在做一些奇特的事情,否則很難在那裡花費真正的錢。
何時離開 Vercel
不只是因為你可以就離開。因為你應該而離開。以下是我的框架:
留在 Vercel 上如果:
- 你的團隊很小(1-3 名開發者)且開發者時間是你最昂貴的資源
- 你在 Vercel 上的支出少於 $100/月
- 你沒有人喜歡基礎設施工作
- 你反覆迅速,需要立即預覽每個 PR
- 你使用 Vercel 特定功能,如分析、速度洞察或 Vercel AI SDK 集成
離開 Vercel 如果:
- 月度帳單超過 $500 並在增長
- 你需要特定區域的基礎設施用於合規性(GDPR、數據駐留)
- 你已經運行重要的 AWS/GCP/Cloudflare 基礎設施
- 無伺服器上的冷啟動對你的用例不可接受
- 你需要不適合 Vercel 模型的自定義快取策略
- 你已經達到 Vercel 的函數大小限制或執行時間限制
認真考慮離開如果:
- 你在 Vercel Enterprise 定價上,合同續期剛剛到達
- 你的應用大多是靜態/ISR,你正在為動態 SSR 定價付費
- 你想在相同基礎設施中運行你的前端與你的後端
遷移手冊
我已經做過三次了。以下是我遵循的流程,通過痛苦的經驗優化。
步驟 1:審計你的 Next.js 功能
在你觸及任何東西之前,記錄你實際使用的 Next.js 功能:
# 查找中間件
find . -name "middleware.ts" -o -name "middleware.js"
# 查找 API 路由
find ./app -name "route.ts" -o -name "route.js" | head -20
# 檢查 ISR
grep -r "revalidate" ./app --include="*.ts" --include="*.tsx" | head -20
# 檢查伺服器操作
grep -r "use server" ./app --include="*.ts" --include="*.tsx" | head -20
# 檢查 next.config 用於特殊功能
cat next.config.js
步驟 2:選擇你的目標
基於審計:
- 重型 ISR + 中間件 + 圖片優化 → AWS/SST
- 簡單 SSR + 內容網站 → Cloudflare 或 VPS
- 已經有 Docker/K8s 基礎設施 → VPS/Docker
- 需要在週五前完成 → Docker on Railway 或 Fly.io
如果你用 Next.js 或 Astro 構建,目標平台的選擇顯著影響你的架構決策。
步驟 3:設置 CI/CD
Vercel 的 CI/CD 真的很出色。你會想念它。用 GitHub Actions 複製它:
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm build
- run: pnpm test
# 用於 SST:
- run: npx sst deploy --stage production
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# 用於 Docker/VPS(替代):
# - run: docker build -t myapp .
# - run: docker push registry.example.com/myapp:latest
# - run: ssh deploy@server 'cd /app && docker compose pull && docker compose up -d'
步驟 4:預覽部署
這是人們最想念 Vercel 的一個東西。對於 SST,使用階段:
# 在你的 PR CI 工作流中
npx sst deploy --stage pr-${{ github.event.pull_request.number }}
對於 Docker,Coolify 等工具(自託管)或 Railway 很好地處理預覽部署。
步驟 5:DNS 轉換
實際遷移時刻。我總是建議:
- 在現有 Vercel 旁邊部署到新基礎設施
- 用臨時域徹底測試
- 在前一天將 DNS TTL 降低到 60 秒
- 在低流量時段進行 DNS 轉換
- 將 Vercel 部署運行 48 小時作為後備
- 密切監控錯誤率、TTFB 和核心網路活力指標
步驟 6:撤除 Vercel
一旦你確定(給它至少一週),取消 Vercel 訂閱並移除項目。不要留下殭屍項目累積費用。
常見陷阱及如何避免它們
環境變數消失。 Next.js 有 NEXT_PUBLIC_ 前綴變數(在構建時打包)和僅伺服器變數(在運行時可用)。在 Vercel 上,這個區分有點模糊。在自託管上,它是嚴格的。確保所有 NEXT_PUBLIC_ 變數在你的 CI 中的構建時間可用。
ISR 快取不持久化。 在 Docker 上,.next/cache 目錄需要在持久卷上。否則,每個容器重啟都會丟失你的快取頁面:
# docker-compose.yml
services:
web:
build: .
ports:
- "3000:3000"
volumes:
- next-cache:/app/.next/cache
volumes:
next-cache:
Sharp 安裝失敗。 sharp 圖片優化庫需要平台特定的二進位檔案。在 Docker 中,確保你在與你的運行時相同的架構內安裝依賴項。上面的 Dockerfile 通過使用相同的基礎映像進行多階段構建來處理這一點。
中間件行為差異。 Vercel 在其邊緣網絡上運行中間件。在 AWS/SST 上,它作為 CloudFront 函數運行(限制在 10ms 執行、2MB 大小)。複雜的中間件可能需要移動到伺服器函數。我不得不重構認證中間件,因為這些限制。
缺少標頭和重寫。 如果你依賴 vercel.json 用於標頭、重定向或重寫,你需要將這些移動到 next.config.js 或你的 CDN/反向代理配置。
如果任何這些感到不堪重負,這正是 Social Animal 處理的那種基礎設施工作。檢查我們的 定價 或 聯繫我們 — 我們已經做過足夠的遷移次數,有一個精細的流程。
常見問題
OpenNext 在 2026 年生產就緒嗎? 可以。OpenNext v3.x 為數千家公司運行生產工作負載。SST/AWS 路徑是最經過戰鬥測試的,Cloudflare 支持緊跟其後。我不會稱 Google Cloud 或裸 Kubernetes 支持為成熟,但 AWS 和 Cloudflare 是穩定的。
OpenNext 是否支持 Next.js App Router 和伺服器組件? 完全支持。App Router、伺服器組件、伺服器操作、流和 Suspense 都有效。OpenNext 團隊密切跟蹤 Next.js 版本,儘管通常在主要 Next.js 版本發佈後有 1-3 週的滯後期才能被 OpenNext 趕上。
通過離開 Vercel 我實際上能節省多少? 這在很大程度上取決於你的使用模式。對於一個運行中等流量應用的 5 人開發者團隊,我看到團隊從 Vercel Pro 上的 $600-800/月降至 AWS/SST 上的 $30-80/月或 VPS 上的 $20 以下/月。節省是實際的,但維護負擔也是。
我可以在沒有 Vercel 的情況下使用 ISR(增量靜態再生)嗎?
完全可以。在 AWS/SST 上,ISR 使用 DynamoDB 進行標籤快取和 SQS 進行非同步重新驗證——它完全功能,包括通過 revalidateTag() 和 revalidatePath() 進行按需重新驗證。在 VPS 上,ISR 使用文件系統快取工作,對單伺服器部署很好。
Vercel 的預覽部署呢?我可以複製那些嗎? 你可以獲得 80% 的體驗。SST 支持基於階段的部署,所以每個 PR 可以獲得自己的堆棧。Coolify 和類似工具為基於 Docker 的設置提供預覽部署。你不會輕易複製的是 Vercel 的視覺評論系統和部署狀態的緊密 GitHub 集成。大多數團隊發現權衡可以接受。
對於無頭 CMS 網站,我應該使用 OpenNext 與 Cloudflare 還是 AWS? 對於內容豐富的無頭 CMS 網站(Sanity、Contentful、Storyblok),Cloudflare Workers 是一個極好的選擇。這些網站傾向於重型 ISR、相對較輕的伺服器端邏輯——完美適合 Cloudflare 的定價模型。我只會在 Cloudflare 尚不支持你需要的功能時或你已經深入 AWS 生態系統時選擇 AWS。
自託管 Next.js 比自託管 Astro 或 Remix 更難嗎? 說實話?是的。Next.js 在任何框架中都有最複雜的構建輸出,因為 ISR、中間件、圖片優化和部分預渲染等功能。Astro 和 Remix 有簡單得多的部署故事。如果你正在啟動一個新項目且自託管是優先事項,考慮 Astro — 它在託管上簡單得多。但如果你已經在 Next.js 上,OpenNext 使遷移實踐。
如果 OpenNext 停止被維護會發生什麼?
OpenNext 由 SST 支持,有一個活躍的社區和主要贊助者。話雖如此,這是任何開源依賴的合法關注。緩解是 Docker/獨立方式(next start)不使用 OpenNext 也能工作——你只是失去一些更高級的功能,如 ISR 標籤重新驗證和邊緣中間件。這是一個優雅的降級,而不是絕壁。