前端系統設計:從團隊怎麼分工,推到畫面怎麼渲染
文字解析 · 1 支影片 · 產生於 2026-10-01 00:54
章節(18)
1. Outline
- 起點 · Frontend System Design Explained w/ Senior Engineer (Microfrontends, Monorepo, MCP UI, Reactjs)
以「AI 讓實作變快、驗證變慢」為樞紐,把前端系統設計串成一條連續推理:先用 Conway's law 把團隊拆成垂直切片(微前端 + 微服務),再逐一償還切分欠下的債(gateway、BFF、負載平衡、容器、CDN、design system、MCP、monorepo),最後轉向體感層(Core Web Vitals、code splitting、渲染策略、SSE)。
2. YouTuber 的思維推導
Frontend System Design Explained w/ Senior Engineer (Microfrontends, Monorepo, MCP UI, Reactjs)
theSeniorDev · 38m02s · 字幕 en · vision=on (這是一支全程對著白板/架構圖講解的影片,transcript 裡「looking at our client-server model」「a typical microservice blueprint will look like something like this」「as you see there, it can even render a map」等指示語遠超過三次,圖本身承載了推理的主要結構,所以 vision 開啟。) · YouTube
預估 vs 實際耗時
| 階段 | 預估 | 實際 |
|---|---|---|
| fetch | 6s | 2s |
| segment | 1m46s | 5m10s |
| shot | 1m21s | 9s |
| analyze | 16m15s | 19m10s |
| render | 5s | – |
作者的推導有一條很清楚的主軸:**先問誰在工作,再問系統長什麼樣,最後才問畫面怎麼畫。**
他從一個時代前提起手——AI 已經會寫前端 code,所以「會實作」不再稀缺。但他沒有停在這個老生常談上,而是丟出一個更精準的觀察:coding agent 把實作時間壓到接近零,卻**推高了驗證時間**。這句話是整支影片的樞紐:既然瓶頸從「寫」搬到了「確認寫對了沒」,那麼好的架構就不再是「優雅」或「可擴展」,而是**讓每一次變更都容易被驗證**。之後每一個技術選擇,他都會回到這個標準上重新評價一次。
有了標準,他開始拆。第一刀從人下手:團隊四十個人、stand-up 開一個半小時,這種結構從開發角度就無法 scale。Conway's law 提供了機制——想要小而獨立的團隊,就得有小而獨立的系統切片。於是後端拆成 microservices,前端拆成 microfrontends 加一個 shell,兩邊對接成 **vertical slice**:一個團隊完整擁有的縱向路徑。這是全片的結構高點,也是他職涯建議的來源——要成為能吃下整條切片的人。
接下來的每一段,其實都是在**還切分欠下的債**。切開了,跨網路請求的雜事重複了 → API gateway 把 edge functions 收成一次。gateway 沒解決資料形狀與擁有權 → BFF 讓前端團隊自己擁有後端。每一層都是單機 → load balancing。技術棧太雜、部署變噩夢 → Docker 與 orchestration。機房離使用者太遠 → CDN。團隊各自出貨、畫面開始不一樣 → design system。design system 躺在程式庫裡沒接上 AI → design-to-code MCP。程式碼散在上千個 repo、agent 看不見全貌 → monorepo。這一長串看似鬆散的名詞,其實是同一筆帳的九期分期付款。
在傳統議題收尾之後,他插入 **MCP UI** 作為前沿:當 LLM 不只回文字而是回 UI 元件,前端要怎麼接。然後才轉向最後一個維度——**體感**。這裡他換了一套語言:Core Web Vitals 把「好慢」拆成三個可歸因的數字,critical rendering path 說明數字為什麼難看,code splitting 處理「送太多 JavaScript」,渲染策略處理「畫面該在哪裡生成」,最後 server-sent events 補上請求—回應模型涵蓋不到的即時推送——而它的選擇理由,正好又回到他一貫的方法:**先看需求的形狀(LLM 的通訊是不對稱的),再選技術。**
把這條鏈拉直來看,他真正想教的其實不是二十個名詞,而是一種提問順序:這件事卡住了誰?成本落在哪一邊?有沒有一個切法能讓變更的爆炸半徑變小、讓驗證變快?學會這個順序,名詞會自己長出來。
推理鏈:每段留給下一段的線索
每一列是一段,箭頭後的字是這段留給下一段的線索。點段落標題跳到該段。
- 開場:為什麼前端要學系統設計 → 留下一個還沒回答的問題:既然要「拆」,那第一刀該從哪裡下?作者選擇不從前端開始,而是先回到後端的 microservices——因為要先看懂拆的動機。
- 從單體到微服務:團隊撐不住了 → 拆分的動機成立了,但還缺一個原則:憑什麼相信「組織」和「架構」會互相牽動?下一段作者用 Conway's law 補上這個環節,同時揭露 AI 帶來的真正瓶頸。
- AI 的真正瓶頸:verification time → 後端切好了、組織也對齊了,但前端仍是一整塊——這個不對稱就是下一段的起點。
- 前端還是單體:微前端與 shell → 前端切開了、shell 也就位了,但切開的微前端要怎麼跟切開的微服務對上?下一段用 vertical slice 把兩邊接起來。
- 垂直切片、職涯兩極與 blast radius → 切片之間要靠網路溝通,而每個請求都得處理認證、快取、限流這些重複的雜事——這個新增的成本就是下一段要解決的問題。
- API Gateway:把 edge functions 收成一次 → 留下一個 gateway 解不掉的缺口:它把橫切關注點收攏了,卻沒有改變資料的形狀,client 仍要對一堆長相不同的 API 各打各的;更麻煩的是,前端要一個新欄位還是得去別的團隊 backlog 排隊。
- BFF:前端團隊自己擁有後端 → 架構越接越長:client → gateway → BFF → 微服務。但這條鏈上的每一台 server 都是單機,使用者一多就撐不住——這個規模問題留給下一段。
- Load balancing:單台 server 的天花板 → 要開出很多個一模一樣的 instance,就得先能把應用程式打包成「到哪台機器都跑得起來」的東西——這正是下一段 Docker 要解的問題。
- 容器化:Docker 與 orchestration → 部署與擴展都自動化了,但無論開幾台機器,資料仍然要從機房飛到使用者面前——這段物理距離是下一段要處理的問題。
- CDN:跟光速借時間 → 效能與部署都處理完了,接下來要回頭面對切分留下的另一筆帳:各自獨立的團隊,做出來的畫面正在慢慢長得不一樣。
- Design system:對抗視覺分歧 → design system 有了,但它還躺在程式庫裡等人手動使用;下一段要把它接進 AI 的工作流,讓 agent 直接讀得到設計本身。
- Design-to-code MCP 與 Atomic CSS → 設計、元件、AI 工作流都接上了,但這些微前端與 design system 還散在各自的 repo 裡,agent 一次只看得到其中一個——這個 context 的邊界問題留給下一段。
- Monorepo:給 agent 看得見邊界 → 到這裡傳統的前端系統設計已經完整了;下一段作者轉向一個全新的東西——當 LLM 不只回文字、而是直接回 UI 元件時,前端架構要怎麼接。
- MCP UI:讓 LLM 回你元件而不只是字 → 不管介面怎麼變,畫面終究要被畫出來、而且要夠快——下一段回到效能,處理「快不快」到底怎麼量。
- Core Web Vitals 與關鍵渲染路徑 → 既然 LCP 的頭號兇手是「送了太多 JavaScript」,那下一步自然是問:能不能只送這一頁真正需要的那些?
- Code splitting 與 lazy loading → JavaScript 送得剛剛好了,但如果第一個畫面本身就得等 JavaScript 跑完才出現呢?下一段回到更根本的問題:畫面到底該在哪裡被渲染。
- 渲染策略:CSR、SSG、ISR、SSR → 畫面渲染的問題解決了,但還有一類資料不遵守「請求—回應」的節奏:伺服器要主動、持續地推東西過來。這是最後一段的主題。
- 即時通訊:polling、WebSocket、SSE
3. 逐段說明
Frontend System Design Explained w/ Senior Engineer (Microfrontends, Monorepo, MCP UI, Reactjs)
1. 開場:為什麼前端要學系統設計 0:00–0:46
作者開門見山:AI 越來越會寫前端 code,前端工程師唯一保持競爭力的路是把系統設計與架構能力拉上來。他指出坊間系統設計內容幾乎都偏後端、完全忽略前端。接著預告整支影片的大綱:從微前端架構、BFF 之類的系統設計模式,到 monorepo 與 server-side rendering 等渲染策略,最後談怎麼用 AI 與 agentic coding 把這些系統送上 production。
推理因為作者認定「會寫元件」這件事的稀缺性正在被 AI 吃掉,所以他把前端工程師的價值重新定位在「決定系統長什麼樣」上,並直接宣告接下來要補的是那塊被忽略的前端系統設計。他把大綱先攤開——微前端、系統設計模式、monorepo、渲染策略、AI 部署——等於預告整支影片是一條由「團隊怎麼分工」推到「畫面怎麼渲染」的連續推理,而不是零散的名詞列表。
AI 補充作者沒說破的是這條論證的隱含前提:AI 取代的是**局部、可驗證的實作**,取代不了**跨模組的取捨**。寫一個按鈕元件有標準答案,決定「這個按鈕該屬於哪個微前端、狀態放哪裡、誰能改它」沒有。整支影片其實都在放大這個縫隙。另外要先建立一個閱讀姿勢:他接下來講的每個概念(gateway、BFF、CDN、SSR)在後端教材裡都存在,差別是他一律從**前端團隊的處境**去問「這對我有什麼用」,這也是把它當前端系統設計來讀的方式。
2. 從單體到微服務:團隊撐不住了 0:46–2:32
要談微前端得先從後端的 microservices 說起。作者用 client-server 模型:一開始 server 與 client 都是單體,功能一直加,團隊也一直長大——他遇過 40 人的開發團隊,光每天 stand-up 每人講一分半就開一個半小時。這種架構從「開發」的角度就不可能 scale。他搬出 Jeff Bezos 的 two pizzas team(5–9 人),並補一刀:有了 AI 之後,two pizza team 變成 one pizza team。

推理因為上一段把問題定位在「系統怎麼設計」,所以作者接著要證明拆分的驅動力**不是技術,是人**。他刻意從最小的 client-server 單體圖起手,然後只加一個變數——團隊人數——就讓這張圖失效:40 個人、每天一個半小時的 stand-up。這一步很關鍵,因為它把「要不要用微服務」從架構品味的問題,改寫成組織成本的問題。two pizzas team 是他給的量化上限,而「AI 讓 two pizza 變成 one pizza」則把這個上限再往下壓,順勢把 AI 拉進論證裡。
AI 補充這裡值得補一個作者跳過的因果:團隊變大帶來的成本不是線性的。n 個人之間的溝通路徑是 n(n-1)/2 條,40 人就是 780 條——這才是 stand-up 開一個半小時的數學原因,也是為什麼「再加一個人」通常讓專案更慢(Brooks 定律)。另外要注意他的論證方向:他**不是**說微服務讓系統更快或更省資源(多半相反,你會多付網路延遲與運維成本),他說的是微服務讓**團隊**能平行前進。這個區分後面每次談到取捨時都會回來。
術語:monolithclient-server model
「as many as you can feed with one pizza」
3. AI 的真正瓶頸:verification time 2:32–4:31
作者丟出這支影片最關鍵的原則:像 Claude Code 這種 coding agent 把「實作時間」壓到接近零,但它們**拉高了驗證時間(verification time)**。所以 AI 時代的前端工程師,任務是設計出「降低驗證時間、抑制架構漂移、同時放大開發速度」的系統——重點不再是寫得快,而是系統要極度容易驗證。接著用 Conway's law 導出結論:想要小而獨立的團隊,就得把系統切成小而獨立的垂直切片,而這件事從後端拆出 microservices 開始。


推理因為上一段已經證明「人多就卡住」,所以作者這一段要回答「那 AI 讓一切變快之後呢」。他給的答案是這支影片最反直覺的一句:coding agent 把**實作時間**壓到接近零,卻**推高了驗證時間**。這一步把 AI 從「加速器」重新定義成「產能轉移器」——產出變多,於是審查、測試、確認正確性的負擔變成新的瓶頸。有了這個前提,他才敢下結論:AI 時代的架構目標是**讓系統容易被驗證**。接著 Conway's law 提供機制:想要小而獨立的團隊,就得有小而獨立的垂直切片;而切片要從後端的 microservices 開始長。
- Cverification time:coding agent 把實作時間壓到近零,推高驗證時間;AI 時代架構目標=讓系統容易被驗證→ 畫地圖
- A架構決定 diff 的可讀性,diff 的可讀性決定你敢不敢用 AI 產出的東西→ 批判類比
- RConway's law 原本是描述性的;作者用的是反向:先切團隊,架構自己長成那樣(inverse Conway maneuver)→ 存+回想
AI 補充「verification time」值得停下來想,因為它決定了你後面每個架構選擇的方向。同一段 code,放在一個 20 萬行、全域狀態亂竄的單體裡,你要確認它沒壞掉得跑完整套回歸測試;放在一個邊界清楚、只有 3,000 行的微前端裡,你讀 diff 就知道影響範圍。作者的主張其實是:**架構決定 diff 的可讀性,而 diff 的可讀性決定你敢不敢用 AI 產出的東西**。另外補一個他略過的方向性——Conway's law 原本是描述性的(架構「會」長得像組織),實務上常被反過來用成規範性的 inverse Conway maneuver:先把團隊照你想要的架構切好,架構自己會長成那個樣子。作者說的「想要小團隊就得切系統」正是這個反向用法。
術語:feature teamplatform team
4. 前端還是單體:微前端與 shell 4:31–6:16
後端拆完了,前端還是一整塊。作者點出前端單體的痛:太多人往同一個 client 推 code,一個人改到全域 CSS 就影響所有人,溝通成本高到無法 scale。解法是把前端單體切成多個可獨立部署的前端應用,再用一個 **micro frontend shell** 把它們兜起來。shell 負責全域功能——auth、routing、語言、global state——其他微前端都被 shell 載入,並由 shell 把全域狀態傳下去。他舉例:header 可以獨立跑在 header.theseniordev.com。


推理因為上一段證明了拆分的價值,所以作者這一段要說明「同樣的刀怎麼砍在前端」。他先把前端單體的痛講具體——太多人推同一個 client,一條全域 CSS 規則就能波及所有人——這是刻意的,因為前端的耦合比後端更隱蔽:後端至少有 API 當邊界,前端共用的是同一個 DOM、同一份 CSS、同一個 bundle。接著他導出微前端,並立刻補上關鍵零件:**shell**。這一步很重要,因為切開之後必須有人管全域的東西(auth、routing、語言、global state),shell 就是那個「不能被拆掉的中心」。最後用 header.theseniordev.com 這個例子把「獨立部署」講成一個具體的網域。
- Cmicrofrontends:前端單體拆成獨立部署的應用,執行時由 shell 組合;判準是「有幾個團隊在互相卡住」→ 畫地圖
- Rshell 管 auth、routing、語言、global state——不能被拆掉的中心,也是單點故障,所以做得極薄→ 存+回想
- R微前端三個現實代價:bundle 重複、global state 形狀變動=無型別分散式 API、樣式洩漏→ 存+回想
AI 補充作者省略了微前端最現實的三個代價,但它們決定你該不該用:**一、bundle 重複**——每個微前端各自帶 React,使用者可能下載三份,要靠 Module Federation 之類的機制共享依賴。**二、版本偏移**——shell 傳下去的 global state 形狀一改,所有微前端都得跟著改,這其實是一個沒有型別檢查的分散式 API。**三、樣式洩漏**——他說的「改一條全域 CSS 影響所有人」在微前端裡並不會自動消失,除非你做了 CSS 隔離。所以微前端的正確判準和微服務一樣:**你有幾個團隊在互相卡住**。團隊只有一個卻上微前端,你買到全部的成本、沒有任何好處。另外「shell 管 auth 和 routing」意味著 shell 是單點故障,它掛了整個站就掛了——這也是為什麼 shell 通常做得極薄。
術語:independent deployability
5. 垂直切片、職涯兩極與 blast radius 6:16–8:31
微前端配上微服務,就得到 **vertical slice**:一個微前端對上同領域的一到多個微服務,由一個獨立團隊擁有、獨立發布。作者由此推到職涯建議:前端工程師會往兩極走——往 full-stack 的 feature team,或往 infra/design system 團隊;並主張要盡快變成「vertically integrated engineer」,一個能跨全端、配 coding agent 的一人團隊。最後回到 AI:微前端與微服務**縮小了 production bug 的 blast radius**,PR 更小、context 更少,AI 工具因此更有效率,驗證時間也跟著降低。


推理因為前後端各自都切開了,所以作者這一段把兩條線收在一起:一個微前端 + 同領域的一到多個微服務 = 一個 **vertical slice**,由一個團隊獨立擁有、獨立發布。這是全片的結構高點——前面所有拆分都是為了得到這個單位。收完之後他做兩件事:一是把架構結論翻譯成職涯建議(往 full-stack 的功能團隊走,或往 infra/design system 走,並主張成為 vertically integrated engineer);二是回到 AI,指出小切片降低 **blast radius**、縮小 PR、減少 context,所以 AI 工具更有效率、驗證時間更短。這一步完成了第 3 段開出的支票:架構確實可以拿驗證時間當設計目標。
- Cvertical slice:一個微前端+同領域微服務=一個團隊獨立擁有、獨立發布的單位;全片所有拆分都為了它→ 畫地圖
- Rblast radius:一次變更實際能波及的範圍;小切片=小 PR=少 context=AI 更準、驗證更短→ 存+回想
- A「AI 補上你缺的那一半,所以一個人吃整條切片」在 CRUD 成立,在需要深度的地方失效→ 批判類比
AI 補充要小心「垂直整合」這個建議的邊界。作者的論證是「AI 補上你缺的那一半技能,所以一個人能吃下整條切片」,這在 CRUD 型功能上成立;但在需要深度的地方(資料庫查詢計畫、分散式一致性、複雜的無障礙互動)AI 給的是**看起來對**的答案,而你缺乏判斷它對不對的能力——這正好又回到 verification time:你驗證不了的領域,AI 幫不了你。所以比較安全的讀法是:**廣度用來知道要問什麼、跟誰對接;深度仍然要自己選一到兩個方向長。**另外 blast radius 這個詞值得記住,因為它給了「小 PR」一個實質理由——不是「小比較好看」,而是**出事時壞掉的東西比較少、找起來比較快**。
術語:cognitive load
6. API Gateway:把 edge functions 收成一次 8:31–10:15
微前端要打很多後端服務,每個請求都帶著所謂的 **edge functions**:caching、HTTPS、authentication、content negotiation、rate limiting。每接一個微服務就兩邊各實作一次,overhead 極大。解法是 API gateway:client 只實作一次 edge functions,請求進 gateway 後再轉發給後端服務,後端只管自己的邏輯。這些服務都住在 virtual private cloud 裡,唯一入口就是 gateway,所以安全。額外好處是效能:client↔gateway 走 HTTPS,gateway↔微服務可以走 HTTP,省掉 handshake 的來回。

推理因為切分帶來了大量跨網路的請求,所以作者這一段先把「重複的部分」命名為 **edge functions**——caching、HTTPS、authentication、content negotiation、rate limiting——再指出問題:每接一個微服務,前後端就各實作一次,成本隨服務數量線性膨脹。命名完問題,解法就自然浮現:把這些橫切關注點抽到一個**單一入口**,也就是 API gateway。他接著補兩個好處來完成論證:安全上,後端全部躲進 VPC,唯一的門就是 gateway;效能上,對外 HTTPS、對內 HTTP,省掉 handshake 的來回。
- CAPI gateway:把每個服務都要重做的 edge functions(快取、TLS、認證、限流)抽到單一入口,只實作一次→ 畫地圖
- Egateway 對外 HTTPS、對內 HTTP 省 handshake——2015 年主流,zero trust 時代已不推薦→ 存+演練
AI 補充gateway 的真正價值是「橫切關注點只實作一次」,但這也意味著它是**單點故障與單點瓶頸**:所有流量都經過它,它掛了整站就掛了,它慢了整站就慢了。所以實務上 gateway 一定是多實例 + 前面再擺負載平衡(下一段的主題)。另外要提醒一個和作者論證方向不同的現實:對內走純 HTTP 這件事,在近年的 zero trust 思路裡已經不被推薦——「進了 VPC 就是安全的」預設一旦被攻破(例如某個服務被入侵),內網流量就完全裸奔。現代做法是 mTLS 或 service mesh 自動加密,把 TLS 的成本交給基礎設施吸收。他的說法在 2015 年是主流,現在是 debatable。
「HTTPS it's likely less performant than the HTTP」
7. BFF:前端團隊自己擁有後端 10:15–13:46
有了 gateway,client 還是得對一堆長相不同的微服務 API 各打各的 fetch,而且只要功能需要一丁點後端改動,就得去求後端團隊排 backlog。作者說這是他們輔導的大公司工程師最大的痛。解法是 **backend for frontend(BFF)**:一個屬於前端團隊的後端,接住前端請求再轉給微服務,讓前端團隊能以 full-stack 的方式端到端擁有一個功能。再往前一步,每種 client(desktop / mobile)有各自的 BFF,避免 over-fetching 與 under-fetching。他強調這代表前端工程師必須懂 API design,也要懂一點 GraphQL。


推理因為 gateway 只是把橫切關注點收攏,並沒有改變資料的形狀與擁有權,所以作者這一段換一種刀法:不是再抽一層共用的,而是給前端團隊**一個自己的後端**。他先把痛點講到最痛——每個小欄位都要去別的團隊 backlog 排隊,這是他輔導的大公司工程師最常見的卡點——再導出 BFF:一層屬於前端團隊、負責聚合與裁切的後端。有了它,前端團隊就能以 full-stack 的方式端到端擁有一個功能。接著他把 BFF 推到第二層價值:**每種 client 一個 BFF**,desktop 與 mobile 各有各的 API,解決 over-fetching 與 under-fetching。最後他把結論落到能力清單上:前端工程師得懂 API design、懂一點 GraphQL。
- CBFF:前端團隊自己擁有的後端,負責聚合與裁切;判準是擁有權不是技術——由前端部署、前端 on-call→ 畫地圖
- E痛點:每個小欄位都要去別的團隊 backlog 排隊——大公司工程師最常見的卡點→ 存+演練
- RGraphQL 當 BFF 的兩個坑:快取變難(不再是 URL 快取)、查詢複雜度攻擊要防→ 存+回想
AI 補充BFF 的判準其實是「**擁有權**」而不是「技術」。技術上你當然可以叫後端團隊多開一個聚合端點,但那條端點的排程仍然在他們手上——BFF 的價值是把那個決定權搬到前端團隊,所以它必須由前端團隊部署、由前端團隊 on-call。如果 BFF 最後還是後端團隊在維護,你只是多了一層網路跳躍。要注意的成本有兩個:BFF 是**真的後端**,它有部署、監控、on-call、資安責任;而且 client 種類一多,BFF 就會重複,於是又出現「要不要抽共用層」的老問題。GraphQL 常被拿來當 BFF 的實作,因為讓 client 自己宣告要什麼欄位,正好一次解掉 over/under-fetching——但代價是快取變難(不再是單純的 URL 快取)與查詢複雜度攻擊的防護。作者提到 GraphQL 但沒提這兩個坑。
8. Load balancing:單台 server 的天花板 13:46–15:00
回到 client-server 模型:使用者一多,單台 server 就撐不住。作者給了具體數字——一台調校良好的 Node.js server 大約能扛 2,000 到 10,000 個並發請求,超過就得換方法 scale。最簡單的做法是 load balancing:開多個一模一樣的 server instance,前面擺一個 application load balancer 分流。他務實地說前端工程師不必鑽太深,但最好能自己用 Nginx + Docker Compose 在本機兜一個出來,重點是「能推理得出來」。

推理因為前面幾段一直在增加架構的層數,所以作者這一段回頭處理「每一層自己怎麼撐住流量」。他先給一個具體錨點——調校過的 Node.js server 大約 2,000 到 10,000 並發——再指出超過就得換做法。解法是水平擴展:開多個一模一樣的 instance,前面擺 application load balancer 分流。這裡他刻意收斂範圍,明說前端工程師不必鑽進分流演算法,但最好能用 Nginx + Docker Compose 在本機兜一個出來,理由是「重點是你能推理得出來」——這也順手把下一段的 Docker 埋了進來。
- R調校過的 Node.js 約 2,000–10,000 並發(數量級);超過就水平擴展+load balancer→ 存+回想
- P水平擴展的前提是 stateless:先把 session 外移到 Redis/DB,再加機器;本機用 Nginx + Docker Compose 兜一個→ 練習
AI 補充水平擴展能成立有一個前提作者沒點破:**server 必須是無狀態的(stateless)**。如果登入 session 存在某台 server 的記憶體裡,使用者被分到另一台就等於登出了。所以真正的第一步不是加機器,而是把狀態外移到 Redis 或資料庫;做不到就只能退而求其次用 sticky session,但那會讓分流失衡、也讓那台機器不能隨便重啟。另外 2,000–10,000 這個數字要當數量級讀而不是規格:純轉發的 I/O 密集工作可以很高,一旦有 JSON 解析、模板渲染或加密這類 CPU 工作,Node 的單執行緒特性會讓數字掉一到兩個級距。真正該記住的是**形狀**:I/O 密集看連線數,CPU 密集看核心數。
「it can usually satisfy up to 2,000 to 10,000 concurrent requests」
9. 容器化:Docker 與 orchestration 15:00–17:31
架構被拆成一堆微前端與微服務之後,部署反而變成噩夢:Python 的微服務、Node.js 的微服務、Vue 或 Next.js 的前端,各有各的 pipeline。解法是用 Docker 標準化:Dockerfile 是打包的食譜,產出的 image 包含程式碼、runtime(例如 Node)與作業系統(通常是 Linux)。只要 host 跑得動 Docker 就跑得動這個 image,不必管 Node 版本或依賴。DevOps 再把這些 image 丟進 container orchestration system(Kubernetes、AWS 的 ECS)處理負載平衡、多實例、失敗自動重啟。作者明講:前端工程師不必會 Kubernetes,但要能說出它在架構裡的位置。


推理因為前面已經把系統拆成一堆技術棧各異的微前端與微服務(Python、Node、Vue、Next.js),所以作者這一段要解的是**部署的異質性**。他的推理很直接:如果每個服務都要自己一套佈建流程,拆分省下的協作成本會被運維成本吃回去。Docker 的作用是**把差異封裝進 image**——Dockerfile 是食譜,image 裡裝著程式碼、runtime 與作業系統,於是對外只剩一個統一介面:跑起來、開這個 port。統一之後才有下一步:把一堆 image 丟進 container orchestration system,讓它處理多實例、失敗重啟與負載平衡——也就是上一段那些事,現在由 Kubernetes 自動化。最後他務實地劃線:前端工程師不必會 Kubernetes,但要能說出它在架構裡的位置。
- RDocker image 的「作業系統」只是使用者空間,kernel 共用宿主機——所以幾百毫秒就啟動→ 存+回想
- R前端工程師不必會 Kubernetes,但要能說出它在架構裡的位置:接手多實例、失敗重啟、負載平衡→ 存+回想
AI 補充有一個常見誤解值得澄清:Docker image 裡的「作業系統」不是完整的 OS,而是**使用者空間的檔案與函式庫**——kernel 是跟宿主機共用的。這解釋了兩件事:為什麼容器啟動只要幾百毫秒(不必開機),以及為什麼 Linux 容器不能直接跑在 Windows kernel 上(要靠虛擬機墊一層)。對前端工程師最有實感的好處其實不在 production,而在**本機**:一句 docker compose up 就能起一組和 CI 一模一樣的環境,「在我機器上是好的」這句話從此失效。而回到全片的主軸——容器讓 orchestration 能自動把壞掉的實例換掉,這等於把「出錯後的復原」也自動化了,同樣是在壓低 verification time(見第 3 段)。
10. CDN:跟光速借時間 17:31–20:01
這是全片第一個純前端概念。作者用一個實體限制開場:美國使用者要拿歐洲 server 的 JS/CSS,資料得橫跨大西洋來回,而**資料最快只能跑到光速**,長距離下每個請求會多出大約 200–250 ms 的延遲,這是繞不過去的物理限制。解法是縮短距離:CDN 把靜態資源推到全球各地的 edge location,請求會被導到離你最近的那一個。他接著把 CDN 定義成一個分散式快取——拿到資源叫 cache hit,server 推新版叫 cache invalidation,並連到前端熟悉的 cache busting。結論:CDN 是最便宜、最快改善 web performance 的手段,現代 CDN 還順便幫你壓縮與設好 cache policy。

推理因為前面所有優化都發生在伺服器端,所以作者這一段刻意換一個維度:他從一個**不可談判的物理限制**出發——資料最快只能以光速前進,美國使用者拿歐洲的檔案,一個來回就是 200–250 ms,任何程式碼優化都動不了它。這個開場很有力,因為它把問題從「我們寫得夠不夠好」改成「距離太遠」,於是解法只剩一種形狀:**把檔案搬近一點**。CDN 就是這個形狀的實作——邊緣節點遍布全球,請求被導到最近的一個。導出解法後他再做一次概念收攏:CDN 本質上是分散式快取,於是 cache hit、cache invalidation 都能套上來,並接到前端熟悉的 cache busting。結尾給出實用的判斷:CDN 是投入產出比最高的效能手段。
- CCDN:光速是不可談判的限制(跨洋一來回 200–250 ms),唯一解法是把檔案搬近;本質是分散式快取→ 畫地圖
- Pcache busting 標準組合:檔名塞內容雜湊、index.html 不快取、其餘設一年不變→ 練習
AI 補充這段最值得補的是「為什麼快取失效是難題」。cache busting 的做法是在檔名裡塞內容雜湊(app.a3f9c2.js),內容一變檔名就變,於是**舊檔案永遠不必失效**——你只要讓 index.html 不被快取,其餘檔案全部設成一年不變。這個組合是現代前端部署的標準答案,而作者只提到名詞沒說機制。另外要修正一個對 CDN 常見的想像:邊緣節點通常不是「事先被推滿」,而是**第一個請求的人回源拉一份、之後的人才命中**(pull 模式)——所以每個地區的第一位使用者仍然要付完整的來回延遲。最後一個作者沒展開但很實際的點:現代 CDN 已經不只放靜態檔,它還能跑程式碼(edge functions/edge workers),這讓「在離使用者最近的地方做個人化」變得可能——快取與運算的界線正在往邊緣移動。
「whenever the server pushes a new version, that's called cache invalidation」
11. Design system:對抗視覺分歧 20:01–22:16
微前端讓各功能團隊獨立發布,代價是 code repetition 與 **visual divergence**——產品頁的按鈕跟付款頁的按鈕長得不一樣,使用者會察覺這其實是好幾個前端。解法是 design system:先定義 design tokens(主色、border、字體家族),現代做法是在 shell 的全域 CSS 裡用 CSS custom properties 宣告,再餵給所有微前端;再往上建可重用元件,讓功能團隊組裝。好處除了視覺一致與不重複程式碼,還能集中處理 accessibility 與單元測試。他最後把它連回 AI:一個扎實的 design system 是「AI 產出一堆不一致的元件」與「AI 產出穩定可靠結果」之間的差別,他自己每個新專案的第一件事就是先萃取 design system 餵給 coding agent。

推理因為第 5 段建立的垂直切片讓團隊互相解耦,所以這一段要處理解耦的**副作用**:沒有共用的約束,產品頁的按鈕和付款頁的按鈕就會不一樣,使用者會察覺這其實是好幾個前端拼起來的。作者把這個現象命名為 visual divergence,並指出它同時是產品問題(失去一致性)與技術問題(重複的程式碼)。解法分兩層推進:先是 **design tokens**——用 CSS custom properties 在 shell 的全域層宣告,往下餵給所有微前端;再往上是**可重用元件**,讓功能團隊直接組裝。這個順序有意義:token 是最低成本、最容易共用的一致性;元件是更強的約束但也更難維護。最後他把整段接回 AI:design system 是 agent 產出穩定與否的分水嶺,他自己每個新專案的第一件事就是先萃取 design system 再開始讓 agent 寫。
- Cdesign system:對抗垂直切片解耦後的 visual divergence;token 先、元件後;也是 agent 產出穩定的分水嶺→ 畫地圖
- A有 --color-primary 和既有 <Button>,agent 面對的是選擇題不是申論題——約束越強,驗證越快→ 批判類比
AI 補充「design system 讓 AI 產出穩定」這句話值得展開成機制,因為它是這段最有操作價值的部分:coding agent 每次都在一個有限的 context 裡工作,它不知道你的品牌色,於是會**發明**一個。當專案裡存在 --color-primary 和一個既有的 <Button>,agent 面對的就不再是開放式創作,而是「選用哪個既有元件」的選擇題——選擇題的錯誤率遠低於申論題,而且錯了你一眼就看得出來。這正好又回到第 3 段的 verification time:**約束越強,驗證越快**。另外提醒一個作者沒說的順序陷阱:design system 太早做會變成猜測(你還不知道需要哪些元件),太晚做則要付重寫的代價。實務上的折衷是**先只做 token**——顏色、間距、字體、圓角這幾組變數幾乎不會猜錯,而它們就能擋掉大部分的視覺分歧。
術語:DRY principle
12. Design-to-code MCP 與 Atomic CSS 22:16–23:45
有了 design system,下一步是把它接上 AI 工作流。作者的情境:設計師在 Figma 裡先建了 design system,你在 library 裡實作它,然後用 **Figma MCP server** 配 coding agent 快速把功能組裝進垂直切片——他說多數公司正往這個工作流走,前端工程師必須知道 MCP server 是什麼、怎麼用,甚至可能得自己接。接著補一段 CSS 架構:把 design tokens 配上 **Atomic CSS** 方法論,做成 `.border` 這種原子類別讓其他開發者直接用——而 Tailwind CSS 就是 Atomic CSS 這個架構風格的一種實作。

推理因為上一段證明了「約束讓 agent 產出穩定」,所以這一段要把約束的**來源**再往前推一步:與其讓工程師把 Figma 上的設計翻譯成程式碼、再讓 agent 讀程式碼,不如讓 agent 透過 **MCP server** 直接讀設計本身。他描述的流程是:設計師在 Figma 建 design system → 你在 library 實作它 → coding agent 透過 Figma MCP server 直接取用,快速把功能組裝進垂直切片。接著他給出能力要求:知道 MCP server 是什麼、會用、必要時自己接。最後補一段 CSS 架構把上一段的 token 收尾——用 Atomic CSS 把 token 變成原子類別,並點名 Tailwind CSS 就是 Atomic CSS 的一種實作。
- RMCP 是工具接進 LLM 的統一介面;Figma MCP server 讓設計稿變成可查詢的結構化資料→ 存+回想
- RAtomic CSS(Tailwind 是一種實作):CSS 大小不隨專案成長、刪元件不留孤兒樣式;代價是 HTML 塞滿類別→ 存+回想
AI 補充MCP 值得用一句話講清楚它為什麼重要:它是**工具接進 LLM 的統一介面**。在它之前,每個 AI 應用要接 Figma、接 GitHub、接資料庫,都得各寫一套整合;MCP 把「有哪些工具、每個工具吃什麼參數」標準化,於是同一個 server 可以被任何支援 MCP 的 agent 使用。這對前端的實際意義是:設計稿不再是一張要被人眼翻譯的圖,而是**可查詢的結構化資料**——agent 可以問「這個元件用了哪個 token」而不是猜像素。至於 Tailwind 那句定位很準但值得補完:Atomic CSS 的代價是 HTML 會塞滿類別、可讀性下降,收益是 CSS 檔案大小不隨專案成長(類別會重複使用)、而且刪掉元件不會留下沒人敢刪的孤兒樣式。它和 design system 不衝突——token 定義值,atomic class 提供用法,元件封裝組合。
13. Monorepo:給 agent 看得見邊界 23:45–25:16
微前端散在上千個 GitHub repo 裡,會長出不同的 code style、不同依賴、不同品質標準——這就是 **architectural drift / code style drift**;開發者換團隊就得重學一次,標準化完全沒發揮。解法是 monorepo:一個大 repository 裝下所有小應用,工具鏈共用,`npm run build` 一次把所有應用各自建好。作者把它接回 AI:monorepo 給 coding agent「跨服務邊界修改所需的 context」——你在微前端裡發現一段可重用的邏輯,可以在同一個 session 裡把它抽成 design system 的元件;分成兩個 repo 就得想辦法把兩份 repo 都餵進去。結論:微前端 + 微服務 + monorepo 通常是跟 AI 合作最有效率的組合。

推理因為第 4 段的切分讓每個微前端各有一個 repo,所以這一段要處理切分的第三筆帳(前兩筆是視覺分歧與工作流斷裂):**標準的分歧**。散在上千個 repo 裡,code style、依賴版本、品質標準會各自漂移,開發者換團隊得重學一次,標準化的好處完全沒兌現。解法是把所有小應用收進單一 repository,共用工具鏈,一次 build 全部。接著他做出這段最有價值的轉折——monorepo 不只對人有用,**它給 coding agent 跨服務邊界所需的 context**:你在微前端裡發現一段可重用的邏輯,可以在同一個 session 裡把它抽成 design system 的元件;分成兩個 repo 就得想辦法把兩份都餵進去。結論是把三件事疊起來:微前端 + 微服務 + monorepo 是跟 AI 合作最有效率的組合。
- Cmonorepo:所有切片收進單一 repo 共用工具鏈;對 agent 的價值是能沿 import 追蹤真實依賴,跨服務邊界重構→ 畫地圖
- Rrepo 邊界≠部署邊界:Nx/Turborepo 靠依賴圖只重建受影響的套件;成本在規模與擁有權(CODEOWNERS)→ 存+回想
AI 補充這裡有個表面矛盾值得拆開:**單一 repo 和獨立部署會衝突嗎?** 不會,因為 repo 邊界和部署邊界是兩件事。monorepo 管的是原始碼放哪裡與工具鏈怎麼共用,獨立部署(第 4 段)管的是誰能單獨上線——Nx、Turborepo 這類工具正是靠依賴圖判斷「這次改動只影響 payments,所以只重建與部署 payments」。真正的成本在別的地方:**規模**(單一 repo 大到讓 git 操作與 CI 變慢,Meta 與 Google 得自己寫工具)與**擁有權**(所有人都能改所有東西,需要 CODEOWNERS 這類機制把邊界重新畫回來)。另外對 agent 的價值可以講得更準:context 不只是「檔案都在」,而是 agent 能沿著 import 路徑**追蹤真實的依賴關係**——它看得到誰用了這個元件,才敢改它。這是跨 repo 時 agent 最常出錯的地方:它以為自己在做局部修改,實際上動到了別人的介面。
術語:polyrepo
14. MCP UI:讓 LLM 回你元件而不只是字 25:16–27:45
作者說這是他最興奮的東西:MCP UI 是傳統網站與 LLM 應用之間的黏著劑。在聊天應用裡,你送出 query,LLM 回答——但這次它可以用 **UI 元件**回答,直接把商品、地圖 render 在答案裡。他用自己找活動場地的親身經驗舉例:聊著聊著,介面開始 render 場地卡片、跟他要輸入、甚至畫出地圖。運作機制是:model harness 在 context 裡提供 tool registry 與各 MCP server,LLM 回傳文字答案外還附上「render 某個 div」的指令,前端解析後渲染。他反駁「有了 chat 就不需要 UI」的說法,主張未來是 LLM 與傳統 web 的混合。


推理因為第 12 段已經把 MCP 建立成「LLM 連接外部工具的標準介面」,所以這一段可以直接把它推到介面層:如果 LLM 能呼叫工具,它為什麼不能**要求前端渲染一個元件**?作者把 MCP UI 定義成傳統網站與 LLM 應用之間的黏著劑,並用親身經驗當證據——他找活動場地時,聊天介面突然 render 出場地卡片、要他給回饋、還畫出地圖。有了具體畫面他才拆機制:model harness 在 context 裡提供 tool registry 與各 MCP server,LLM 回傳文字答案外附帶「渲染某個 div」的指令,前端解析後渲染。最後他反駁「有了 chat 就不需要 UI」——他的論證是 UI 在傳達結構化資訊上仍然不可取代,未來是兩者的混合。
AI 補充這段最需要補的是**安全邊界**,因為作者完全沒提,而這正是把它從 demo 做成產品的分水嶺:讓 LLM 的輸出決定畫面上渲染什麼,等於把一個不可信的來源接到渲染路徑上。所以實作一定要走「**宣告式白名單**」而非「執行任意標記」——前端事先註冊好一組元件與各自的 props schema,LLM 只能回傳「元件名 + 通過驗證的參數」,絕不能回傳 HTML 或程式碼片段。這也是為什麼 MCP UI 的規格傾向用 iframe 或 sandbox 隔離第三方渲染。第二個作者略過的難題是**狀態歸屬**:使用者在 LLM 渲染出來的卡片上按了「Love it」,這個狀態算誰的?它得回到對話的 context 裡讓模型知道,又得反映在應用程式自己的資料上——這種雙寫是這類介面最容易出錯的地方。回到全片主軸看,MCP UI 其實是第 5 段那個 vertical slice 的延伸:一條新的垂直路徑,只是入口從網址列換成了對話框。
15. Core Web Vitals 與關鍵渲染路徑 27:45–30:30
作者說這是前端職缺描述裡最常出現的效能模式。Core Web Vitals 是三個指標,量的是網站效能的三個面向:載入速度、互動速度、視覺穩定性,對應 **LCP**(按下 enter 到最大元素被畫出來)、**INP**(互動後多久重繪)、**CLS**(載入過程中畫面位移多少)。LCP 與 CLS 關於初次渲染,INP 關於重新渲染——這在元件框架下特別重要。要理解這些就得懂 critical rendering path:DOM → CSSOM → render tree → layout tree → paint operations → GPU → composite,再加上元件框架拿到資料後的 re-render,最後才畫出 LCP。結論很直接:JS 太多、CSS 太多、資料抓太多、server 太慢,LCP 就會很難看。


推理因為前面十四段講的都是**結構**,所以作者從這裡開始轉向**體感**,而第一步必須是量測——否則優化只能靠感覺。他的推進方式很乾淨:先把「效能」拆成三個維度(載入速度、互動速度、視覺穩定性),每個維度配一個 Google 定義的指標(LCP、INP、CLS),於是模糊的「網站好慢」變成三個可以分別歸因的數字。接著他做關鍵的分組:LCP 與 CLS 屬於**初次渲染**,INP 屬於**重新渲染**——這個分組直接對應到元件框架的行為,也預告了後面兩段的分工。最後他把指標往下接到 critical rendering path:DOM → CSSOM → render tree → layout → paint → composite,說明 LCP 為什麼慢的原因全都藏在這條路徑的某一步上。
- CCore Web Vitals 把「好慢」拆成三個可歸因的數字:LCP(載入)、INP(互動)、CLS(穩定)→ 畫地圖
- R三指標各自主因:LCP=TTFB/阻塞資源/主視覺圖/等資料;CLS=沒尺寸的圖與延遲字體;INP=主執行緒長工作→ 存+回想
- R實驗室數據(Lighthouse)與真實使用者數據(field / CrUX)常對不上,Google 排名看後者→ 存+回想
AI 補充這三個指標各自的**主因**值得記牢,因為它決定你要去改哪裡。**LCP** 幾乎總是卡在四件事之一:伺服器回應太慢(TTFB)、阻塞渲染的資源(同步的 CSS/JS)、最大元素本身載得慢(沒優化的主視覺圖)、或客戶端渲染要等資料。**CLS** 的頭號兇手是沒給尺寸的圖片與延遲載入的字體——解法便宜到近乎免費:img 標上 width/height、字體用 font-display: optional 或先配好 fallback 的尺寸。**INP** 則是主執行緒被長工作佔住,React 的常見版本是一次狀態更新引發整棵子樹重繪。另外補一個作者略過的重要區分:這些指標有**實驗室數據**(Lighthouse,在你的機器上模擬)和**真實使用者數據**(field data / CrUV,真實使用者的裝置與網路)兩種來源,兩者經常對不上——而 Google 排名採用的是後者。優化時盯錯數據源是很常見的浪費。
術語:reconciliation
16. Code splitting 與 lazy loading 30:30–32:00
接續效能:傳統 module bundler 把所有 JavaScript 打成一個大檔,載入它會直接毀掉 Core Web Vitals。**Code splitting** 讓你只把某一頁真正需要的 JavaScript 送過去——最簡單的切法是按 route,`/login` 只拿登入要用的元件,圖表很重的 dashboard 就不會一起送。這由 Webpack 或 Vite 這類 module bundler 配合 router 動態載入完成。作者把它升到更高的心智模型:**lazy loading**(用到才載)是 eager loading(一進來全載)的反面,可以綁在捲動、換頁或點擊上,一切都是為了讓 Core Web Vitals 更好。

推理因為上一段已經把「JS 太多 → LCP 難看」建立成因果,所以這一段直接處理那個因。作者先指出傳統 module bundler 的預設行為——全部打成一個大檔——正是問題本身;接著給出最小可行的切法:**按 route 切**,/login 只拿登入要用的元件,圖表很重的 dashboard 不會被一起送出去。他點名這由 Webpack 或 Vite 配合 router 動態載入完成,讓概念落地成具體工具。最後他做了一個抽象上升:code splitting 只是 **lazy loading** 這個更大心智模型的一個實例,而 lazy loading 的對立面是 eager loading——載入時機可以綁在捲動、換頁或點擊上,全都是為了讓 Core Web Vitals 更好。
AI 補充「按 route 切」是起點不是終點,值得補完整套策略:**第一刀切路由**(收益最大、風險最低);**第二刀切重量級依賴**——圖表庫、富文字編輯器、日期選擇器這類幾百 KB 但只在特定互動後才用到的東西,用動態 import 延後;**第三刀是 vendor 分離**,把不常變的第三方套件單獨成 chunk,讓使用者的快取在你每次發版時仍然有效。同時要知道 lazy loading 的**反效果**:切得太碎會製造大量小請求與瀑布式的依賴鏈,反而更慢;而在使用者點下去之後才開始載入,會把延遲從載入期搬到互動期——變成 INP 的問題。成熟的做法是搭配 prefetch:閒置時或滑鼠移到連結上時先偷偷載好,讓使用者感覺不到等待。作者只講了「延後」,沒講「預先」,但兩者其實是一組。
17. 渲染策略:CSR、SSG、ISR、SSR 32:00–35:15
現代元件框架(React、Vue、Angular)的問題是進站看到白畫面:載入空 HTML,跑完 render function 才看得到東西——這是 **client-side rendering**,SPA 要先拿靜態檔、再抓動態資料、最後才渲染,對效能與 SEO 都不利。替代方案依序是:靜態網站先在 server 預先渲染好直接送 HTML/CSS;內容會變的(例如部落格)用 **incremental static generation**,CMS 觸發 rebuild 只重生變動的頁面;最後是 **server-side rendering**,前端 server 去後端拿資料、在 server 上渲染再把完整 HTML 送回,白畫面沒了但頁面還不能互動,得經過 **hydration** 把 virtual DOM 掛上既有 HTML。作者對 SSR 的態度很保留:只有真的需要極致效能或 SEO 才用,否則就像「為了買菜造一台 F1 賽車」。



推理因為上一段的所有手段都在「送多少 JS」這個維度上,所以這一段換維度:**畫面在哪裡被渲染**。作者用一個所有人都有實感的症狀開場——現代元件框架進站的白畫面——並解釋成因:拿到的是空 HTML,得等 render function 跑完才有東西。這是 client-side rendering,對效能與 SEO 都不利。接著他按「內容變動頻率」排出一條光譜:內容不變 → 建置時預先渲染成靜態檔;內容會變但不頻繁 → incremental static generation,CMS 觸發只重生變動的頁;內容每次都不同 → server-side rendering,在伺服器抓資料渲染完再送出。SSR 解掉白畫面,但引入 **hydration**:頁面看得到卻還不能互動,得等 JS 執行、建好 virtual DOM 掛上既有 HTML。作者對 SSR 的態度很保留——「為了買菜造一台 F1 賽車」——只有真的需要極致效能或 SEO 才用。
- C渲染策略的判準是「這一頁的內容在什麼時候才能確定」:build 時→SSG、會過期→ISR、每次不同→SSR/CSR→ 畫地圖
- ASSR 是「為了買菜造一台 F1 賽車」;真正的複雜度不在渲染而在你多了一台要維運的伺服器→ 批判類比
AI 補充這條光譜的**判準**可以講得比作者更明確:不是「哪個技術比較先進」,而是**這一頁的內容在什麼時候才能確定**。建置時就確定(部落格、文件、行銷頁)→ SSG;建置時確定但會過期(商品列表、新聞)→ ISR;每個使用者每次請求都不同(個人化推薦、儀表板)→ SSR 或乾脆 CSR。同一個網站的不同路由用不同策略是完全正常的,Next.js 這類框架正是為此設計。另外要補 hydration 的真正代價:使用者會遇到一段**看得見卻按不動**的空窗期,這對 INP(第 15 段)是直接的傷害,而且諷刺的是,SSR 為了消除白畫面反而讓這段空窗更容易被察覺——因為畫面已經在那裡了。這也是近年 islands architecture、React Server Components、partial hydration 這些方向要處理的問題:**只 hydrate 真的需要互動的那幾塊**。最後替作者的保留意見補一個更精確的判準:SSR 的複雜度成本主要不在渲染本身,而在**你現在有一台需要維運的伺服器**——快取、記憶體洩漏、冷啟動、以及所有「在瀏覽器有、在 Node 沒有」的 API 差異。如果你的 SEO 需求只涵蓋幾個公開頁面,SSG 幾乎總是更划算的選擇。
術語:static site generation
「that's like building an F1 car to go to the groceries」
18. 即時通訊:polling、WebSocket、SSE 35:15–38:02
最後一個概念,也是作者強調前端要能碰資料層的理由。不走 request-response 週期的即時通訊有三種:**polling** 一直打同一個 endpoint 直到狀態改變,用 setTimeout 就能做、很簡單但打太多次、會有 race condition、不好 scale;**WebSocket** 開一條雙向通道,適合聊天這種雙邊都在送訊息的場景,但 overhead 大、很吃 server 資源;而 AI 應用的通訊是**單向不對稱**的——你送一個 query,然後 server 一直吐 token 回來。答案是 **server-sent events**:送一則訊息建立對話,然後在那個 endpoint 上持續接收 server 的更新。他點名這就是多數 LLM 應用的做法,你打開 ChatGPT 或 Claude 的 network 面板看那個 conversation 請求,回應就是一連串 event stream——不是 WebSocket,也不是 polling。


推理因為前面所有架構都建立在 client 發問、server 回答的模型上,所以最後一段要補上這個模型涵蓋不到的情況。作者用同一套方法——列出選項、逐一指出代價、再讓需求決定答案。**polling** 最簡單,setTimeout 就能做,代價是打太多次、有 race condition、scale 不好;**WebSocket** 開雙向通道,適合聊天這種兩邊都在送的場景,代價是 overhead 大、很吃伺服器資源。然後他丟出決定性的觀察:**AI 應用的通訊是不對稱的**——你送一個 query,server 吐回幾千個 token。既然是單向,用雙向通道就是浪費。於是 **server-sent events** 成為答案。他最後給了一個可以立刻自己驗證的證據:打開 ChatGPT 或 Claude 的 network 面板看那個 conversation 請求,回應就是一串 event stream。
- P即時通訊選型:只有伺服器要說話用 SSE,雙方都頻繁說話用 WebSocket,低頻狀態查詢用 polling→ 練習
- RSSE 跑在普通 HTTP 上:既有基礎設施照用、內建重連;限制是 HTTP/1.1 每網域 6 條連線→ 存+回想
AI 補充SSE 有兩個作者沒提、但實作時一定會撞到的特性。**好處**:它跑在普通的 HTTP 上,所以 CDN、代理、認證、壓縮這些既有基礎設施全部照用,而且瀏覽器的 EventSource 內建自動重連與 Last-Event-ID 續傳——這些在 WebSocket 上全都得自己寫。**限制**:在 HTTP/1.1 下每個網域的並行連線數上限是 6,幾個分頁一開就會互相卡住(升上 HTTP/2 就沒這問題);另外原生 EventSource 只支援 GET、不能自訂標頭,所以要帶 Authorization 的場合通常改用 fetch 手動讀 stream——這也是多數 LLM SDK 實際的做法。至於選擇標準,可以收成一句話:**只有伺服器要說話就用 SSE,雙方都要頻繁說話才用 WebSocket,簡單且低頻的狀態查詢用 polling 就好**。這也正好呼應這支影片從頭到尾的態度——先問需求的形狀,再選技術,而不是反過來。
4. 總結
這支影片的推理鏈可以壓成一條線:**AI 把瓶頸從「寫」搬到「驗證」→ 所以架構的目標變成讓變更容易被驗證 → 而最有效的手段是縮小每次變更的爆炸半徑 → 縮小的方法是把系統切成小而獨立、由單一團隊擁有的垂直切片。** 切分的依據來自 Conway's law:想要小而獨立的團隊,就得有小而獨立的系統。後端切成 microservices,前端切成 microfrontends 加一個薄 shell,兩邊對接成 vertical slice。接下來的九個概念,其實都是在還這一刀欠下的債——跨網路的雜事重複了用 API gateway 收攏;資料形狀與擁有權沒解決用 BFF;每層都是單機用 load balancing;技術棧太雜用 Docker 與 orchestration;機房離使用者太遠用 CDN;團隊各自出貨導致視覺分歧用 design system;design system 沒接上 AI 用 design-to-code MCP;程式碼散落讓 agent 看不見全貌用 monorepo。 傳統議題收完後,作者插入 MCP UI 作為前沿——當 LLM 回的不只是文字而是 UI 元件,前端要怎麼接。然後換到體感維度:Core Web Vitals 把「好慢」拆成 LCP、INP、CLS 三個可歸因的數字,critical rendering path 解釋數字為什麼難看,code splitting 處理送太多 JavaScript,渲染策略(CSR → SSG → ISR → SSR + hydration)處理畫面該在哪裡生成,最後 server-sent events 補上請求—回應模型涵蓋不到的即時推送。 真正該帶走的不是這二十個名詞,而是它們共用的提問順序:**這件事卡住了誰?成本落在哪一邊?有沒有一個切法能讓爆炸半徑變小、讓驗證變快?**
勘誤總整理
確定錯誤/已過時見仁見智(取決於版本或情境)
| 段落 | 原話(transcript 逐字) | 說明 |
|---|---|---|
| 2. 從單體到微服務:團隊撐不住了 1:45 |
「as many as you can feed with one pizza」 | 作者剛說完這條規則叫 two pizzas team,緊接著卻把它描述成「一個披薩餵得飽」。Amazon 的原始規則是**兩個**披薩餵得飽的人數(約 5–9 人),一個披薩會把上限壓得比他自己給的 5–9 人還低,前後矛盾。他下一句「有了 AI 就變成 one pizza team」才是刻意的引申。 依據: Jeff Bezos 的 two-pizza team rule,Amazon 內部沿用至今的說法為 two pizzas |
| 6. API Gateway:把 edge functions 收成一次 9:55 |
「HTTPS it's likely less performant than the HTTP」 | 這個說法以今天的標準過度簡化了。TLS 1.3 把 handshake 壓到 1-RTT、session resumption 可到 0-RTT,開銷通常只有個位數毫秒;而且 HTTP/2 與 HTTP/3 在瀏覽器上都**只**在 TLS 之上啟用,所以走 HTTPS 反而拿得到多工與更好的壅塞控制,整體常常更快。內部服務間改走純 HTTP 現在也不再是推薦做法——zero trust 與 service mesh 的主流意見是內網一律 mTLS,把加密成本交給基礎設施。 依據: RFC 8446(TLS 1.3, 2018);主流瀏覽器僅在 TLS 上支援 HTTP/2 與 HTTP/3 |
| 8. Load balancing:單台 server 的天花板 14:05 |
「it can usually satisfy up to 2,000 to 10,000 concurrent requests」 | 這個區間只在「幾乎純 I/O、每個請求 CPU 工作極少」的前提下成立,作者沒有講出這個前提。一旦每個請求有 JSON 序列化、模板渲染、加密或任何同步運算,Node.js 的單執行緒事件迴圈會讓實際承載量掉到數百甚至更低。反過來說,純轉發的代理型工作可以遠高於一萬。當成數量級的直覺可以,當成容量規劃的依據不行——實際數字只能靠壓測得出。 依據: Node.js 單執行緒事件迴圈模型;承載量取決於每請求的 CPU 時間與 I/O 比例 |
| 10. CDN:跟光速借時間 19:58 |
「whenever the server pushes a new version, that's called cache invalidation」 | 這個定義把兩件事混在一起了。cache invalidation 指的是**讓既有的快取項目失效**(CDN 上叫 purge),是一個明確的清除動作;「server 推上新版本」本身並不會讓舊快取失效,除非你主動 purge,或是用下一句他提到的 cache busting 讓新版本有新的網址。實務上正是因為 invalidation 不可靠,現代前端才幾乎全面改用內容雜湊檔名來繞過它。 依據: CDN 供應商(Cloudflare、Fastly、CloudFront)皆將 invalidation/purge 定義為主動清除既有快取項目的操作 |
| 17. 渲染策略:CSR、SSG、ISR、SSR 34:53 |
「that's like building an F1 car to go to the groceries」 | 這個比喻對「為了 SEO 就全站 SSR」的批評是對的,但把 SSR 一概說成過度設計在今天偏保守。Next.js App Router、Remix、Nuxt 已經把 SSR 變成預設路徑,運維成本大幅下降;而 React Server Components 與 partial hydration 也在削減他點出的 hydration 代價。比較準確的判準不是「要不要 SSR」,而是**逐路由**決定:內容在建置時就能確定的用 SSG,需要個人化的才用 SSR。 依據: Next.js App Router(2023 起預設 Server Components)、Remix、Nuxt 3 皆以 SSR 為預設渲染模式 |
5. 推薦三個下一步
1. 往下挖深:Module Federation 與微前端的實際落地
影片把微前端講到「shell 載入各微前端」就停住了,沒有回答最實際的三個問題:多個微前端怎麼共用同一份 React 而不重複下載、shell 傳下去的 global state 怎麼避免變成沒有型別的隱性 API、以及樣式怎麼隔離。這是從概念走到能上線的那一段。
YouTube 搜尋:Module Federation micro frontends tutorial micro frontend shared dependencies React micro frontend css isolation
2. 往旁邊對照:React Server Components 與 islands architecture
影片對 SSR 的態度停在「像造 F1 去買菜」,但它點出的 hydration 代價(看得到卻按不動)正是近年整個生態在解的題目。把 RSC、islands、partial hydration 拿來對照,你會看到「只 hydrate 需要互動的那幾塊」如何改寫渲染策略的取捨表。
YouTube 搜尋:React Server Components explained islands architecture partial hydration Astro vs Next.js rendering
3. 往上應用:把 SSE 串流接進自己的 LLM 應用
影片給了「LLM 應用用 server-sent events」這個結論,也給了打開 network 面板自己驗證的方法,但沒有走到實作。親手寫一次串流端點與前端接收,你會同時撞到它沒提的兩個坑:原生 EventSource 不能自訂標頭,以及 HTTP/1.1 下每網域六條連線的限制。
YouTube 搜尋:server sent events streaming LLM tutorial EventSource vs fetch streaming React OpenAI streaming response frontend
- 接著看 ←Every Frontend Architecture Pattern Explained in 23 Minutes · 架構演化站列出的 micro-frontend、BFF、CDN、SSR,在這站被接成一條由驗證時間驅動的推理鏈
- 接著看 ←Top 15 Frontend Interview Questions for 2026 (wa/ Senior Engineer) · 面試題點到的 bundle 切分、即時協定、Core Web Vitals,在這站各自展開成機制與判準
- 接著看 →Real Senior Frontend System Design Interview 2026 (AI Coding Included) · 這站建立的 SSE 判準、design system 與垂直切片,在那場模擬面試裡被拿來實際設計一個系統
- 相關 —3 Frontend Skills AI Can't Replace (become AI-proof) · 共用 Core Web Vitals 與 critical rendering path:一站談架構怎麼降驗證成本,一站談哪些判斷 AI 取代不了
- 接著看 ←15 Frontend Concepts Every Senior Dev Has Mastered · CRP、Core Web Vitals、SSR、CDN 在這站建立,那站直接拿來用不再解釋
- 接著看 ←How Senior Frontend Engineers Think in System Design Interviews · 這站只給決策方法,那站補上要決策的具體內容:BFF、渲染策略、微前端
- 相關 —Real Frontend System Design (from a Senior Engineer) · 同一批零件、兩種組織法:一站用驗證時間串起推理鏈,一站用 scale level 逐層加壓
- 相關 —Frontend System Design at Scale (The Senior Dev Playbook) · 同樣談微前端與 monorepo:那站往組織與渲染推,這站往上線流程與可靠性推
- 接著看 ←Senior Frontend Interview 2026 🎉 | Javascript 🎯 (Mock) [Most Asked Questions] · reconciliation、hydration、WebSocket 等單點觀念在這站被放進整個系統設計裡
- 接著看 ←15 Fullstack Concepts Every Frontend Should Know · API Gateway、BFF、SSE、WebSocket 等十個共同術語,那站不再解釋
- 接著看 →The 3 Skills That Separate Architects From Senior Developers · 共用 Conway's law、microservices、API gateway;那站切邊界,這站談怎麼改掉造成耦合的條件
- 接著看 ←Frontend System Design: Performance API, Chrome, React Profiler · 量出瓶頸之後,那站給 bundle 切分、渲染策略等可以拿來改的選項
- 相關 —How to scale WebSockets to millions of connections · 共用 WebSocket、stateless、horizontal scaling:一站講後端怎麼擴,一站講前端架構怎麼接
- 相關 —Keep Those WebSocket Connections Alive! · 共用 WebSocket、race condition:一站在系統設計層選型,一站在程式碼層保活