從一個封包到一套可擴展架構:前端該懂的 15 個全端概念
文字解析 · 1 支影片 · 產生於 2026-10-01 00:54
章節(16)
1. Outline
- 起點 · 15 Fullstack Concepts Every Frontend Should Know
從瀏覽器按下 Enter 之後的第一個封包開始,一層層往上推到 API Gateway、BFF 與負載平衡,把「前端該懂的全端」串成一條完整路徑。
2. YouTuber 的思維推導
15 Fullstack Concepts Every Frontend Should Know
theSeniorDev · 41m57s · 字幕 en · vision=on (整支影片是簡報+手繪架構圖講解,transcript 中「in this picture you see」「if we look at the headers」「this is the diagram of the Amazon API gateway」「and this is how these certificates look like」等指示語遠超過 3 次,封包結構、TLS 交握、N+1、BFF 架構都要看圖才懂,因此逐張讀圖。) · YouTube
預估 vs 實際耗時
| 階段 | 預估 | 實際 |
|---|---|---|
| fetch | 6s | 1s |
| segment | 1m54s | 5m00s |
| shot | 1m24s | 9s |
| analyze | 17m30s | 25m00s |
| render | 5s | – |
作者的推導是一條「由下往上、每一層都由上一層的缺口逼出來」的直線。他先從最底層問「在網址列按 Enter 之後到底發生什麼」,得到 HTTP 一問一答的模型;為了送出請求需要 IP,於是有 DNS;為了理解 IP 為什麼稀缺又為什麼有物理極限,於是往下看封包與海底電纜。既然跨網路有成本,就用快取省掉那趟路;既然連線是明文,就用 TLS 把它包起來。
到這裡「安全地拿一份資源」完整了,但 HTTP 仍然只能由客戶端發問,於是他用 polling → WebSocket → SSE 三段給出即時通訊的梯度。接著他把焦點從「怎麼傳」換到「請求長什麼樣」:RPC 讓請求像呼叫函式但會把兩端綁死,REST 用資源與動詞換來可預測性,卻在同時服務桌面與手機時裂成 under-fetching 與 over-fetching,於是 GraphQL 把欄位的決定權交給前端,而這又帶出 N+1 與 DataLoader。最後兩層是架構與組織:API Gateway 把各微服務重複的邊緣功能抽出來做一次,BFF 讓前端團隊擁有自己的資料層以繞開跨團隊協調,而全部流量集中之後產生的單點故障,再由負載平衡收尾。
整支影片的落點不是十五個名詞,而是一句話:前端要往 senior 走,必須看得見自己那個 fetch 之後的整條路徑,並且知道每一層是被前一層的哪個缺口逼出來的。
推理鏈:每段留給下一段的線索
每一列是一段,箭頭後的字是這段留給下一段的線索。點段落標題跳到該段。
- HTTP:一封信的來回 → 整條路徑都建立在「請求要送到某個 IP」上,可是你在網址列打的是 theseniordev.com 而不是一串數字——那個 IP 是誰告訴瀏覽器的?
- DNS:先問到 IP 才能發請求 → DNS 換來的是一串 IP 加一個埠號,但 IP 本身到底是什麼、為什麼會有「不夠用」這種事?
- IP:機器之間如何找到彼此 → 既然跨網路取檔案受限於光速與實體線路,那有沒有辦法乾脆不要再跑那一趟?
- HTTP 快取與 E-Tag → 快取解決了速度,但從第一個封包到現在,整條連線都是明文的——坐在中間的人看得到你送了什麼。
- TLS:為什麼要換兩種加密 → 到這裡「安全地把一份資源拿回來」已經完整了,但 HTTP 從頭到尾都只能由客戶端發問——想要「狀態一變就知道」該怎麼辦?
- Polling:最土但最簡單的即時 → 輪詢的成本跟「問的頻率」成正比,一旦資料量變大或要做聊天這種雙向場景,它就撐不住了。
- WebSocket:改成打電話 → 但很多場景其實只需要伺服器單向一直送,為了這個開一條雙向通道並不划算。
- SSE:AI 應用的串流來源 → 前面談的都是「怎麼把資料搬過來」,還沒談「請求本身該長什麼樣」——如果請求可以直接是「執行對面的一個函式」呢?
- RPC / tRPC 與 MCP → 既然主流仍然是 REST,那 REST 到底規範了什麼,才讓它贏過 RPC?
- REST:把 HTTP 標準化 → 這套規則有個隱含假設:只有一種客戶端。一旦要同時服務桌面與手機,它就開始出現裂縫。
- Under-fetch 與 Over-fetch → 如果問題出在「欄位由後端決定」,那把決定權交給前端會發生什麼事?
- GraphQL:前端自己決定要什麼 → 把決定權交給前端之後,後端要怎麼把那一次查詢變成資料庫操作?這裡藏著一個會把資料庫打爆的陷阱。
- N+1 問題與 DataLoader → 資料層的問題解決了,但這些微服務各自都要處理認證、SSL、限流……前端每接一個新的資料來源就要重新面對一次。
- API Gateway:重複的事只做一次 → 技術上的重複被消掉了,但要出一個功能仍然要跟一堆團隊協調——瓶頸其實已經不在程式碼裡了。
- BFF:前端擁有自己的後端 → 但所有流量仍然全部穿過同一個 API Gateway——它現在同時是壓力來源,也是單點故障。
- 負載平衡:消除單點故障
3. 逐段說明
15 Fullstack Concepts Every Frontend Should Know
1. HTTP:一封信的來回 0:00–3:02
作者從最底層開始:瀏覽器對伺服器發出 GET 請求,伺服器把 index.html 拆成 TCP 封包送回,客戶端再組回一份 HTTP response。他拆開封包給你看:IP header 包住 TCP header 再包住 payload,TCP 多出來的那層換來「不掉包、會照順序到」的保證。最後他把 HTTP response 描述成一封信:第一行狀態碼、接著是 headers(資料的資料)、空行、然後才是內容。


推理因為要先建立一套共同語言,所以作者接著跑完整條路徑:瀏覽器發 GET → 伺服器開始送 index.html → 拆成 TCP 封包 → 客戶端把封包組回一份 HTTP response → 讀 Content-Type 決定怎麼渲染。中間他刻意把封包剖開:IP header 包著 data,而那份 data 裡面又是 TCP header 加 TCP payload;TCP 多花的那塊空間換到的是「不掉包、會照順序到」。最後他把 response 描述成一封信:狀態行、headers(資料的資料)、空行、然後才是內容。
- CTCP:在不可靠的 IP 上用序號、ACK、重傳做到「不掉包、照順序」,代價是延遲與 header→ 畫地圖
- AHTTP response 像一封信:狀態行、headers(資料的資料)、空行、然後才是內容→ 批判類比
- RTCP 不是「不掉包」,是掉了會補:封包還是會掉,靠序號與 ACK 重傳;傳資料前還要三次交握→ 存+回想
AI 補充作者說 TCP「保證不會掉封包」,更精確的說法是:封包在網路上還是會掉,TCP 用序號、ACK 與重傳把掉的補回來,所以在應用層看起來像沒掉過,代價是延遲與那顆 header。他也跳過一步:TCP 連線本身要先三次交握才開始傳資料,這是之後談 TLS「更慢」時的基礎。另外畫面上的 HTTP Response 範例寫的是 403 Forbidden 而旁白講 200,兩者只是同一個結構的不同狀態行,不影響結構本身。
術語:HTTP header
2. DNS:先問到 IP 才能發請求 3:02–5:52
既然請求要送到 IP,那人類記不住 IP 怎麼辦?DNS 就坐在 client 與 server 中間,把 domain 換成 IP。作者示範在瀏覽器 Network 分頁看第一個 document 請求的 Remote Address,就能看到真正連上的 IP 與 443 埠。他再往上追:GoDaddy 只是經銷,域名空間來自 Verisign,最上層由 IANA 協調。


推理因為請求必須有 IP 才送得出去,所以作者把 DNS 畫在 client 與 server 中間:輸入網址或發 fetch 時,瀏覽器先做一次 DNS lookup 拿到 IP,之後才真的發 HTTP 請求。接著他讓你自己驗證這件事——DevTools 第一個 document 請求的 Remote Address 就是那個 IP 與 443 埠。最後他往上追誰在維護這張對應表:GoDaddy 只是經銷,域名空間來自 Verisign,最上層由 IANA 協調。
- CDNS:把網域名稱換成 IP 的分散式查詢系統,每次 fetch 之前都先跑一次(命中快取就不出去)→ 畫地圖
- P在 DevTools 驗證 DNS:第一個 document 請求的 Remote Address 就是查到的 IP 與 443 埠→ 練習
- RDNS 查詢有多層快取:瀏覽器→OS→遞迴解析器→根/TLD/權威;每筆記錄自有 TTL;傳統是明文(所以有 DoH)→ 存+回想
AI 補充作者說「去最近的 DNS server 問」,實際上瀏覽器與作業系統各有一層快取,命中就根本不會出去;沒命中才往遞迴解析器,再逐層問根、TLD 與權威伺服器,而每筆記錄自己也有 TTL。這一點值得記住,因為它和下一段要談的東西是同一種思路:把慢的查詢結果留下來重用。另外 DNS 查詢傳統上是明文的,這也是 DoH(DNS over HTTPS)出現的原因。
術語:domain name
3. IP:機器之間如何找到彼此 5:52–10:04
再往下一層是 IP —— 讓機器在網路上互相定位的協定,封包裡寫著來源與目的 IP,中間的網路設備照著轉送。作者用海底電纜地圖說明「網際網路是實體的」,資訊以光速在光纖裡跑。接著談 IP 位址像不動產一樣稀缺又昂貴(17.x.x.x 整段是 Apple 的),這也是 2000 年前後推出 IPv6 的原因,但因為大量既有設備,至今仍在緩慢遷移。


推理因為那串位址是整條路徑的終點,所以作者往下走到網路層:每個 IP 封包裡都寫著來源與目的位址,中間的網路設備照著轉送。接著他用海底電纜地圖說明這一切跑在實體光纖上,資訊以接近光速前進——所以「快」有物理上限。最後他解釋位址為什麼像不動產:早期被企業與政府大量買走(17 開頭整段是 Apple),剩下的越來越貴,這正是 IPv6 的動機,只是既有設備太多,遷移至今仍在進行。
- AIP 位址像不動產:早期被企業政府整段買走,剩下的越來越貴,所以才有 IPv6→ 批判類比
- RHTTPS 用 443 埠(作者口誤 440);17.x.x.x 整段是 Apple;NAT 讓 IPv4 枯竭被拖延二十幾年→ 存+回想
AI 補充作者提到 HTTPS 埠時口誤說成 440,實際是 443,畫面上的 Remote Address 也寫 443。另外「IPv4 不夠用」在實務上被 NAT 拖延了二十幾年:家裡與公司的所有裝置共用一個對外 IPv4,對內用私有位址,所以你雖然沒感覺,位址其實早就枯竭了。這也解釋了為什麼 IPv6 遷移遲遲沒有急迫性——痛點被一層轉譯吸收掉了。
術語:port
「so expensive around the 2000 people came up with the idea of IPv6」
4. HTTP 快取與 E-Tag 10:04–13:05
既然跨網路拿檔案慢,就把檔案留下來重用,這就是快取;能重用多久叫 TTL,在 HTTP 裡寫成 max-age。max-age 過期後不是直接重抓,而是拿 E-Tag(依內容產生的唯一識別碼)去問伺服器「我這份還是最新的嗎」,是就重設計時器,不是才下載新版。作者示範在 DevTools 看 200 OK (from memory cache)、age、cache-control 與 etag 這幾個 header 怎麼配合。



推理因為跨網路慢,所以作者提出把檔案存在瀏覽器快取重用,並定義「能重用多久」就是 TTL,在 HTTP 裡寫成 max-age。接著他處理過期之後怎麼辦:不是直接重抓,而是帶著 E-Tag(依檔案內容產生的唯一識別碼)去問伺服器「我這份還是最新的嗎」,是就重設計時器,不是才下載新版。最後他用 DevTools 把 200 OK (from memory cache)、age、cache-control、etag 四個線索兜成一個完整故事。
- CHTTP caching:TTL 內直接用本地副本;過期後帶 ETag 問伺服器,沒變就重設計時器,變了才下載→ 畫地圖
- EDevTools 四線索:200 (from memory cache)、age、max-age、etag——age 比 max-age 就知道過期沒→ 存+演練
- P讀一個靜態資源的快取故事:找 status、age、cache-control、etag 四個欄位兜成一句話→ 練習
AI 補充補一個作者沒說清楚的關鍵:age 是「這份資料在快取裡待了多久」,由中間的 CDN 回報,所以判斷是否過期就是拿 age 去比 max-age——畫面上 age 672803 對 max-age 31536000,還早得很。畫面裡那個 immutable 指令的意思是「這個 URL 的內容永遠不會變」,連重新整理時的驗證請求都可以省掉,這正是前端 build 工具在檔名裡塞內容雜湊的理由:檔案變了就換 URL,於是快取可以設到一年。
術語:HTTP caching
「Now that number it's in milliseconds.」
5. TLS:為什麼要換兩種加密 13:05–17:38
HTTP 是明文,所以有人可以坐在中間攔截你的 header 與付款資料,這就是 man-in-the-middle 攻擊,在公共 Wi-Fi 特別容易。1996 年 Netscape 提出 HTTPS:先用非對稱加密完成交握——瀏覽器取得憑證(公鑰)、向憑證機構驗證它確實屬於這個網域、產生一把密鑰用憑證加密送回、伺服器用私鑰解開。之後改用對稱加密傳真正的資料,因為非對稱慢又貴,對稱快但需要雙方共有一個祕密,而那個祕密正是交握換來的。



推理因為明文可被攔截,所以作者先描述威脅本身:有人坐在你與伺服器中間(公共 Wi-Fi 特別容易),把 IP 封包還原成 HTTP,就能讀到你的 authorization header 甚至信用卡資料。這在只看部落格的年代無所謂,電子商務出現後才變成災難,於是 Netscape 提出 HTTPS。接著他拆交握:瀏覽器取得憑證(公鑰)→ 向憑證機構驗證它確實屬於這個網域 → 產生一把 secret key、用憑證加密後送回 → 伺服器用私鑰解開。之後改走對稱加密,因為非對稱慢又貴、對稱快但需要一個雙方共有的祕密,而那個祕密正是交握換來的。
- CTLS:先用非對稱加密交換一把 secret key(憑證證明公鑰屬於這個網域),之後改走快的對稱加密→ 畫地圖
- R憑證的作用不是加密資料,是「證明這把公鑰屬於這個網域」;真正保護流量的是對稱金鑰→ 存+回想
- E作者說交握「至少五個來回」是 TLS 1.2 以前的粗估;TLS 1.3 完整交握 1-RTT、重連 0-RTT→ 存+演練
AI 補充有個常見誤解值得說清楚:憑證的作用不是加密資料,而是「證明這把公鑰屬於這個網域」;真正保護後續流量的是那把對稱金鑰。所以 HTTPS 同時給你兩件事——機密性來自加密,身分可信來自憑證鏈,缺一個都不算安全(自簽憑證加密照做,但沒人替它背書)。另外作者說交握「至少五個網路來回」是 TLS 1.2 以前(含 TCP 三次交握)的粗估;TLS 1.3 已把完整交握壓到 1-RTT、重連還能 0-RTT,所以今天 HTTPS 的額外延遲遠比影片描述的小。
術語:man-in-the-middle attackcertificate authority
「in order to prevent this in 1996 which is basically 30 years ago Netscape」
6. Polling:最土但最簡單的即時 17:38–19:26
HTTP 是一來一回的信件,那想要「狀態一變就知道」怎麼辦?最簡單的是 polling:客戶端每隔固定間隔(polling interval)打同一個端點,直到狀態改變為止。作者用付款狀態當例子,程式碼就是 fetch 包在 setInterval 裡,拿到想要的答案就 clearInterval。使用者不必手動重新整理,這是最早的「假即時」。


推理因為 HTTP 只能由客戶端發動,所以最簡單的即時就是週期性重問。作者用付款狀態當例子:瀏覽器每 3 秒打一次 /payments/:id/status,伺服器回 pending 就繼續,回 completed 就 clearInterval 停下來。程式碼只是 fetch 包在 setInterval 裡,完全用瀏覽器原生 API,換到的是使用者不必再自己按重新整理——在那之前的做法真的就是「十秒後請重整頁面」。
AI 補充作者的虛擬碼有個在 React 裡會出事的地方:setInterval 直接寫在元件本體,每次 render 都會多開一個計時器,正確做法是放進 useEffect 並在 cleanup 裡 clearInterval。另外固定間隔在伺服器忙碌時會反過來放大壓力,生產環境通常改用指數退避——每次沒結果就把間隔加倍並設上限,讓等得越久問得越稀疏。
7. WebSocket:改成打電話 19:26–20:53
polling 在資料量大或聊天這種場景就不夠用了,因為每則訊息都要重新寄一封信。WebSocket 是打電話:開一條雙向通道,兩邊都能隨時送訊息,不必為每則訊息重新建立請求。作者強調實作其實很簡單,瀏覽器端 new WebSocket、Node 端監聽連線並回訊息,現代聊天與社群的即時推播就是靠這個。



推理因為每則訊息都重新寄一封信太貴,所以作者把 WebSocket 比成打電話:開一條雙向通道之後,兩邊都能隨時送訊息,不必為每則訊息重新協商。他刻意把 client 與 server 的程式碼並排,讓你看到 new WebSocket("ws://localhost:8080") 與 wss.on("connection", ...) 其實都很短,門檻沒有想像中高。最後用 user B → server → user A 的圖收尾:現代聊天與社群的即時推播,本質上就是這張圖。
- CWebSocket:單一 TCP 連線上的全雙工通道,兩邊隨時能送;從 HTTP Upgrade 請求開始所以沿用 443 與 TLS→ 畫地圖
- AWebSocket 像打電話、HTTP 像寄信:開一條通道後不必每則訊息重新協商→ 批判類比
AI 補充補一步作者跳過的:WebSocket 連線其實是從一個普通的 HTTP 請求開始的,帶著 Upgrade: websocket 標頭請伺服器切換協定,所以它能沿用既有的 80/443 埠與 TLS(wss://),不必另外開防火牆。也因為連線是長期存在的,伺服器端得自己處理心跳偵測、斷線重連,以及「同一個使用者開了三個分頁」的狀態管理——這些才是規模化時真正的成本,而不是那幾行連線程式碼。
8. SSE:AI 應用的串流來源 20:53–22:06
第三種即時是 Server-Sent Events:客戶端只發一次請求並訂閱,之後由伺服器單向持續推事件。這正好對上 LLM 一個 token 一個 token 生成的模式,所以現代 AI 應用幾乎都用它。作者示範打開 ChatGPT 的 Network,找到 conversation 端點的 Event Stream,就能看到畫面上的字是怎麼一則一則被推過來的。


推理因為只需要單向,所以作者介紹 Server-Sent Events:客戶端對 /conversation/:id 發一次請求並訂閱,之後伺服器就持續往同一條連線推事件。他馬上把它接到今天最熱的場景——LLM 一次生成一個 token,正好是單向串流,所以現代 AI 應用幾乎都用 SSE。打開 ChatGPT 的 DevTools 看 conversation 端點的 EventStream,那一排 delta 事件就是畫面上逐字浮現的字,證明看起來很新的介面底層是很老的瀏覽器 API。
- CServer-Sent Events:訂閱一次後伺服器沿同一條 HTTP 連線單向推文字事件,自動帶 Last-Event-ID 重連→ 畫地圖
- EChatGPT 的 conversation 端點是 EventStream,一排 delta 事件就是畫面逐字浮現的字→ 存+演練
- R三種即時的梯度:polling 最簡單最浪費、SSE 單向且自動重連、WebSocket 雙向但要自己管狀態→ 存+回想
AI 補充值得補的是 SSE 的兩個實用細節:它走純文字格式、自帶 id 與 retry 欄位,斷線後瀏覽器會自動帶 Last-Event-ID 續傳,這是 WebSocket 沒有的內建行為;代價是只能傳文字、只能單向,而且在 HTTP/1.1 下受同網域連線數上限拖累(HTTP/2 之後不再是問題)。至此三種即時方式構成一個清楚的梯度:輪詢最簡單但最浪費、SSE 單向且自動重連、WebSocket 雙向但要自己管狀態。
術語:EventSource
9. RPC / tRPC 與 MCP 22:06–24:31
接著換一種思路:不是取資源,而是直接叫另一台電腦執行一個函式,這就是 RPC,比網際網路還老,最近因為 TypeScript 以 tRPC 之姿復活,好處是 client 與 server 之間有型別安全。但作者也給出它沒有普及的原因:client 與 server 高度耦合,伺服器程式碼會變得很有意見、很快變成義大利麵。有趣的是 RPC 在 AI 時代以 MCP 回來了——AI 幫你訂會議就是透過 MCP(走較輕量的 JSON-RPC)呼叫外部系統的函式。



推理因為 HTTP 只規範傳輸、不規範請求的形狀,所以作者拿出比網際網路還老的 RPC:客戶端直接叫伺服器執行某個函式並取回結果。tRPC 是它在 TypeScript 生態的復活版,賣點是兩端共用型別、改壞了編譯期就會抓到。但他立刻給出它沒有普及的理由:這種寫法把 client 與 server 綁死,伺服器程式碼必須知道前端在做什麼,久了就是義大利麵,所以他建議要學就先學 REST。最後他指出 RPC 在 AI 時代以 MCP 回來了——AI 幫你訂會議,底層就是走 JSON-RPC 呼叫外部系統提供的函式。
AI 補充作者說 MCP「大概七個月前才出來」是錄影當下的說法,時效性見下方勘誤。另外有兩件常被混談的事值得分開:tRPC 是 TypeScript 專用、靠型別推導做到端到端型別安全的函式庫,它連線上格式都沒有規範;JSON-RPC 則是語言無關的線上協定,MCP 用的是後者。作者說的「RPC 讓程式碼耦合」也要分層看——真正的耦合來自「函式名稱即 API」這個設計,而不是 RPC 這個傳輸方式本身。
「it was only probably 7 months ago. So, this stuff is pretty recent.」
10. REST:把 HTTP 標準化 24:31–28:51
HTTP 只規範傳輸,請求本身可以隨便自由發揮,結果每個 API 都要重新學一次。REST 的做法是把實體當成資源,用複數名詞的 URI(/products、/users)加上 HTTP 動詞形成統一介面,還可以加 query parameter 做分頁與搜尋,巢狀成 /products/:id/prices。作者用電商領域模型示範怎麼把 product、price、rating、review 對應成端點,並整理出 CRUD ↔ POST/GET/PUT 或 PATCH/DELETE 的對照(PUT 具冪等性,通常比 PATCH 好用)。實作良好時,你不看文件就知道這個 API 提供什麼。



推理因為人人自由發揮會讓每次串接都要重學一次,所以作者用「把實體當成資源」重新組織 HTTP:URI 用複數名詞(/products、/users),操作用 HTTP 動詞,篩選與分頁用 query parameter,關聯用巢狀路徑 /products/:id/prices。他先從電商領域模型出發——Product 底下的 Price、Rating、DeliveryTime 都是複合型別而不只是數字——再把 CRUD 對到 POST / GET / PUT 或 PATCH / DELETE,並指出 PUT 具冪等性、通常比 PATCH 好推理。結論是:實作得好的 API,你不看文件就知道它提供什麼。
- CREST:把實體當資源,URI 用複數名詞、操作用 HTTP 動詞、篩選分頁用 query、關聯用巢狀路徑→ 畫地圖
- P替一個實體設計 REST 端點:複數名詞、CRUD 對 POST/GET/PUT/DELETE、關聯巢狀、篩選走 query→ 練習
- Ridempotency:PUT 送一次和十次最終狀態一樣;PATCH「數量加一」重送會多加——客戶端自動重試時是正確性問題→ 存+回想
AI 補充把作者一句話帶過的冪等性說清楚:同一個 PUT 送一次和送十次,伺服器的最終狀態一樣;PATCH 若是「數量加一」這種相對操作就不具此性質,重送會多加。這在網路不穩、客戶端會自動重試時是實際的正確性問題,也是除了 POST 之外還需要其他動詞的理由。順帶一提,字幕把 idempotent 誤聽成 important,讀 transcript 時別被誤導。
11. Under-fetch 與 Over-fetch 28:51–30:23
REST 在單一客戶端時很好,但同時要服務桌面與行動端就出問題。桌面畫面大、資料多,一個視圖得打十幾個端點才湊得齊,這叫 under-fetching;行動端畫面小、流量有限,若沿用桌面端點就會拿回一堆不顯示的 JSON,這叫 over-fetching。兩個問題方向相反,卻都源自「端點的形狀由後端決定,前端只能將就」。


推理因為端點的形狀由後端決定,所以每種客戶端只能將就。桌面畫面大、清單與詳情混在一起,一個視圖要打十幾個端點才湊得齊資料,這是 under-fetching;手機畫面小、流量與電量都有限,沿用桌面端點就會拿回一堆根本不會顯示的 JSON,這是 over-fetching。作者刻意讓兩張圖並排:同一組端點,一邊嫌不夠、一邊嫌太多。
AI 補充這兩個詞常被當成「請求太多」與「資料太大」的別名,但它們真正的共同根源是控制權的位置——欄位由誰決定。在 REST 裡的常見解法是替每個畫面另開一個端點(/products/mobile-list),短期有效,代價是端點數量爆炸、而且已經不再是 RESTful 設計;作者說「今天的 REST API 其實都不 RESTful」指的就是這種折衷。認清楚問題是控制權而不是效能,才會理解下一步為什麼要換一整層。
12. GraphQL:前端自己決定要什麼 30:23–32:13
2013 年 Facebook 為了同一組問題做出 GraphQL 並開源:一個資料層,讓前端用一次查詢跨多個資源、明確指定要哪些欄位,同時解掉 under-fetching 與 over-fetching。桌面把十幾個 REST 請求收斂成一次查詢,行動端只要改查詢就拿更少資料。附帶好處是 GraphQL 本身有型別,前端不必額外加工具就能寫型別安全的程式碼。


推理因為那兩個問題同源,所以一個解法就能同時解掉:GraphQL 是一層資料層,前端用一次查詢跨多個資源、並明確列出要哪些欄位。桌面把十幾個 REST 請求收斂成一次查詢,under-fetching 消失;手機只要改查詢就拿更少資料,over-fetching 消失。附帶好處是 schema 本身有型別,前端不必另外接工具就能寫型別安全的程式碼——REST 要做到同一件事得再加一層 OpenAPI 之類的工具鏈。作者也指出這才是它真正發光的場景:多種客戶端各要各的資料。
- CGraphQL:前端一次查詢跨多個資源並明確列出欄位,同時解掉 under/over-fetching;schema 自帶型別→ 畫地圖
- RGraphQL 的代價:對同一個 /graphql 發 POST 所以不能以 URL 當快取鍵;伺服器要限制查詢深度與複雜度→ 存+回想
AI 補充需要補上的是代價。把查詢形狀交給前端,等於讓「會有哪些查詢被送出」變成執行期才知道:快取不再能像 REST 那樣以 URL 為鍵(GraphQL 通常是對同一個 /graphql 端點發 POST),伺服器也必須加上查詢深度與複雜度限制,否則一個惡意的巢狀查詢就能拖垮服務。控制權的轉移從來不是免費的,這一點在下一段會用更具體的方式現形。
13. N+1 問題與 DataLoader 32:13–34:17
但 GraphQL 帶來新問題:查 24 個產品時,伺服器先查清單再逐一查細節,變成 24+1 次 SQL,客戶端一多就把資料庫打爆,效能反而比 REST 差。解法是用 DataLoader 這類函式庫做 batching:把同一輪的 id 收集起來合成一次較大的查詢再送出。作者強調重點不是實作細節,而是「凡是要聚合多筆查詢,就必須有一層批次化的機制」。


推理因為一次 GraphQL 查詢可能展開成多層巢狀,所以 resolver 很容易先查一次清單(1),再為每一筆各查一次細節(N):24 個產品就變成 25 次 SQL。作者強調這時的效能會比原本的 REST 還差,等於白換一套架構。解法是用 DataLoader 這類函式庫做 batching:把同一輪收集到的 id 合併成一次較大的查詢再送出。他刻意不講實作細節,而是留下一條通則——凡是要聚合多筆查詢,就必須有一層批次化的機制。
- EN+1:24 個產品的 GraphQL 查詢展開成 25 次 SQL,比原本的 REST 還慢;DataLoader 批次成一次 WHERE id IN→ 存+演練
- RDataLoader 以請求為單位:每個請求 new 一個,跨請求共用會讓使用者看到別人的舊資料→ 存+回想
AI 補充補上作者跳過的機制:DataLoader 利用事件迴圈的一個 tick 把這一輪所有的 .load(id) 收集起來,在 tick 結束時合併成一次 SELECT ... WHERE id IN (...),並且在同一次請求內對相同 id 去重與快取。也因為它「以請求為單位」,正確用法是每個請求 new 一個新的 DataLoader,跨請求共用會讓使用者看到別人的舊資料——這是實務上最常踩的雷。順帶一提,N+1 不是 GraphQL 的專利,ORM 的 lazy loading 產生的是一模一樣的問題。
術語:N+1 problem
14. API Gateway:重複的事只做一次 34:17–37:20
視角拉到架構層:微服務各自實作認證、SSL、rate limiting、快取這些重複的邊緣功能,非常浪費。API Gateway 是一種 reverse proxy——proxy 代表客戶端(例如 VPN),reverse proxy 代表伺服器——它坐在服務前面,把邊緣功能集中做一次再把請求轉給對應微服務。額外好處是憑證只需要買一張,Gateway 之後在私有雲內走 HTTP 就好,省掉每次至少五個來回的 TLS 交握。



推理因為每個微服務都得自己實作 rate limiter、認證中介層與快取,而這些邏輯彼此幾乎一樣,所以作者引入 API Gateway——一種 reverse proxy。他先把兩個方向分清楚:proxy 代表客戶端(例如 VPN,伺服器以為請求來自代理),reverse proxy 代表伺服器(負載平衡器、API Gateway,客戶端以為它就是伺服器)。Gateway 坐在服務前面,把這些 edge function 集中做一次,再把請求轉給對應的微服務。附帶好處是憑證只要買一張,Gateway 之後在 VPC 內走 HTTP 就好,省掉每次連線的 TLS 交握。他也提醒這東西可以在雲上一鍵買到,也可以用 nginx 加 Docker 自己搭。
- CAPI Gateway:坐在所有微服務前的 reverse proxy,把認證、限流、快取、SSL 終結這些 edge function 集中做一次→ 畫地圖
- Aproxy 代表客戶端(VPN,伺服器以為請求來自代理);reverse proxy 代表伺服器(LB、Gateway,客戶端以為它就是伺服器)→ 批判類比
- R「Gateway 之後內網走 HTTP」的前提是信任 VPC 內所有東西;零信任架構要求服務間仍用 mTLS→ 存+回想
AI 補充「內網走 HTTP 沒關係」這個結論值得標註前提:它成立的條件是你信任 VPC 內的所有東西。零信任(zero trust)架構的主流建議正好相反——服務之間仍應以 mTLS 互相驗證,因為一旦有一台被攻陷,平坦的內網就無險可守。在小團隊或單一雲帳號裡作者的做法沒問題,但這是個有前提的取捨,不是普遍原則。另外 Gateway 集中做認證也意味著它成為新的攻擊面與設定錯誤的單一來源,這在下一段會以另一種形式回來。
「the TLS handshake which takes at least five round trips to the network」
15. BFF:前端擁有自己的後端 37:20–40:21
技術問題解決了,組織問題還在:前端要出一個功能,得同時和平台團隊、產品團隊、物流團隊協調,各自有各自的 backlog,作者待過有 300 個微服務的公司。BFF(Backend For Frontend)是另一個 reverse proxy,但為特定前端而建、且由前端團隊自己擁有,通常用 GraphQL 做成專屬資料層。這正是前端要懂全端的原因——BFF 是前端工程師自己要擴充的;行動端也能有自己的 BFF,架構因此在「人」的層面可擴展。



推理因為每個微服務屬於不同團隊、各有各的 backlog 與產品經理,前端要出一個功能得同時協調平台團隊、產品團隊、物流團隊——作者說他待過有 300 個微服務的公司,光是實作一個功能就足以令人抓狂。所以他引入 BFF:同樣是 reverse proxy,但為特定前端而建、而且由前端團隊自己擁有,通常用 GraphQL 做成專屬資料層。這也是整支影片的落點——前端要懂全端,正是因為 BFF 本來就該由前端工程師自己擴充。手機端可以有自己的 Mobile BFF,於是架構在「人」的維度上終於可以擴展。
- CBackend For Frontend:為特定前端而建、由前端團隊自己擁有的聚合層,只做聚合與裁剪,不塞商業規則→ 畫地圖
- E作者待過 300 個微服務的公司:出一個功能要同時協調平台、產品、物流三個團隊的 backlog→ 存+演練
AI 補充值得補的是 BFF 的邊界。它該做的是聚合與裁剪:呼叫多個微服務、拼成這個畫面需要的形狀。它不該做的是塞進商業規則——一旦訂價或庫存邏輯寫進 BFF,你就把剛拆開的耦合又搬回來了,而且是搬到前端團隊身上。另一個常被低估的成本是:每多一個 BFF 就多一個要部署、監控、值班的服務,而承擔的人就是原本只寫前端的那個團隊。這是自主權的價碼,不是附贈品。
16. 負載平衡:消除單點故障 40:21–41:57
但所有流量都經過 API Gateway,它同時變成壓力來源與單點故障。做法是把單一實例換成一群相同的實例加一台負載平衡器(LB),依演算法分流,某一台掛掉整體也不會倒,還能吃下更大的流量。最常見的演算法是 round-robin 輪流分派,另一種 least connections 則把流量送給連線數最少的實例,等於讓分流跟著實例的實際負載走。


推理因為單一實例既有容量上限也有故障風險,所以作者把它換成一組相同的實例加一台負載平衡器:LB 依演算法把流量分給各實例,某一台掛掉整體仍然活著,總吞吐量也跟著堆疊。最常見的演算法是 round-robin(依序輪流),另一種 least connections 則把流量送給當下連線數最少的實例,等於讓分流跟著實例的實際負載走。講到這裡,整條路徑從第一個 TCP 封包一路走到了一整套可擴展的架構,作者也就收尾了。
AI 補充兩件作者沒說、但你一動手就會遇到的事。第一,能這樣水平擴展的前提是實例無狀態:session 一旦存在記憶體裡,使用者被分到另一台就等於登出,於是只能改用 sticky session(把人綁在同一台,代價是分流不均)或把 session 外置到 Redis。第二,LB 自己也是單點,雲上的做法是交給託管服務(跨可用區部署,再由 DNS 層做一次分散),否則你只是把單點往前挪了一格。健康檢查則是這一切的前提——LB 必須先知道哪台掛了,才有辦法不把流量送過去。
4. 總結
整支影片是一條由缺口推動的直線。HTTP 建立了「一問一答」的基本模型,但請求需要 IP,於是有 DNS;IP 本身受限於實體線路與位址稀缺,於是往下看見封包與 IPv6。既然跨網路有成本,就用快取(max-age + ETag)省掉那趟路;既然連線是明文,就用 TLS 把它包起來,並在非對稱與對稱加密之間換手。到這裡「安全地取回一份資源」完整了,但 HTTP 只能由客戶端發問,於是 polling → WebSocket → SSE 構成一個由土到精緻的即時通訊梯度,而 SSE 正好是今天所有 LLM 串流介面的底層。接著焦點從「怎麼傳」換到「請求長什麼樣」:RPC 讓請求像呼叫函式卻把兩端綁死(它今天以 MCP 的形式回到 AI 場景),REST 用資源與動詞換來可預測性,卻在同時服務桌面與手機時裂成 under-fetching 與 over-fetching;GraphQL 把欄位的決定權交給前端而解掉兩者,代價是 N+1,再由 DataLoader 的批次化補上。最後兩層離開程式碼:API Gateway 把各微服務重複的認證、限流、SSL 抽出來做一次;BFF 讓前端團隊擁有自己的資料層,繞開跨團隊協調這個真正的瓶頸;而全部流量集中之後產生的單點故障,由負載平衡收尾。所以「前端要懂全端」在這支影片裡不是口號,而是一個結構性的結論:BFF 本來就該由前端自己擴充,而你得看得懂它前後每一層。
勘誤總整理
確定錯誤/已過時見仁見智(取決於版本或情境)
| 段落 | 原話(transcript 逐字) | 說明 |
|---|---|---|
| 4. HTTP 快取與 E-Tag 12:29 |
「Now that number it's in milliseconds.」 | Cache-Control 的 max-age 單位是「秒」,不是毫秒。畫面上的 max-age=31536000 當成秒剛好是一年(也是規範建議的上限用法);若真是毫秒就只有約 8.7 小時,跟旁邊 age=672803 已經超過七天卻仍算新鮮的事實直接矛盾。 依據: RFC 9111 §5.2.2.1 max-age:delta-seconds |
| 3. IP:機器之間如何找到彼此 9:26 |
「so expensive around the 2000 people came up with the idea of IPv6」 | 把 IPv6 的提出時間推晚了大約五年。IPv6 的第一份規格 RFC 1883 在 1995 年就發布,1998 年由 RFC 2460 定稿,並非「2000 年左右才有這個想法」。作者要表達的「因為位址枯竭才做 IPv6」這個因果本身是對的。 依據: RFC 1883 (1995-12)、RFC 2460 (1998-12) |
| 5. TLS:為什麼要換兩種加密 14:14 |
「in order to prevent this in 1996 which is basically 30 years ago Netscape」 | Netscape 的 SSL 2.0 在 1995 年就隨 Navigator 出貨(SSL 1.0 從未公開),SSL 3.0 才是 1996;標準化並改名為 TLS 1.0 則要到 1999 年的 RFC 2246。說「1996 年 Netscape 提出 HTTPS」大方向沒錯,時間點略晚一年。 依據: SSL 2.0 (1995)、SSL 3.0 (1996)、RFC 2246 TLS 1.0 (1999) |
| 9. RPC / tRPC 與 MCP 24:26 |
「it was only probably 7 months ago. So, this stuff is pretty recent.」 | 這是錄影當下的相對時間,現在讀會誤導。MCP 由 Anthropic 在 2024 年 11 月發布並開源,至今已超過一年,且已被多家 AI 廠商與 IDE 採用,不再是「剛出來七個月」的實驗性東西。 依據: Model Context Protocol 公開發布:2024-11 |
| 14. API Gateway:重複的事只做一次 36:39 |
「the TLS handshake which takes at least five round trips to the network」 | 這是 TLS 1.2 以前(含 TCP 三次交握)的粗估。TLS 1.3 已把完整交握壓到 1-RTT,對曾連過的伺服器還能 0-RTT 續傳。作者用這個數字論證「Gateway 之後走 HTTP 比較快」,結論方向仍成立,但省下的幅度被高估了。 依據: RFC 8446 (TLS 1.3, 2018) |
5. 推薦三個下一步
1. 往下挖深:TLS 交握與 HTTP/2、HTTP/3 的實際成本
影片用「至少五個網路來回」論證 Gateway 之後可以走 HTTP,但這是 TLS 1.2 以前的數字。搞清楚 TLS 1.3 的 1-RTT/0-RTT,以及 HTTP/2 多工與 HTTP/3 走 QUIC 之後連線成本的變化,才能判斷這類架構取捨今天還成不成立。
YouTube 搜尋:TLS 1.3 handshake explained HTTP/3 QUIC vs HTTP/2 TLS handshake round trips 0-RTT
2. 往旁邊對照:GraphQL 之外的選項與它的真實代價
影片把 GraphQL 當成 under/over-fetching 的解答,但沒談它在快取、查詢複雜度攻擊與伺服器複雜度上的代價,也沒提 tRPC 之外的同類方案。把 REST + OpenAPI、GraphQL、gRPC-Web 放在一起比較,才知道什麼時候不該用 GraphQL。
YouTube 搜尋:GraphQL vs REST tradeoffs GraphQL caching problems when not to use GraphQL
3. 往上應用:自己動手做一個 BFF
BFF 是整支影片的落點,也是最需要動手才會懂的一段——聚合幾個公開 API、決定要不要用 GraphQL、處理部署與監控,才會體會到作者說的「自主權有價碼」。
YouTube 搜尋:Backend for Frontend pattern tutorial BFF pattern Node.js GraphQL BFF architecture
- 接著看 →Real Frontend System Design (from a Senior Engineer) · TLS、快取、REST/GraphQL、Gateway、BFF 在這站建立,那站直接當零件用
- 接著看 →Frontend System Design Explained w/ Senior Engineer (Microfrontends, Monorepo, MCP UI, Reactjs) · API Gateway、BFF、SSE、WebSocket 等十個共同術語,那站不再解釋
- 接著看 →Real Senior Frontend System Design Interview 2026 (AI Coding Included) · SSE/WebSocket/polling 的機制差別在這站建立,那站直接拿來選型
- 相關 —Every Frontend Architecture Pattern Explained in 23 Minutes · 共用 GraphQL 與 N+1:一站從協定往上推,一站從架構演化往下切
- 相關 —15 Frontend Concepts Every Senior Dev Has Mastered · 共用 ETag、TTL:一站講快取在協定裡怎麼運作,一站講瀏覽器端效能
- 相關 —How Senior Frontend Engineers Think in System Design Interviews · 共用 WebSocket/polling:一站給協定機制,一站給沒答案時的決策方法
- 相關 —Top 15 Frontend Interview Questions for 2026 (wa/ Senior Engineer) · 共用 SSE/WebSocket/max-age:一站解釋機制,一站是面試速答清單
- 接著看 ←9 JavaScript Concepts That Got Me To Senior Dev · fetch 與 async/await 在那站建立,這站所有範例都以它為起點
- 相關 —How Frontend Engineers can master the Full-stack · 同一批全端概念,一個從封包往上、一個從分層往下
- 接著看 →Authorization vs Authentication - Whats the Difference? | Developer Concepts Explained · 講完 HTTP 與 API 之後,再看誰能呼叫哪一個
- 相關 —Cross-Site Request Forgery (CSRF) Explained · HTTP 方法、API 與 endpoint 在那站建立,這站直接拿來拆解一個偽造請求
- 接著看 →How to scale WebSockets to millions of connections · WebSocket、round robin、單點故障在那站點名,這站把它們拉成一條擴展推理
- 接著看 →Keep Those WebSocket Connections Alive! · 那站分辨 polling/WebSocket/SSE,這站在 WebSocket 上動手寫 heartbeat
- 接著看 →How Web Sockets work | Deep Dive · 那站把 WebSocket 與 HTTP、TCP、SSE 並列點名,這站把 handshake 與 frame 拆到位元
- 接著看 →WebSockets Aren’t as Reliable as You Think.. Here's Why · 那站帶過 WebSocket、EventSource、round robin 三個概念,這站把它們組成一套可靠性設計