CodeGym /課程 /ChatGPT Apps /進階通道:穩定的 dev‑URL 與在 Dev Mode 中更新

進階通道:穩定的 dev‑URL 與在 Dev Mode 中更新

ChatGPT Apps
等級 7 , 課堂 2
開放

1. 「隨機」通道的問題

當你第一次啟動 ngrok http 3000 或快速的 Cloudflare Quick Tunnel,感覺就像魔法一樣:唰——你的 http://localhost:3000 變成了 https://random-1234.tunnelprovider.com。把這個 URL 複製到 ChatGPT 的 Dev Mode,GPT 就會開心地載入你的 App。

然後你重啟通道……又得到一個新網域。ChatGPT 裡 Dev‑應用的舊 URL 瞬間變成「壞掉的連結」,GPT 也老實地顯示「App unavailable」,於是你又回到設定頁,改 URL、按下 Save、等它更新,然後默默地厭世整個技術棧。

偶爾「晚上玩一下」還能忍。但當你:

  • 每天都在持續開發 App;
  • 想給同事/主管看看中間版本;
  • 同時還要設 staging 和 production,

每次遇到新的隨機 URL 都要重連 Dev Mode,這就變成純粹的折磨。

此外,如果你的應用裡已經加了與網域有關的東西(例如 OAuth redirect URI 或 webhook),每個新的 URL 也會把它們一起搞壞。於是出現連鎖反應:換了通道——就得去改 App 的設定、OAuth 供應商上的 redirect‑URL,還有 webhook 接收端的設定。

這就引出本講的核心觀念:穩定的 dev‑URL 不是奢侈,而是維持開發者心理健康的必要工具。

洞見

ChatGPT 對你的應用有非常嚴格的逾時限制,這點很容易被低估。MCP tool call 有時間上限:最多 2 分鐘——超過之後平台就會直接判定呼叫失敗,即使你的伺服器還在做事。

對於應用的註冊(Store 或 Dev Mode),限制更嚴:ChatGPT 讀取你的 manifest、resources 和工具描述大概只有 20 秒。如果在這段時間內你的 MCP 伺服器還沒初始化好、沒把 tools/resources 等回傳,App 註冊就會因逾時而失敗。

建議:所有繁重的初始化都應該發生在你去 Dev Mode 或 Store 之前。預熱資料庫連線、載入大型設定、延遲快取——這些最好事先完成,例如先透過 MCP Jam 或一個內部腳本打一次伺服器。對平台而言,MCP 伺服器必須是「溫的」,回應要在幾秒之內,而不是在註冊期間才「醒來」。

2. 什麼是「進階版」通道

我們來釐清一下,「進階版」通道跟你在課程一開始跑的有什麼不同。

早期模式(模組 2)大概長這樣:

# ngrok 範例
ngrok http 3000
# 會得到: https://random-abc123.ngrok-free.app

你把這個一次性的 URL 填到 Dev Mode。下一次啟動 ngrok 時,URL 又變了,而 ChatGPT 的設定也就過時了。

在「進階」做法中,你會有:

  • 靜態子網域(來自通道供應商或你自己的網域);
  • 同一個網域永遠轉發到你的 localhost:3000
  • 你可以重啟通道、電腦、路由器,但 URL 都保持不變。

這類靜態子網域可用於,例如:

  • ngrok——每個帳號提供免費的 static domain;
  • Cloudflare Tunnel——透過命名通道並綁定自己的網域。

而 ChatGPT 的 Dev Mode 應用就設定成這一個 URL,之後就不再吵你了。

形式上,我們的「進階版」通道需要滿足這些條件:

  • 穩定、固定的公開 HTTPS 網域;
  • 有效的 TLS 憑證(供應商會幫我們處理);
  • 一個設定,描述「把 https://dev.yourdomain.com 的所有流量,轉到 http://localhost:3000」;
  • 可選——基本的安全措施(至少不要把 URL 貼到 Stack Overflow 上曝光)。

3. 設定穩定的 dev‑URL:Cloudflare Tunnel 範例

在課程中我們推薦 Cloudflare Tunnel 作為主要工具,因為它同時適用於開發與更嚴肅的場景。你在模組 2 已經看過基本設定,現在把它「擰緊」到永久的 dev‑URL。

假設我們有一個教學用應用 GiftGenius,希望有穩定的 URL:giftgenius-dev.yourdomain.com

最小步驟(簡化,與 Cloudflare UI 解耦):

  1. 把網域綁定到你的 Cloudflare 帳號(經由他們的後台,一次性)。
  2. 在本機安裝 cloudflared 並登入。
brew install cloudflare/cloudflare/cloudflared   # macOS
cloudflared login                                # 將開啟瀏覽器以完成授權

3. 建立命名通道:

cloudflared tunnel create giftgenius-dev

4. 在 ~/.cloudflared/config.yml 中設定路由:

tunnel: giftgenius-dev
credentials-file: /Users/you/.cloudflared/giftgenius-dev.json

ingress:
  - hostname: giftgenius-dev.yourdomain.com
    service: http://localhost:3000  # 我們的 Next.js 開發伺服器
  - service: http_status:404

5. 啟動通道:

cloudflared tunnel run giftgenius-dev

現在,只要 npm run devcloudflared tunnel run 在執行,你的本機 Next.js 就能透過穩定的 URL https://giftgenius-dev.yourdomain.com 對外提供。而在 ChatGPT 的 Dev Mode 設定中,你就填這個位址。

這如何與我們的應用程式銜接

如果你在瀏覽器中打開你在 ChatGPT 連接 Dev‑應用時輸入的應用 URL:

https://giftgenius-dev.yourdomain.com/mcp

你會看到一個回應(錯誤)——類似這樣:

{"jsonrpc":"2.0","error":{"code":-32000,"message":"Method not allowed."},"id":null}

這完全正常,因為 /mcp 端點不預期 GET 請求。應用的其他部分——小工具、MCP 端點 /mcp、API 路由——也都走同一條通道,你不需要每次記住新網域。

4. 替代方案:ngrok 的穩定子網域

如果你已經習慣 ngrok,也可以用類似的方式「進階化」,改用 static domain。自 2023 年起,ngrok 即使在免費方案也提供一個靜態子網域,例如 myapp-dev.ngrok-free.app

最小設定:

# ~/.config/ngrok/ngrok.yml
authtoken: <你的 token>
tunnels:
  giftgenius-dev:
    addr: 3000
    proto: http
    domain: giftgenius-dev.ngrok-free.app

啟動:

ngrok start giftgenius-dev

結果是 https://giftgenius-dev.ngrok-free.app 會是固定的,你就把它提供給 ChatGPT 的 Dev Mode 作為應用的基底 URL。

理念相同:

  • 不再有任何「隨機」位址;
  • 只有通道的內部狀態(啟動/停止)在變,網域不變;
  • 不需要重綁 Dev Mode。

Cloudflare 與 ngrok 在這個意義上就像不同口味的冰淇淋。有的人喜歡自有網域與較細的 DNS 控制(Cloudflare),也有人偏好「寫好 YAML 就搞定」(ngrok)。在本課兩種做法都可行,關鍵只有一個——穩定的 URL

5. 示意圖:ChatGPT Dev Mode ↔ 通道 ↔ 本機技術棧

為了稍微形式化一點,我們畫張圖。

flowchart TD
    ChatGPT["ChatGPT (Dev Mode)"]
    AppCfg["Dev App(設定:https://giftgenius-dev...)"]
    Tunnel["Cloudflare/ngrok 通道(giftgenius-dev...)"]
    Next["Next.js 開發伺服器 localhost:3000 + MCP handler"]

    ChatGPT --> AppCfg
    AppCfg -->|"設定中填入 https://giftgenius-dev.../.well-known/openai-app"| Tunnel
    Tunnel -->|"HTTPS → HTTP 代理"| Next

ChatGPT 永遠不知道你筆電上在跑什麼。對它而言只有一個 HTTPS 端點。這個端點背後到底是 Vercel、本機通道、或 Kubernetes——由你決定。而在這一講,我們關注的是本機開發時,這個 HTTPS 端點的穩定性。

接下來要做到的是,讓我們的應用內部也把這個位址視為唯一的「真相來源」,而不是散落在硬編碼字串裡——下一節就來處理這件事。

6. 程式中的環境變數與 baseURL

為了讓一切可預期,建議在 Next.js 程式裡定義一次「應用對外的基底 URL」,之後一律依賴它。

例如,在我們的 GiftGenius 應用中,在 app/lib/config.ts 建立:

// app/lib/config.ts
export const baseUrl =
  process.env.NEXT_PUBLIC_APP_URL ?? "http://localhost:3000"; // fallback

export const mcpEndpoint = `${baseUrl}/mcp`;  // MCP 伺服器的 URL

然後在開發用的 .env.local 指定:

NEXT_PUBLIC_APP_URL=https://giftgenius-dev.yourdomain.com

這樣一來:

  • 在小工具與任何連結中,你都只使用 baseUrl
  • 對 ChatGPT Dev Mode 與瀏覽器而言,一切保持一致;
  • 如果你改天遷到 Vercel 的 staging,網域換成 https://giftgenius-staging.vercel.app, 只要改環境變數即可。

這對以下情境尤其重要:

  • callback‑URL(例如 OAuth、webhook 處理器);
  • 你在小工具中顯示給使用者的連結(透過 openExternal 的「在瀏覽器開啟」按鈕);
  • 應用程式邏輯中任何需要絕對 URL 的地方。

雖然我們目前只談 dev‑URL,但「baseUrl 單一真相來源」這個架構觀念同樣適用,之後也能平順搬到 staging/production。

7. 在 ChatGPT Dev Mode 中更新 URL

好,我們已經有漂亮的穩定網域了。那在 Dev Mode 中要怎麼用?

邏輯如下:

  1. 在 Dev‑應用的設定中,先填一次根 URL:https://giftgenius-dev.yourdomain.com/
  2. ChatGPT 會透過它去抓 manifest(.well-known/openai-app), 接著也用同一個根去連 MCP(/mcp)、靜態資源等。
  3. 若你只改程式碼(React 小工具、MCP handlers、樣式),完全不需要改 URL。 只要通道有啟動、Next.js 伺服器有回應即可。
  4. 如果你改了網域本身(比較少見,例如從 ngrok 換到 Cloudflare),那就進 Dev Mode 把 endpoint 改一次。

某些情況下 ChatGPT 會快取 manifest,內容不一定立即更新。Dev Mode 介面通常有「Reload configuration / Refresh App」之類的按鈕;最糟的情況下,關閉再用相同 URL 重新連一次 App 也能解決。

重點:只要你不改 URL,Dev Mode 就會自動「抓到」新版程式。對 App 而言,網域才是主要的觸發點,而不是 commit‑hash。

8. 在 Dev Mode 中切換 dev/staging/prod

穩定的 dev 網域只是第一步。為了避免專案擴張後被一堆 URL 淹沒,最好一開始就理解 dev 通道如何融入整體環境(dev/staging/prod)與 Dev Mode。雖然 staging 與 prod 比較屬於下一堂 Vercel 的主題,但 Dev Mode 現在就能搭配多個環境使用。

先看一張有助理解的表格:

環境 基底 URL 程式在哪裡跑
Local
https://giftgenius-dev.yourdomain.com
本機 Next.js + 透過通道的 MCP
Staging
https://giftgenius-staging.vercel.app
Vercel Preview/staging 部署
Prod
https://giftgenius.vercel.app
Vercel Production

與 Dev Mode 的搭配有兩種做法。

第一種——一個 Dev‑App,但你偶爾去改它的 URL 來測 staging 或 prod(要小心)。這在早期還可以,但很容易搞混:今天測本機、明天測 staging、後天忘了切回來,結果用 Dev‑App 把請求打到 prod。

第二種——更健康:多個 Dev‑應用,各自綁定明確的環境:

  • GiftGenius Devgiftgenius-dev.yourdomain.com
  • GiftGenius Staginggiftgenius-staging.vercel.app
  • GiftGenius(正式版,透過 Store)→ giftgenius.vercel.app

在本講中我們先一步步把 dev‑URL 整頓好。下一講你會看到如何把 Vercel 與 preview 部署合理地對應到 staging/production。

9. 團隊合作:多位開發者與一個通道

當只有一個 dev 網域、也只有一位內向開發者時,通道就是你個人的好朋友。但一旦進到團隊專案,通道與環境就會互相交錯,此時要避免上演「搶一個子網域之戰」。

想像兩位開發者決定共用同一個靜態子網域,例如 giftgenius-dev.ngrok-free.app。兩人都在自己電腦上啟動 ngrok start giftgenius-dev。最好的情況是一個通道起不來(網域衝突);最糟的是你們會輪流「蓋過」彼此的連線,ChatGPT 時而連到甲、時而連到乙。

這裡有幾種策略。

最簡單——個人化的 dev 網域

  • alex.dev.giftgenius.app
  • maria.dev.giftgenius.app

並且每個人在 ChatGPT 中都有自己的 Dev‑App,例如 GiftGenius Dev (Alex)GiftGenius Dev (Maria)。如此一來各自安穩地跑本機,不互相干擾。

更「團隊化」的做法——共用 staging 端點:

  • 每位開發者都有個人 dev 通道(用於個人除錯)。
  • 另外有一個 Vercel 上的 staging,feature 分支合併後部署;共用的 Dev‑App GiftGenius Staging 指向它。

這在真實團隊裡很常見:

  • 功能先在本機誕生,透過個人通道除錯;
  • 送出 pull request 並合併後,大家在 staging 一起測試(不需要通道,直接用 Vercel URL)。

10. dev 通道的安全性(簡短不恐慌)

通道是把你的本機伺服器拉到網際網路上的方便方式。但網際網路多由機器人、掃描器,以及喜歡檢查你是否忘了密碼 admin/admin 的人組成。

在 dev 階段就值得注意的基本事項:

  • 通道會讓外界能存取該埠上的所有服務;不要連資料庫後台、phpMyAdmin、或「我的無密碼測試 CRM」也一起曝露;
  • 不要把通道的 URL 公開貼在開放的倉庫或聊天群;
  • 不工作時請關閉通道(筆電也偶爾關機——它也需要休息)。

更嚴格的作法,例如 Basic Auth、檢查特殊標頭、或在 URL 中帶 token,會在安全性模組中再談。現在只要記住一件事:通道是開發工具,不是受保護的伺服器。正式環境會在像 Vercel 這樣的正規主機上運行,並用不同的保護機制——我們會在下一講抵達那裡。

11. 實作:為我們的應用設定穩定的 dev‑URL

現在從理論與提醒進入實作:把這些綁到我們的 Next.js 教學應用(Apps SDK 範本)。

假設專案結構如下:

apps/
  web/          # Next.js App + 小工具
  mcp-server/   # (可選)獨立 MCP,或 web 裡的 /mcp handler

實務上你可以直接把 MCP 放在 Next.js,例如 app/api/mcp/route.ts,原則相同。

步驟 1. 修改 .env.local

加入穩定的 dev 通道路徑:

NEXT_PUBLIC_APP_URL=https://giftgenius-dev.yourdomain.com

在開發程式碼中,我們已經從這個環境變數使用了 baseUrl(見上)。如果還沒有,現在就是抽出來的時候。

步驟 2. 啟動 dev 伺服器與通道

cd apps/web
npm run dev          # Next.js 在 localhost:3000

# 另外一個終端機
cloudflared tunnel run giftgenius-dev

在瀏覽器中確認 https://giftgenius-dev.yourdomain.com 能打開並顯示你的 App。

步驟 3. 在 ChatGPT Dev Mode 中連接

在 ChatGPT 介面(開發者區):

  • 建立或編輯 GiftGenius Dev
  • 在 URL/Endpoint 欄位填入 https://giftgenius-dev.yourdomain.com/
  • 儲存。

之後 ChatGPT 會透過 /.well-known/openai-app 讀取 manifest,接著就會以這個網域來啟動你的 App。

此時你可以:

  • 更改小工具、MCP handlers、樣式;
  • 重啟 npm run dev
  • 重啟 cloudflared tunnel run giftgenius-dev

但只要網域不變,就再也不用去改 Dev‑App 設定

12. 程式邏輯中的樣子:openExternal 範例

把例子和我們先前的講解串起來:在小工具加一個「在瀏覽器開啟完整介面」的按鈕,也使用那個穩定的 dev‑URL。

假設我們有一個小工具的 React 元件 GiftWidget

// app/components/GiftWidget.tsx
"use client";

import { baseUrl } from "../lib/config"; // 從 env 取得 baseUrl

export function GiftWidget() {
  const handleOpenFull = () => {
    window.openai.openExternal({
      // 在新分頁開啟應用頁面
      url: `${baseUrl}/full`,
      label: "開啟完整介面",
    });
  };

  return (
    <div>
      <button onClick={handleOpenFull}>
        完整模式
      </button>
    </div>
  );
}

如果 NEXT_PUBLIC_APP_URL 指向通道,那麼:

  • 在本機開發時會開啟 https://giftgenius-dev.yourdomain.com/full
  • 部署到 staging 後會開啟 https://giftgenius-staging.vercel.app/full
  • 在 prod 時就是正式網域。

再次強調——網域只有一個真相來源:換環境,不改程式碼。

13. 迷你策略:用「進階」心態看待通道

把一切收斂成簡單的心智模型:

  • 通道只是一條臨時的導線,把你的筆電接到穩定的公開網域;
  • ChatGPT Dev Mode 只認網域,不在乎你的程式實際跑在哪;
  • 你越少改網域,就越少在 ChatGPT 與 OAuth 供應商的設定中浪費時間;
  • dev 通道只是你整體環境地圖中的一行,旁邊還有 staging(Vercel preview)與 prod(Vercel production)。

下一講會示範如何把這條導線換成 Vercel 上的正式託管,並把它和 Git 分支、preview 部署、以及正式環境串起來。

14. 使用「進階版」通道時的常見錯誤

錯誤 №1:「我已經設定了靜態網域,卻還在用隨機 URL」。
有時開發者會先做出漂亮的 giftgenius-dev.yourdomain.com,但出於習慣,仍然直接跑 ngrok http 3000 而不使用設定檔。結果是 ChatGPT 指向一個網域,而程式在另一個網域後面跑。如果你已經有穩定的 dev‑URL——就只用它,並用設定檔(命名通道/設定檔案)來啟動通道。

錯誤 №2:把 localhost:3000 硬寫死在程式碼裡。
常見於在 React 元件或 MCP handler 裡寫 fetch("http://localhost:3000/api/...")。在本機可能還能用,但在 Dev Mode、尤其 staging/prod 會立刻壞掉。永遠把基底 URL 抽到設定裡(baseUrlNEXT_PUBLIC_APP_URL),並在所有需要絕對連結的地方使用它。

錯誤 №3:老是去改 Dev Mode 的 URL,而不是用穩定通道。
如果你常想「算了我再改一次設定裡的 URL 就好」——這就是警訊。設定好 ngrok/Cloudflare 的靜態子網域只需 10–15 分鐘,卻能在開發過程中省下好幾小時。

錯誤 №4:整個團隊共用一個靜態網域,卻沒有規則。
兩位開發者、同一個網域 giftgenius-dev.ngrok-free.app,兩個人想啟動通道就啟動。結果就是通道衝突、Dev Mode 回應「神祕消失」、以及「在我機器上是好的」式的除錯。團隊要嘛每人一個 dev 網域,要嘛用真實主機架一個 staging 網域。

錯誤 №5:把通道當作「幾乎是正式環境」。
有時有人會想:「既然我有透過通道的穩定 HTTPS 網域,不如讓真正的使用者/金流都走它」。這是在找苦吃:筆電關機——應用就掛;網路斷線——一樣;而安全性頂多是象徵性的。通道是 dev 工具。正式流量應該走 Vercel 等進階基礎設施——我們會在下一講抵達那裡。

錯誤 №6:忘了同步環境變數與 Dev Mode。
常見情況是改了 NEXT_PUBLIC_APP_URL(在 .env.local),卻忘記同步改 Dev Mode 的 URL(或反過來)。結果小工具產生的連結指向一個網域,而 ChatGPT 連的是另一個。維護一張簡單的表——「環境 ↔ 網域 ↔ ChatGPT 中的 App」——並在變更時更新,遠比瞎猜「現在到底哪個 URL 才是真的」要省時省心。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION