在海上,Pi 沒辦法讓救生艇停下來。救生艇上有一個海錨,放進水裡之後,船還是會漂,但不會被浪打得團團轉。
到昨天為止,這個網站都只活在我的電腦裡。localhost:3000 只有我打得開,關掉電腦,它就消失了。今天要讓它離開我的電腦:先把網站部署到雲端的主機上,再替它取得一個網址,讓別人輸入這個網址,就能找到它。
網站背後的機器會換、位置會變,但只要有一個固定的網址,別人就找得到它。這就是網站的海錨。
Day 12 為了用手機測試,我們已經試過讓網站「被別的裝置打開」:先用同一個 Wi-Fi 的區網 IP,再用 ngrok。今天的部署,是這條路的最後一步。
| 誰打得開 | 我的電腦關掉之後 | 網址固定嗎 | 適合 | |
|---|---|---|---|---|
localhost:3000 |
只有我這台電腦 | 打不開 | 固定,但只對自己有效 | 開發 |
區網 IP(192.168.x.x) |
同一個 Wi-Fi 裡的裝置 | 打不開 | 換個網路就變了 | 用手機實機測試 |
| ngrok | 任何人 | 打不開 | 免費版通常會換 | 暫時給別人看、測試登入 |
| 部署+網域 | 任何人 | 還在 | 固定 | 正式上線 |
前三種,網站都還是跑在我的電腦上。ngrok 只是替它開了一扇門,讓外面的人連得進來;電腦一關,門也跟著關了。

【圖 1|網站跑在哪裡】
ngrok 是讓別人連進我的電腦;部署是讓網站不再需要我的電腦。
要讓網站真正上線,要補齊三件事:程式放在哪裡、網站叫什麼名字、這個名字指到哪裡。資料庫則沿用原本的 Supabase。
| 要決定的事 | 負責的地方 | 這次的專案 |
|---|---|---|
| 程式放在哪裡 | 部署平台 | Vercel |
| 網站叫什麼名字 | 網域註冊商 | biashelf.com |
| 這個名字指到哪裡 | DNS 服務 | cloudflare |
| 資料放在哪裡 | 資料庫 | Supabase |

【圖 2|上線的角色分工】
這張圖是今天的地圖。每一層只回答一個問題,彼此可以是不同的公司(也可以是)。接下來每一節,都在處理其中一層。順序照實際操作:先部署,再買網域,最後把兩邊接起來。
可以部署 Next.js 的地方不少,常見的有這幾種(以下是以「部署一般 Next.js 專案」為前提的粗略比較,實際難度會依功能而變。):
| 平台 | Next.js 支援 | 設定難度 | 比較適合 |
|---|---|---|---|
| Vercel | Next.js 的開發商,新功能通常最先支援 | 低 | Next.js 專案、前端為主的網站 |
| Netlify | 支援,部分功能透過轉接處理 | 低 | 靜態網站、前端專案 |
| Cloudflare(Workers) | 可以部署,但執行環境不同,功能相容性要另外確認 | 中 | 已經在用 Cloudflare、在意流量成本 |
| Render/Railway | 當成一般 Node.js 伺服器來跑 | 中 | 有長時間執行的後端、背景工作 |
| 自己租主機(VPS) | 什麼都能裝 | 高 | 想完全自己掌控;更新、安全也都要自己來 |
我最後選 Vercel,原因很單純:它是 Next.js 的開發商,幾乎不用額外設定;推上 GitHub 就會自動部署;每個分支還會有自己的預覽網址。目前也沒有需要長時間執行的後端,用不到一台一直開著的伺服器。
免費,不一定商用
Vercel 的免費方案(Hobby)限個人、非商業用途。如果之後放廣告、收費,就要換方案。選平台時,除了流量限制,也要看使用條款。成本的部分,留到 Day 28。
第一次部署大致是這樣:
xxx.vercel.app 的網址
【圖3|新增專案】

【圖4|匯入github Repo專案】
(過程中需要登入github並授權,可以選擇授權單一repo或是所有repo)

【圖5|設定專案細節】
小技巧:Vercel 支援直接貼上整段
.env格式內容,會自動拆成多個環境變數,不需要一個一個複製貼上。

【圖6|部署成功】
過程中,如果有出現錯誤,可以複製錯誤訊息請 AI 分析是哪個環節出錯。
此外,畫面 UI 可能會有調整,不一定跟我的截圖完全一模一樣,但流程基本沒變。
到這一步,網站其實已經上線了,任何人打開這個網址,都看得到,你的電腦不需要一直開著。
之後就不用再手動部署了:

【圖7|部署完後推上 GitHub 流程】
以這個專案目前的預設設定,main 對應正式網站,其他分支產生預覽網址(這可以在 Vercel 設定裡更改)。
Day 20 提過「build 不等於部署」,這裡就看得出差別:build 失敗,就不會進到部署那一步,正式網站會維持上一個成功的版本。
Preview 是很好用的功能:還沒合併的修改,也有自己的網址可以先看、先測,確認沒問題再合併進 main。
本機開發時,Supabase 的網址、金鑰這些設定,都放在 .env.local。但這個檔案被 .gitignore 排除了,不會上傳到 GitHub,Vercel 自然也拿不到。所以在部署時,會需要重新設定一次。
設定時有幾件事要注意:
NEXT_PUBLIC_ 開頭的值,會在 build 時直接寫進瀏覽器的程式。 任何人打開 DevTools 都看得到,所以 secret key 絕對不能加這個前綴。放進環境變數,不代表就是祕密;這個值最後在哪裡執行,才決定使用者看不看得到。網站搬家了,Supabase 還不知道。
登入流程裡,Supabase 會在驗證完成後,把使用者送回網站。但它只會送到事先登記過的網址;不在名單上的,會被拒絕,或被送回預設網址。如果只登記了 localhost,正式網站登入完,就可能被帶回我自己的電腦。
所以要到 Supabase 後台的 Auth 設定裡,更新兩個地方:
| 設定 | 意思 | 要填 |
|---|---|---|
| Site URL | 預設的網址,例如驗證信裡的連結 | 正式網址 |
| Redirect URLs | 允許送回去的網址名單 | 正式網址(寫精確的網址);另外加上 localhost 和 Preview 的網址,Preview 可以用萬用字元一次涵蓋 |

【圖8|Supabase Auth 網址更改】
這一步很容易漏掉,因為 Vercel 那邊一切正常,問題會在「登入」這個動作才出現。而且等一下接上網域之後,這裡要再改一次。
如果確定要購買網域,可以等設定好網域後,再進行這步。(圖8的截圖是買完網域後的截圖)
部署完之後,專案可能有三個地方在跑:我的電腦、Preview、正式網站。但目前的情況,它們都連到同一個 Supabase 專案。

【圖9|目前的環境】
這代表:
常見的做法是把環境分開:
| 做法 | 意思 | 代價 |
|---|---|---|
| 維持同一個 | 靠自己小心 | 最省事,但一不小心就會影響正式資料 |
| 多開一個 Supabase 專案 | 開發和 Preview 用一個,正式網站用另一個 | 兩邊的資料表結構要保持一致 |
| Supabase Branching | 每個分支自動產生一份獨立的資料庫環境 | 設定較多,依方案可能需要付費 |
這次先不分開,但把它記成一個已知的風險。目前只有我一個人開發、還沒有真正的使用者,資料也很少。只要出現下面任何一種情況,就該重新評估:
要不要分開環境,看的不只是現在有多少人在用,也看測試時會做什麼事、出錯時會傷到誰。
xxx.vercel.app 能用,但品牌識別度相對沒那麼高,也不是自己的。只要換平台,這個網址就不見了。所以可以買一個自己的網域。
www . biashelf . com
子網域 網域名稱 後綴(頂級網域,TLD)
└───── 根網域 ──────┘
biashelf.com,也就是買下來的部分www.biashelf.com、xyz.biashelf.com。買了根網域之後,子網域可以自己開,不用另外付錢| 類型 | 例子 | 誰能買 |
|---|---|---|
| 通用後綴 | .com、.net、.org |
任何人。原本分別代表商業、網路、組織,現在已經沒有限制 |
| 新的通用後綴 | .app、.dev、.shop、.xyz |
任何人,用途比較直觀 |
| 國家後綴 | .tw、.jp、.uk |
依各國規定;.tw 任何人都能買 |
| 國家底下的分類 | .com.tw、.org.tw、.idv.tw |
有身分限制,例如公司或商號、組織、個人 |
| 限定機構 | .edu、.gov、.edu.tw、.gov.tw |
只有學校、政府機關 |
(.tw 後綴的網域,通常要在台灣的網域供應商購買)
.com。大家最熟悉,也最不容易打錯.tw 或 .com.tw 都適合,但 .com.tw 要有公司或商號.dev、.app 很常見。這兩個後綴強制使用 HTTPS,部署在 Vercel 上剛好沒問題.tw 後綴的)常見的購買地方:
| 地方 | 特色 |
|---|---|
| Cloudflare | 照成本價賣,不另外加價;DNS 必須交給 Cloudflare 管理 |
| Namecheap、Porkbun | 價格透明,介面簡單 |
| Vercel | 買了直接接到專案,最省事 |
| 台灣的註冊商(Hinet、PChome) | 要買 .tw、.com.tw 這類網域,要找有提供的註冊商 |
挑的時候,可以看這幾件事:
我最終,選擇在 Cloudflare Registrar 上購買了biashelf.com 的網域,主要考量是價格以及 DNS管理不需要再轉移。

【圖 10|Cloudflare Registrar 瀏覽網域】

【圖 11|同一個網域 Vercel 貴了一點點】 (但可以發現有.com.tw的)
買網域的地方,和管理 DNS 的地方,可以不是同一個。
網域在 Namecheap 買、DNS 交給 Cloudflare 管理、網站放在 Vercel,三個都是不同的公司,這也很常見。不過通常也有公司橫跨多種服務,像是Vercel 、Cloudflare 同時可以購買網域、管理DNS、部署網站。
電腦之間其實是用 IP 位址找到彼此,網域只是給人記的名字。DNS(Domain Name System,網域名稱系統)做的事,就是把名字換成位址。

【圖 12|輸入網址後流程】
這裡簡化了中間幾層查詢,只留下最重要的兩個角色:
1.1.1.1、8.8.8.8 這類公共服務解析器問到答案之後,會存一份複本,每筆紀錄也有自己的有效期限(TTL)。所以修改 DNS 之後,有時要等一段時間,各地才會看到新的結果;我的電腦已經是新的,別人的可能還是舊的。
這就是昨天講的快取。昨天講的是資料為什麼會舊,今天會發現:連「這個網站在哪裡」這個答案,本身都會被快取。
DNS 裡存的是一筆一筆的紀錄。今天和明天會用到這幾種:
| 紀錄 | 意思 | 例子 |
|---|---|---|
| A | 名字 → IP 位址 | 根網域指到 Vercel 的 IP |
| CNAME | 名字 → 另一個名字 | www 指到 Vercel 給的名稱 |
| NS | 這個網域的 DNS,由誰負責 | 指定由 Cloudflare 管理 |
| TXT | 一段文字,常用來證明「這個網域是我的」 | 明天寄信會用到 |
| MX | 寄到這個網域的信,要送到哪裡 | 明天寄信會用到 |
NS 決定要去問誰;A、CNAME 才決定答案是什麼。
www,並選一個當主要網址,另一個自動轉過去www)用 CNAME

【圖 13|新增網域】

【圖 14|Vercel上會顯示要設定的DNS紀錄】

【圖 15|管理DNS的地方,添加紀錄(以Cloudflare為例)】

【圖 16|添加 DNS 紀錄(以Cloudflare為例)】

【圖 17|添加 DNS 紀錄-2(以Cloudflare為例)】
紀錄的值,以 Vercel 畫面上顯示的為準。不同專案拿到的值可能不一樣,不要直接照抄別人的教學。(像這次我的根網域他顯示也用CNAME)
為什麼根網域也能用 CNAME?
DNS 規格傳統上不允許 apex 直接使用普通 CNAME,但 Cloudflare 提供 CNAME Flattening,可以讓根網域看起來用 CNAME 指向其他 hostname,再由 Cloudflare 回傳最終位址。
所以實作時不要死背「根網域一定是 A」,以平台當下顯示的設定為準。
要注意,接上網域,並不是把網域搬到 Vercel。網域還是在原本的註冊商,DNS 也還是在原本的地方管理;只是多了幾筆紀錄,告訴大家:這個名字的網站,在 Vercel 那裡。
另一種做法是把 DNS 整個交給 Vercel 管理(改用 Vercel 的 nameserver)。設定更少,但這個網域的其他紀錄(例如信箱)也要一起搬過去。接好之後,Vercel 會自動申請 HTTPS 憑證,不用自己處理。
最後,回到 Supabase,把 Site URL 和 Redirect URLs 換成新網域。 這是 4.3 說的「要再改一次」。
上面那一步,非常重要,會影響到登入功能。

【圖 18|更換 nameserver(NS) 前後】
如果網域在 Cloudflare 買,DNS 本來就在 Cloudflare,直接加紀錄就好。(這也是選擇在Cloudflare買的原因)
如果在其他地方買,又想用 Cloudflare 管理 DNS,有兩種做法:
做法一:只把 DNS 交給 Cloudflare(較常見)
網域還是在原本的地方續約,只是「誰負責回答這個網域在哪裡」換人了。
換之前,先確認原本的紀錄都搬過去了,尤其是信箱的 MX 紀錄。Cloudflare 通常會自動掃描原有的紀錄,但最好自己再對一次,不然網站正常了,信卻收不到。
做法二:把網域整個轉到 Cloudflare
如果連網域註冊商也想一起換,需要做 Domain Transfer。那是另一件事,和單純更換 nameserver 不同;只想讓 Cloudflare 管 DNS,不需要搬網域。
只是想用 Cloudflare 管 DNS 的話,做法一就夠了。
在 Cloudflare 加紀錄時,旁邊有一朵雲:
這次我用灰色。Vercel 本身已經有 CDN 和 HTTPS,多繞一層 Cloudflare,多一層 Proxy,快取、TLS、來源 IP 與除錯路徑都會多一層設定,出問題時比較難查。如果之後真的需要 Cloudflare 的防護或快取功能,再另外評估。
| 測試 | 預期結果 |
|---|---|
打開 xxx.vercel.app |
看到 Biashelf |
| 推一個新分支 | 產生 Preview 網址 |
| 故意讓 build 失敗 | 正式網站維持上一個版本 |
| 打開正式網域 | 看到網站本體,網址是 HTTPS |
打開 www 版本(或根網域) |
自動轉到主要網址 |
| 在正式網域登入 | 登入後回到正式網域,不是 localhost |
| 在 Vercel 檢查 Preview 的環境變數 | 確認用的是哪一組(目前和正式相同,是已知風險) |
| 收藏、回報錯誤、管理後台 | 跟本機一樣正常 |
| DevTools 搜尋瀏覽器載入的程式 | 找不到 secret key |
用 nslookup 或 dig 查網域 |
回傳的紀錄和 Vercel 要求的一致 |
| 關掉自己的電腦,用另一台裝置打開正式網域 | 網站照常運作 |
| 手機關掉 Wi-Fi,用行動網路打開正式網域 | 網站照常運作 |

【圖 19|開新的無痕視窗,輸入剛剛購買的網域】
| 情境 | 網域 | DNS | 主機 |
|---|---|---|---|
| 公司官網 | 早年就買好,在某家註冊商 | 可能交給 Cloudflare | 換過好幾次平台,網址一直沒變 |
| 電商開店平台 | 店家自己的網域 | 店家用 CNAME 指向平台 | 平台統一管理 |
| SaaS 讓客戶用自己的網域 | 客戶的網域 | 客戶加一筆紀錄指向服務 | 服務商的主機 |
| 公司內部系統 | 內部網域 | 公司內部的 DNS | 公司自己的機房或雲端 |
網域、DNS、主機分開,好處就是其中一個換掉,另外兩個不用跟著動。網址不變,使用者不會發現網站搬過家。
今天的新觀念:
| 觀念 | 一句話 |
|---|---|
| 部署平台 | 程式在哪裡執行 |
| Preview/Production | 還沒合併的修改有自己的網址,合併後才更新正式網站 |
| 環境變數 | 設定和金鑰不寫在程式碼裡,依環境給不同的值 |
| 網域註冊商 | 買網站名字的地方 |
| DNS | 把名字換成位址 |
| Nameserver | 決定這個網域的 DNS 由誰負責 |
| 環境分離 | 開發、Preview、正式是不同的環境;要不要共用資料,看風險決定 |
網站終於不需要等我的電腦開著,別人才連得到了。
背後的機器在哪裡,我其實不知道,那是 Vercel 在管的。以後它也可能換地方,甚至我可能會換別的平台部署;但只要重新設定,讓網址指到新的位置,別人照樣找得到它。這就是今天放下的海錨。
有了自己的網域,就像有了一個屬於自己的招牌。那麼,寄信是不是也能用這個網域?比起陌生的寄件地址,收到 noreply@自己的網域 寄來的信,看起來也更可信。
不過,寄件人寫上自己的網域,不代表信就收得到。登入驗證信、通知信寄出去,還是可能直接被丟進垃圾信件匣。
明天,我們要用自己的網域寄信,而且讓信真的被收到。答案,一樣藏在今天設定的 DNS 裡。
我們明天見。