Next.js 專案離開 Zeabur 要去哪:Vercel、Cloudflare Workers、Docker 自架三條路比較

Next.js 專案離開 Zeabur,常見的去處有三條:交給 Vercel、用 OpenNext 轉接到 Cloudflare Workers、或用 Docker 自己架。Next.js 官方文件寫明,以 Node.js 伺服器或 Docker 部署可支援所有功能;Vercel 與 Cloudflare 則各有執行時間、大小或快取設定上的限制。選之前先盤點專案用了哪些功能(Server Actions、ISR、Middleware、圖片最佳化),再處理環境變數的兩個坑:Zeabur 專屬變數搬走會失效,NEXT_PUBLIC_ 開頭的變數在建置時就寫死,改了值要重新建置。文中也附上我們照官方 with-docker 範例實際建置一次的時間、映像大小與記憶體用量。

這篇是〈Zeabur 搬家前先換金鑰〉的 Next.js 專篇。停止營運的時程、換金鑰的順序、退款與網域的共通部分,請看那篇;這裡只講 Next.js 要搬去哪、搬的時候會卡在哪。

文中官方資料的查詢日期是 2026 年 10 月 18–19 日,來源包括 Next.js、Vercel、Cloudflare、OpenNext 的官方文件;Docker 自架一節的實測在 10 月 19 日進行。各平台的價格與方案內容會變動,本文不列價格,以官方價格頁為準。

先看你的 Next.js 用了什麼

三條路能跑的功能不完全一樣。搬之前,先在專案裡確認這幾件事:

  • App Router 還是 Pages Router:有 app/ 資料夾是 App Router,有 pages/ 是 Pages Router,兩者可以並存。
  • API:pages/api/ 底下的檔案,或 app/ 裡的 route.ts(Route Handlers)。
  • Server Actions:程式碼裡有 'use server'。
  • ISR/revalidate:頁面有 revalidate 設定,或呼叫 revalidatePath、revalidateTag。
  • Middleware/Proxy:根目錄有 middleware.ts 或 proxy.ts。Next.js 16 起 Middleware 改名為 Proxy,而且預設跑在 Node.js runtime。
  • 圖片最佳化:有用 next/image 的 <Image> 元件。
  • 純靜態:next.config 裡設了 output: 'export'。
  • Next.js 版本:看 package.json。

再對照下表。表中只寫官方文件寫得到的內容,Cloudflare 那欄以 OpenNext Cloudflare adapter 的官方文件為準:

你的專案用了VercelCloudflare Workers(OpenNext)Docker 自架(standalone)
App Router/Pages Router支援兩種都支援支援
API routes/Route Handlers支援,跑在 Vercel Functions,有執行時間上限支援支援
Server Actions支援(Vercel 說明:透過 Vercel Functions)支援(Cloudflare 的 OpenNext 說明頁)支援;開多個容器要共用同一把加密金鑰
ISR/revalidate支援支援,但要另外設定快取(建議 R2)支援;單一容器存在本機磁碟,多個容器要共用快取
Middleware/Proxy支援支援;Node.js middleware(15.2 起)尚未支援支援
next/image 圖片最佳化支援,不用設定要設定 Cloudflare Images(另外計費)支援,需要 sharp 套件
output: ‘export’ 純靜態可以可以可以,也可以只用 Nginx 等靜態主機

Next.js 官方〈Deploying〉頁寫明:以 Node.js 伺服器部署「supports all Next.js features」,Docker 部署也「support all Next.js features」;靜態匯出則不支援需要伺服器的功能,包括 Server Actions、ISR、Proxy、預設的圖片最佳化、Cookies、Rewrites、Redirects、Headers。

如果你的專案是 output: 'export' 純靜態,三條路都很簡單:官方說靜態匯出可以放在任何能提供 HTML、CSS、JS 的伺服器上,例如 AWS S3、Nginx 或 Apache。下面的比較主要是給有用到伺服器功能的專案。

要人代搬可看我們的PaaS 停運搬家與資安檢查服務。

環境變數的兩個坑

坑一:Zeabur 專屬變數搬走就沒有值

依 Zeabur 官方文件〈環境變數〉,${ZEABUR_[連線埠名稱]_URL}、${ZEABUR_[連線埠名稱]_DOMAIN}、${CONTAINER_HOSTNAME}、${ZEABUR_SERVICE_ID} 這類變數是 Zeabur 幫你填的,搬到別的平台就沒有值了。常見的寫法是 NEXT_PUBLIC_API_URL=${ZEABUR_WEB_URL},或後端的資料庫連線字串引用 Zeabur 注入的變數,這些都要改成新環境的實際網址與主機名稱。

坑二:NEXT_PUBLIC_ 是建置時寫死的

Next.js 官方文件〈Environment Variables〉的原句是:

After being built, your app will no longer respond to changes to these environment variables.

意思是,NEXT_PUBLIC_ 開頭的變數在 next build 時就被換成固定值,寫進送到瀏覽器的 JavaScript 裡。官方也舉例:同一個 Docker 映像部署到多個環境時,所有 NEXT_PUBLIC_ 變數都會固定在建置當時的值。

所以搬家後改了 NEXT_PUBLIC_ 的值,要重新建置,重新啟動沒有用。三條路各有對應的寫法:

  • Vercel:官方文件寫明,環境變數的修改不會套用到之前的部署,只會套用到新的部署。改完要重新部署一次。
  • Cloudflare Workers:OpenNext 文件寫明,用 Workers Builds 部署時,變數要設在「Build variables and secrets」,建置才拿得到 NEXT_PUBLIC_ 的值。
  • Docker:官方 with-docker 範例建議用 --build-arg 在建置階段傳入 NEXT_PUBLIC_ 的值;同一份 README 也提醒,不要把金鑰當成 build argument 傳,因為能從映像歷史還原。

另外,NEXT_PUBLIC_ 的值本來就會送到瀏覽器,不該放金鑰。如果之前有人把金鑰放在 NEXT_PUBLIC_ 變數裡,視同已公開,一起換掉。

順手:Next.js 用的金鑰也要換

Zeabur 狀態頁寫明,10 月的事件可能外洩服務的環境變數。Next.js 專案常放在環境變數裡的,除了資料庫密碼與第三方 API key,還有登入用的 AUTH_SECRET(NextAuth/Auth.js),以及有設定的話 NEXT_SERVER_ACTIONS_ENCRYPTION_KEY。搬到新平台時直接產生新的,不要沿用。每類金鑰去哪裡換,見〈Zeabur 金鑰外洩後要換哪些?〉。

路線一:Vercel

它是誰:Vercel 官方文件寫明,Next.js 由 Vercel 維護,部署到 Vercel 不需要另外設定(zero-configuration)。Vercel 自己的比較文寫「the framework runs with full feature support」。Next.js 官方〈Deploying〉頁也把 Vercel 列為 verified adapter,也就是開源、跑 Next.js 完整相容性測試的轉接器。

要注意的限制(引自 Vercel 官方〈Functions Limitations〉,2026-08-24 更新):

  • 執行時間有上限:官方原句是「If a Vercel Function doesn’t complete within the duration, a 504 error code (FUNCTION_INVOCATION_TIMEOUT) is returned.」開啟 fluid compute 時,Node.js 函式的預設與上限,Hobby 方案都是 300 秒;Pro 方案預設 300 秒,上限可以設到 800 秒。要跑很久的工作(大量匯入、長時間的 AI 呼叫)要拆開,或放到別的地方。
  • 請求與回應大小:每次請求或回應的內容上限是 4.5 MB,超過會回 413。要讓使用者上傳大檔案,不能直接傳進函式。
  • 函式大小:解壓縮後上限 250 MB。
  • 免費方案只限個人非商業使用:官方〈Hobby Plan〉頁寫明「the Hobby plan restricts users to non-commercial, personal use only」。公司的產品要看付費方案,以官方價格頁為準。

資料庫要另外找:Vercel 的儲存服務有 Blob(存檔案)與 Global Config(設定值);關聯式資料庫、Key-Value 等,要透過 Vercel Marketplace 開別家的服務(官方範例是 vercel install neon)。如果你的資料庫原本也在 Zeabur 上,要先決定資料庫搬去哪,再決定 Next.js 放哪。

怎麼搬:已經有 Next.js 專案的,官方說安裝 Vercel CLI,在專案根目錄執行 vercel 指令;或在 Vercel 後台接上 Git 儲存庫。環境變數在 Vercel 後台重新設一次,記得用換過的新金鑰。

路線二:Cloudflare Workers(OpenNext)

它是什麼:@opennextjs/cloudflare 是 OpenNext 社群維護的轉接器。OpenNext 官方文件寫明,它會先執行你的 next build,再把建置結果轉成能在 Cloudflare Workers 上跑的格式,用的是 Next.js 的 Node.js runtime。支援的 Next.js 版本是 Next.js 16 的所有版本,以及 14、15 的最新小版本。

先知道一件事:Cloudflare 自己的 Next.js 文件(2026-08-25 更新)現在把 vinext 列為預設推薦做法,vinext 仍在 beta;OpenNext 頁(2026-10-12 更新)寫明是給維護既有 OpenNext 專案用,而且 Wrangler 的自動設定會走 vinext,要用 OpenNext 得手動設定。本文照 OpenNext 這條寫,因為它是建立在 next build 的輸出上;要不要改用 vinext,請先用 vinext 官方的相容性檢查確認。

一定要開 nodejs_compat:OpenNext 與 Cloudflare 的設定說明都寫明,要在 Wrangler 設定檔開啟 nodejs_compat 相容性旗標,相容性日期設在 2024-09-23 以後。Cloudflare〈Node.js compatibility〉頁另外寫明,相容性日期是 2026-08-04 以後的,會預設開啟。

怎麼搬:OpenNext 官方對既有專案的建議是執行:

npx @opennextjs/cloudflare migrate

它會自動完成安裝轉接器、Wrangler 設定檔等步驟;也可以照官方文件手動設定。完成後用 preview 在本機的 Workers 環境預覽,再 deploy。

要注意的限制(引自 Cloudflare〈Workers Limits〉,2026-10-12 更新):

  • CPU 時間:免費方案每次請求 10 毫秒;付費方案預設 30 秒,可以調到 5 分鐘。等待網路請求與資料庫查詢的時間不算在 CPU 時間裡。伺服器端渲染比較吃 CPU,免費方案要先用 preview 測過。
  • 記憶體:每個 Worker 128 MB。
  • Worker 大小:Cloudflare 限制頁寫的是解壓縮後 64 MiB、沒有壓縮後的上限;OpenNext 文件還寫著「免費方案 3 MiB、付費方案 10 MiB(壓縮後)」。兩份文件不一致,以 Cloudflare 官方限制頁為準。
  • 啟動時間:Worker 的全域程式碼要在 1 秒內執行完,套件裝太多會超過。

和 Docker 不一樣的地方:

  • ISR 要自己組快取:OpenNext 文件寫明,一般的伺服器端渲染不用設定快取,但 ISR 與資料快取要另外設定:建議用 R2 存快取、Durable Objects 做重新驗證的佇列、D1 存標籤。
  • 圖片最佳化:要在 Wrangler 設定檔加 IMAGES 綁定,走 Cloudflare Images,官方提醒會另外計費;minimumCacheTTL 設定不支援。
  • 資料庫連線:OpenNext〈Database & ORM〉文件提醒,不要建立全域共用的資料庫連線池,每個請求要建立新的連線,否則後續請求會失敗。從 Zeabur 搬過來、原本寫成全域連線的程式要改。
  • Proxy/Middleware:OpenNext 與 Cloudflare 都寫明「Node.js middleware(Next.js 15.2 起)尚未支援」。Next.js 16 的 proxy.ts 預設跑在 Node.js runtime,兩份文件都沒有寫 proxy.ts 能不能在 OpenNext 上跑;有用的專案,先用 preview 實際測過再決定。

路線三:Docker 自架

關鍵設定是 standalone:在 next.config 加上:

module.exports = {
  output: 'standalone',
}

Next.js 官方文件〈output〉寫明,這會在 .next/standalone 產生一個資料夾,只複製正式環境需要的檔案(包含必要的 node_modules),可以單獨部署、不用再安裝 node_modules,並附一個精簡的 server.js 取代 next start。要注意的是,public 與 .next/static 預設不會被複製進去,要自己複製,或交給 CDN。

官方範例:Next.js 的 GitHub 有官方 with-docker 範例(examples/with-docker),README 寫的既有專案做法是三步:複製範例的 Dockerfile、複製 .dockerignore、在 next.config 加上 output: "standalone"。範例的 Dockerfile 分三個階段(安裝套件、建置、執行),已經處理好 public 與 .next/static 的複製,並以非 root 的 node 使用者執行 node server.js,預設埠 3000。

README 也特別提醒兩件事:

  • 範例的 .dockerignore 會排除 .env,所以本機 .env 裡的值在容器裡會是 undefined。伺服器端用的金鑰要在執行時傳入(例如 docker run -e)。
  • 建置環境裡的 env 檔會被 standalone 一起複製進映像,拿得到映像的人都讀得到。金鑰不要放在會進映像的 env 檔裡。

我們照官方範例做了一次:在自己機房一台 4 核 CPU、8 GB 記憶體的測試虛擬機上,用 create-next-app 建一個新專案(Next.js 16.4.2、Node.js 24.22.0),在 next.config 加上 output: "standalone",再套用官方 with-docker 範例的 Dockerfile 與 .dockerignore:

項目實測結果
第一次建置映像(含下載基底映像、安裝套件)1 分 39.5 秒,其中 next build 這一步 12 秒
改一行程式後重新建置20.0 秒
映像大小391 MB,壓縮後 95 MB(對照 node:lts 映像 1.66 GB,壓縮後 428 MB)
從 docker run 到第一次有回應2.3 秒
記憶體docker stats 顯示 45–47 MiB;容器內行程的 VmRSS 是 95,520 kB。兩種量法差了一倍,比較時要用同一種
首頁回應時間(TTFB)在同一台機器內量 10 次,中位數 3.35 毫秒(2.5–5.2 毫秒),不含對外網路

這是只有預設首頁的新專案,首頁是預先產生的靜態頁;你的專案大小與頁面型態不同,數字會不一樣。我們沒有在 Zeabur 上量同一個專案,所以這裡不做兩邊的比較。

做的過程中,有兩件事值得先知道:

  • 範例的 Node.js 版本要自己更新。官方 Dockerfile 把 NODE_VERSION 固定在 24.13.0-slim,我們建置時 node:lts 已經是 24.22.0。Dockerfile 裡的註解也寫明「regularly update the NODE_VERSION ARG to the latest LTS version」。
  • 自己改寫 Dockerfile 時,照抄範例的兩處:standalone 不會自動帶 public 與 .next/static,範例是另外 COPY 進映像,漏了的話 CSS 與圖片會 404;範例也設了 HOSTNAME="0.0.0.0"。

能放在哪:任何能跑容器的地方。Next.js 官方〈Deploying〉頁寫明,可以部署到任何支援 Docker 容器的服務,包括 Kubernetes;with-docker README 列了 Google Cloud Run、AWS ECS/Fargate、Azure Container Instances、DigitalOcean App Platform,也可以是你自己的 VPS。

要自己處理的事(引自 Next.js〈Self-Hosting〉,2026-10-15 更新):

  • 反向代理與 HTTPS:官方建議在 Next.js 前面放反向代理(例如 nginx),不要直接對外,由它處理異常請求、慢速連線攻擊、請求大小上限與流量限制。HTTPS 憑證也要自己在反向代理或前面的 CDN 上處理。
  • 串流:用 nginx 時要關掉緩衝,串流才會生效,官方的做法是設定 X-Accel-Buffering: no。
  • 圖片最佳化:用 next start(或 standalone 的 server.js)不用另外設定就能用,但需要 sharp 套件。官方提醒,在 glibc 的 Linux 上可能要另外設定,避免吃掉過多記憶體。最佳化後的圖片快取在 .next/cache/images,官方說目前沒有讓快取失效的機制;with-docker 範例特別讓 .next 資料夾可寫入,就是為了存這些快取。
  • ISR 快取:預設存在每個容器自己的磁碟上。只跑一個容器沒問題;開多個容器時,要設定共用的快取(官方有 Redis 範例),不然各容器的內容會不一致。
  • 多個容器的 Server Actions:官方寫明,每次建置會產生不同的加密金鑰,多個容器不一致時會出現「Failed to find Server Action」錯誤,要用 NEXT_SERVER_ACTIONS_ENCRYPTION_KEY 統一。
  • 更新、備份、監控:這些在 Zeabur 上是平台做的,自架後要自己負責。

怎麼切換:先降 TTL,舊的先別關

不管選哪條路,切換的順序都一樣:

  1. 新環境先跑起來:用換過的新金鑰設定環境變數,NEXT_PUBLIC_ 的值確認是新網址後再建置。
  2. 用平台給的測試網址驗收:首頁、登入、表單送出(Server Actions)、API、圖片、ISR 頁面更新,逐項點過。
  3. 先降 DNS 的 TTL:Zeabur 官方〈搬遷專案〉文件建議,切換 DNS 前先降低 TTL,加速生效;也建議搬遷期間暫停對舊專案的寫入,避免資料不一致。
  4. 切 DNS,觀察幾天:確認新環境穩定、沒有流量再回到 Zeabur,才停掉 Zeabur 上的服務。

網域本身如果是在 Zeabur 買的,轉出與 DNS 切換的細節見〈Zeabur 網域怎麼轉出?〉。

怎麼選:一張表

你的情況可以考慮原因先確認
不想管主機,想用 Next.js 原本的功能VercelNext.js 由 Vercel 維護,不用另外設定函式執行時間、4.5 MB 請求大小、商用要付費方案
DNS 已在 Cloudflare,功能用得單純Cloudflare Workers(OpenNext)跑在 Cloudflare 的全球網路上CPU 時間、ISR 快取設定、圖片要開 Cloudflare Images、Node.js middleware
有長時間工作、大檔上傳,或想和資料庫放同一處Docker 自架官方寫明 Docker 部署支援所有功能,時間限制由你自己的環境決定反向代理、HTTPS、備份與監控誰負責
output: 'export' 純靜態任何靜態主機不需要 Node.js 伺服器有沒有其實用到 Redirects、Headers 等不支援的功能

揭露

火曜領航有提供 Next.js 等服務的搬家與主機代管服務,也可以代搬到您自己名下的 Vercel、Cloudflare 或雲端帳號。這篇的步驟不需要找任何人也能自己做。

如果您的服務還在 Zeabur 上,需要人幫忙盤點、搬遷或輪換金鑰,可以到〈PaaS 停運搬家與資安檢查服務〉看四種做法,或直接填寫詢價表單,我們會在一個工作日內回覆搬遷順序建議。

常見問題

Next.js 一定要放 Vercel 嗎?

不用。Next.js 官方〈Deploying〉頁寫明,Next.js 可以部署成 Node.js 伺服器、Docker 容器、靜態網站,或透過轉接器放到其他平台;Node.js 伺服器與 Docker 部署都支援所有 Next.js 功能。Vercel 是其中一個選擇,不是唯一選擇。

Cloudflare 可以跑 Next.js 的 Server Actions 嗎?

可以。Cloudflare 的 OpenNext 說明頁(2026-10-12 更新)在支援功能表裡把 Server Actions 列為「Supported」。但 Cloudflare Workers 有 CPU 時間與記憶體限制,Server Actions 裡如果有比較重的運算,要先用 OpenNext 的 preview 測過。

NEXT_PUBLIC 變數改了為什麼沒生效?

因為 NEXT_PUBLIC_ 的值是在 next build 時寫進前端程式的。Next.js 官方原句是「After being built, your app will no longer respond to changes to these environment variables.」改了值之後要重新建置、重新部署;只重新啟動伺服器或容器,前端拿到的還是舊值。

Docker 映像太大怎麼辦?

先確認 next.config 有設 output: 'standalone'。我們照官方 with-docker 範例建的新專案,映像是 391 MB(壓縮後 95 MB),對照 node:lts 基底映像的 1.66 GB。依 Next.js 官方文件,建置時會分析每個頁面實際用到的檔案,只把正式環境需要的檔案(包括部分 node_modules)複製到 .next/standalone,部署時不用再裝整份 node_modules。再搭配官方 with-docker 範例的多階段建置,做出來的映像只放執行需要的東西。範例 README 也說可以改用 Alpine 映像,但它用的是 musl libc,需要原生二進位檔的套件可能出問題,要自己測過。

可以只搬前端、API 先留在 Zeabur 嗎?

短期可以,但 Zeabur 那端一樣要搬,而且期限可能比 12 月 31 日早。依 Zeabur 官方公告,共享叢集 12 月 1 日起暫停所有運行中的服務;專用伺服器會依各自的到期日,在 12 月 1 日到 31 日之間陸續關閉。前端如果用 NEXT_PUBLIC_ 變數記 API 網址,API 搬家後要改值、重新建置前端一次。

參考來源

以上資料皆於 2026 年 10 月 18–19 日查詢。

最後更新: