資深前端的 15 個核心心智模型:從瀏覽器渲染路徑到微前端架構
文字解析 · 1 支影片 · 產生於 2026-10-01 00:54
章節(17)
1. Outline
- 起點 · 15 Frontend Concepts Every Senior Dev Has Mastered
以瀏覽器的關鍵渲染路徑為地基,依「量測 → 網路優化 → 資料建模 → 渲染位置 → 組織架構」的順序,把 15 個跨框架成立的前端心智模型串成一條推理鏈。
2. YouTuber 的思維推導
15 Frontend Concepts Every Senior Dev Has Mastered
theSeniorDev · 35m42s · 字幕 en · vision=on (使用者指定 vision=true;影片本身也大量出現「as you see here」「that's how it looks in the code」「in this picture」等指示語,說明高度依賴畫面上的流程圖、程式碼與 UI 截圖。) · YouTube
預估 vs 實際耗時
| 階段 | 預估 | 實際 |
|---|---|---|
| fetch | 6s | 2s |
| segment | 1m41s | 3m30s |
| shot | 1m16s | 10s |
| analyze | 15m00s | 15m00s |
| render | 5s | – |
作者的出發點是一個經驗觀察:他訪談過 300 多位資深前端工程師,背景與框架各不相同,唯一的共同點是同一組心智模型。於是他不從框架 API 講起,而是從瀏覽器把 HTML 變成像素的那條路徑(critical rendering path)開始,把它當作整支影片的骨架。接著他一層一層往上疊:先有路徑,才能量它(Core Web Vitals);要讓路徑變快,就從別重複下載(HTTP 快取)→ 距離變短(CDN)→ 位元組變少(內容協商壓縮)→ 根本先不載(lazy loading)→ 把 bundle 切開(bundle splitting)→ 連 CSS 也只送必要的(critical CSS)。
到這裡效能面走完,他把主題轉到資料建模:狀態越少越好(essential state),狀態的變更要收斂成單一純函式(reducer pattern),渲染量本身要受控(windowing)。最後把渲染工作搬去伺服器(SSR)、補回互動性(rehydration)、只對需要的區塊補(partial pre-rendering)、連 JavaScript 都省掉(server components),再把尺度從一頁拉到整個組織(micro frontends)。整條線的收束是他反覆講的第三個建議:不要背 15 個名詞,要看見它們彼此的關係——每一個新概念都是在補前一個概念留下的缺口。
推理鏈:每段留給下一段的線索
每一列是一段,箭頭後的字是這段留給下一段的線索。點段落標題跳到該段。
- 為什麼卡在 mid-level → 既然這 15 個模型是由底層往上長的,就得先有一個地基——瀏覽器到底怎麼把 HTML 變成螢幕上的像素。
- #1 關鍵渲染路徑 → 路徑講完了,但「快」是個相對詞——下一步需要能把這條路徑量化的指標。
- #2 Core Web Vitals → 指標有了,接下來的問題是怎麼改善它們;而路徑上最貴的一段是下載,所以第一個手段是別重複下載同一份檔案。
- #3 HTTP 快取與 TTL → 快取解決了「重複下載」,但第一次下載還是得從遠端伺服器跑一趟——距離本身還沒有被處理。
- CDN:把快取推到邊緣 → 距離縮短了,但傳輸的位元組數量本身還沒動——CDN 順手做的那個「壓縮」到底是怎麼談成的,就是下一個問題。
- #4 內容協商與壓縮 → 位元組變少了,但那些資源畢竟還是被送出去了;下一個更根本的問題是——有些東西根本不需要在一開始就送。
- #5 延遲載入與動態匯入 → 既然單一模組可以延後,那整個打包好的 bundle 顯然也不該一次全送——問題變成怎麼把它切開。
- #6 Bundle splitting → JavaScript 已經被切開了,但還有一種資源從第一段起就一直擋在路徑上、而且到現在都沒被處理——CSS。
- #7 Critical CSS → 到這裡效能面的路徑優化告一段落;但畫面畫得再快,如果背後的資料建模是亂的,重繪本身就會失控——主題該換到狀態了。
- #8 Essential state → 狀態被壓到最小之後,還有一個問題沒解:這些狀態該怎麼變更,才不會在複雜畫面上失控。
- #9 Reducer 模式 → 變更被收斂成一次計算了,但如果畫面上本來就掛著上千個節點,那一次計算引發的重繪還是會很慢——下一個要管的是渲染量本身。
- #10 Windowing 與可視區觀察 → 客戶端的渲染量已經被控制住了,但有一件事從頭到尾沒被質疑過——為什麼第一次渲染非得在客戶端做?
- #11 伺服器端渲染 → 使用者現在立刻看得到內容了,但那份 HTML 是死的——點下去沒有反應,這個缺口必須補上。
- #12 Rehydration → 互動性補回來了,但這個補法是整頁一起補;問題是同一頁裡其實有些區塊根本不需要互動。
- #13 Partial pre-rendering → 分區之後有個更激進的問題浮出來:那些完全不需要互動的區塊,是不是連 JavaScript 都不必送?
- #14 伺服器元件 → 到這裡單一應用內部能拆的都拆完了;最後一個尺度的問題是——當一個前端大到一個團隊放不下時該怎麼辦。
- #15 微前端與收尾
3. 逐段說明
15 Frontend Concepts Every Senior Dev Has Mastered
1. 為什麼卡在 mid-level 0:00–0:34
作者用 300 位資深前端工程師的共同點開場:不管背景與框架,他們都掌握同樣 15 個前端核心心智模型。多數開發者連五個都說不清楚,這正是卡在 mid-level 多年、面試一直失敗的原因。整支影片的承諾是把這 15 個模型講到能自己解釋。
推理作者不從「資深該會什麼技能」出發,而是從一份樣本反推:分析 300 多位資深前端工程師後發現,背景、公司、框架都不同,唯一穩定的共同點是同一組心智模型。既然是共同點,它就不是某個框架的知識,而是更底層的東西——這個推論決定了整支影片的講法:由瀏覽器機制往上講,框架只當範例。
AI 補充這裡有個作者沒說破的判準:他挑的 15 個概念全都是「跨框架仍然成立」的。React 換成 Vue、Webpack 換成 Vite,這 15 條都不用重學。這也解釋了為什麼「會用 React」不等於資深——框架 API 是實作細節,會隨版本淘汰,而心智模型不會。另外要注意樣本本身的偏誤:這 300 人來自作者自家的輔導計畫,「共同點」有一部分可能來自他們受過同一套訓練,不必當成客觀統計。
2. #1 關鍵渲染路徑 0:34–2:54
第一個也是整片的地基:critical rendering path 是瀏覽器從 HTML/CSS/JS 走到螢幕像素的完整步驟。伺服器給 HTML,瀏覽器由上往下讀,遇到 CSS/JS 就去下載、解析,組成 CSSOM 與 DOM,合成 render tree,再走 style → layout → paint → composite 四步,直到 first contentful paint。頭部的資源因此叫 render blocking。作者順帶給第一個資深建議:解釋事情要從瀏覽器機制講起,框架只是實作範例。


推理因為上一段確立了「由底層往上長」,作者就把 critical rendering path 放在第一個,並明說後面每個概念都會回頭引用它。他的講法是先給全景圖(server → HTML → CSS/JS/fonts → CSSOM/DOM → render tree → 四步渲染),再用一份具體的 HTML 文件把「哪些資源會擋住渲染」指出來——先建立骨架,再讓細節掛上去。
- Ccritical rendering path:DOM+CSSOM 合成 render tree,再 Style→Layout→Paint→Composite→ 畫地圖
- P看一份 HTML 找出哪些資源會擋住首次繪製:head 裡的 stylesheet 與同步 script 都是 render blocking→ 練習
- R四步渲染的成本排序:Layout 重算最貴、Paint 次之、只動 Composite(transform、opacity)最便宜→ 存+回想
AI 補充截圖裡的流程圖值得逐格看:CSS 走到 CSSOM、HTML 走到 DOM,兩者合流成 render tree,才進入 Style → Layout → Paint → Composite。這四步的分工是後面很多優化的根據:Layout 重算最貴,Paint 次之,只動 Composite(例如 transform、opacity)最便宜。另外作者這裡口誤了一處:DOM 是由 HTML 標記解析出來的,JavaScript 只是「可能會擋住解析、也可能修改 DOM」,不是「用 JavaScript 建 DOM」。第二張截圖把重點講得比聲音清楚——head 裡的三個 stylesheet 與兩個 script 是 render blocking,body 裡的 `<h1>First paint</h1>` 才是 FCP,紅色箭頭就是瀏覽器由上往下讀的順序。
「with the JavaScript that it will find in the hat section of the HTML document it will build the DOM」
3. #2 Core Web Vitals 2:54–5:53
有了渲染路徑,才能談怎麼量它。Core Web Vitals 是三個經驗指標:LCP 與 CLS 量初次渲染,INP 量互動後的重繪速度。作者用 F1 賽車的極速、敏捷、下壓力做類比,說明指標是用來跟業界平均對標的。接著把三個指標一一掛回關鍵渲染路徑:LCP 是渲染過程中最大元素出現的時刻,CLS 是瀏覽器連續截圖比對出的版面位移,INP 則是使用者互動 → state 更新 → reconciliation → 瀏覽器重繪的整段時間。


推理因為上一段留下了「快是相對的」這個缺口,作者引入 Core Web Vitals 作為經驗指標,並刻意用 F1 賽車的極速/敏捷/下壓力做類比:一個複雜系統無法用單一數字描述,得用幾個互補的指標。更關鍵的是他接著做的動作——把三個指標一一掛回上一段的路徑:LCP 是渲染過程中最大元素出現的時刻,CLS 是持續渲染中版面位移的累積,INP 則是路徑跑完之後、使用者互動觸發的那一輪重繪。這是他示範「概念要連起來」的第一個實例。
- CCore Web Vitals:LCP、INP、CLS 三個互補指標,各自量到渲染路徑的不同段落→ 畫地圖
- A三個 Core Web Vitals 像 F1 賽車的極速/敏捷/下壓力:複雜系統不能用一個數字描述→ 批判類比
- E門檻值:LCP 好 ≤2.5s 差 >4s;INP 好 ≤200ms 差 >500ms;CLS 好 ≤0.1 差 >0.25→ 存+演練
- RLighthouse 是 lab data(同一台機器模擬網路),Google 排名看的是 CrUX 的 field data,兩者常對不上→ 存+回想
AI 補充截圖上的門檻值比口述精確,值得記下來:LCP 好 ≤ 2.5 秒、差 > 4 秒;INP 好 ≤ 200 毫秒、差 > 500 毫秒;CLS 好 ≤ 0.1、差 > 0.25。作者說 LCP 與 CLS「在初次渲染時量測」,這對 LCP 大致成立,對 CLS 並不準確——CLS 會累積整個頁面生命週期的位移,你捲到一半才插進來的廣告一樣會扣分。另外要補一個作者略過的層次差別:他示範的 Lighthouse 報告是實驗室數據(lab data,同一台機器、模擬網路),Google 排名實際看的是 CrUX 蒐集的真實使用者數據(field data),兩者常常對不上。還有一點值得記在心裡:INP 的定義涉及「state 更新 → 重繪」這條鏈,而這條鏈正是後面談狀態管理與渲染量控制時要動刀的地方。
「the LCP and the CLS are basically measured during the initial render」
4. #3 HTTP 快取與 TTL 6:25–9:30
要改善這些指標,最直接的手段是別重複下載。作者先把快取往上抽象成 memoization:同樣輸入就重用上次輸出,這個模式在程式、資料庫、檔案各層都成立。檔案層的快取多了 TTL(視為新鮮的時間)。接著走一次完整流程:瀏覽器先向伺服器要檔案,回應依 cache-control 存進快取;TTL 內直接用快取,過期後拿 ETag 去問伺服器有沒有新版,這就是 cache invalidation。最後用 Walmart 的 CSS 檔在 DevTools 裡驗證 max-age 真的存在。


推理作者在講 HTTP 快取之前先往上抽象一層,這個順序是刻意的:他先說快取的底層模式是 memoization——同樣輸入就重用上次輸出——並指出這個模式在程式、資料庫、檔案各層都成立。有了通用模式,HTTP 快取就只是它在檔案層的特例,多了一個 TTL。接著他才走完整條時序:首次請求 → 伺服器回應並依 cache-control 存進快取 → TTL 內直接命中 → 過期後拿 ETag 去問「還新鮮嗎」。最後用 Walmart 的真實回應驗證這些標頭確實存在。
- CTTL:快取資料被視為新鮮、可直接重用的時間;過期後拿 ETag 問伺服器「還新鮮嗎」→ 畫地圖
- AHTTP 快取就是 memoization 在檔案層的特例:同樣輸入重用上次輸出,只多了一個 TTL→ 批判類比
- EWalmart 回應:Cache-Control: public, max-age=30541039(秒,約 353 天),對得上 Expires 日期→ 存+演練
- RTTL 設很長的前提是檔名帶雜湊(app.4f2a9c.js),否則使用者會卡在舊版本→ 存+回想
AI 補充第一張截圖是時序圖的起手式(Browser/Browser Cache/Server 三條泳道),完整動畫在影片裡才看得到,但泳道本身已經說明了關鍵:快取是攔在瀏覽器與伺服器之間的一層,命中就不必走到最右邊。第二張 Walmart 的 DevTools 值得逐行讀:`Cache-Control: public, max-age=30541039`、`Content-Encoding: br`、`Expires: Tue, 29 Sep 2026`,三個標頭剛好對應本段與下兩段的主題。這裡作者說錯了單位——`max-age` 的單位是秒不是毫秒,30541039 秒約等於 353 天,跟旁邊的 Expires 日期正好對得上;若真是毫秒就只有 8.5 小時,跟畫面矛盾。另外要補一個作者沒說、但實務上最常踩的坑:TTL 設很長的前提是檔名帶雜湊(`app.4f2a9c.js`),改版時檔名跟著變,舊快取自然不會被用到;沒有這個前提就長 TTL,使用者會卡在舊版本。
「set that max age to 3 million milliseconds」
5. CDN:把快取推到邊緣 9:30–10:36
快取政策通常不用自己設,CDN 會代勞。CDN 把靜態資源推到全球 edge locations,使用者從最近的節點拿檔案;每次重新編譯後的 JS bundle 與 CSS 都會發到 CDN,CDN 實際上取代了原伺服器的角色。除了距離變短,它還自帶合理的快取政策與壓縮,作者認為這是網頁效能投資報酬率最高的第一步。壓縮怎麼談成的,就是下一個概念。

推理作者的推進方式是「把上一段的機制搬到別的位置」:快取政策其實多半不用自己寫,因為 CDN 會代勞;而 CDN 做的事在概念上就是把快取往使用者的方向推到全球各地的邊緣節點。他特別點出一個角色轉換——每次重新編譯後的 JS bundle 與 CSS 都發到 CDN,於是 CDN 實際上取代了原伺服器面對使用者的角色。他把 CDN 稱為網頁效能投資報酬率最高的第一步,理由是它同時帶來距離、快取政策與壓縮三件事。
- CCDN:把靜態資源複製到全球邊緣節點,使用者連最近的點;同時帶來距離、快取政策、壓縮三件事→ 畫地圖
- E跨洲來回延遲通常 150–300 毫秒,同城是個位數毫秒;頁面串十幾個請求時差距是決定性的→ 存+演練
AI 補充截圖把「為什麼變快」講得比聲音清楚:橘色的 origin server 只有一個(北美),藍色的 CDN server 散佈在各大洲,每個使用者連的是離自己最近的藍點,橘線只在邊緣節點回源時才走。這裡值得補一個作者省略的量級感:跨洲的來回延遲通常是 150–300 毫秒,而同城是個位數毫秒;一個頁面要串接十幾個請求時,這個差距是決定性的。另外「CDN 取代伺服器」要加個限制條件——它取代的只是靜態資源的分發,動態 API 請求仍會回到你的伺服器(除非你另外用邊緣運算)。順帶一提,上一段 Walmart 截圖裡的 `Server-Timing: cdn-cache;desc=HIT` 正是 CDN 命中的證據,那條標頭現在讀得懂了。
6. #4 內容協商與壓縮 10:36–12:39
CDN 自帶的壓縮,機制是 content negotiation:瀏覽器在 accept-encoding 標頭裡告訴伺服器它接受哪些編碼(gzip、br/Brotli,後者效率更高),伺服器挑一個有的版本送出,並在 content-encoding 標明。之所以划算,是因為解壓縮比多下載那些位元組便宜。作者在此給第二個資深建議:前端到資深必須有紮實的資料層基礎——HTTP、TCP、HTTPS、REST、GraphQL、WebSocket,否則會變成致命盲點。

推理作者把上一段留下的「壓縮從哪來」補完:瀏覽器在 Accept-Encoding 標頭裡列出自己接受的編碼,伺服器挑一個手上有的版本送出,並在 Content-Encoding 標明用了哪個。他接著給出這件事划算的理由,而且是用算的而不是用感覺的——解壓縮的 CPU 成本遠低於多傳那些位元組的網路成本。這一段也是他第二個資深建議的落點:能不能講清楚這種協商,反映的是你對資料層(HTTP/TCP/HTTPS/REST/GraphQL/WebSocket)的掌握程度。
- Ccontent negotiation:瀏覽器用 Accept-* 標頭說自己接受什麼,伺服器挑一個手上有的版本回並標明→ 畫地圖
- EChrome 送 Accept-Encoding: gzip, deflate, br, zstd;伺服器備三個版本挑一個回→ 存+演練
- R回應要附 Vary: Accept-Encoding,否則中間快取可能把 Brotli 版本餵給不支援的客戶端→ 存+回想
AI 補充截圖把機制講得非常乾淨:左邊 Chrome 送出 `Accept-Encoding: gzip, deflate, br, zstd`,右邊伺服器同時備有 `/style.css`、`/style.css.gzip`、`/style.css.br` 三個版本,挑一個回。注意畫面上瀏覽器實際送的清單裡有 `zstd`,比作者口述的「只有 gzip 和 Brotli」多一個——Zstandard 從 2024 年起已被 Chrome 與 Firefox 支援,壓縮率接近 Brotli 但速度快得多。同一張圖還有一個容易被忽略的細節:`Accept-Language: en-GB,en-US;q=0.9` 說明內容協商不只協商壓縮,也協商語言與格式(`Accept: text/css`),這是同一個機制的三種用途。實務上還有第三個維度作者沒提:伺服器回應時應該附上 `Vary: Accept-Encoding`,否則中間的快取層可能把 Brotli 版本餵給不支援它的客戶端。
「broadly with broadly being actually the most efficient one」
7. #5 延遲載入與動態匯入 12:39–14:46
壓縮只是讓東西變小,更狠的做法是根本先不載。lazy loading 的反面是 eager loading:一次載完四張圖。改成捲到才載,效率立刻不同。JavaScript 同樣可以延遲載入,靠的是 dynamic import:傳統 static import 在 build time 就被 bundler 收進主 bundle,成為擋住渲染的關鍵資源;動態匯入則是在 runtime、使用者按下按鈕之後才去抓那塊 chunk 並執行,初始要跑的 JavaScript 因此變少。


推理作者先用對照法定義:延遲載入的反面是 eager loading,一次把四張圖全載完。改成捲到才載,成本立刻不同。接著他把同一個想法推廣到 JavaScript,這一步需要一個機制上的區分——static import 在 build time 就被打包進主 bundle,成為擋住渲染的關鍵資源;dynamic import 則在 runtime 才去抓那塊 chunk。這個「編譯期 vs 執行期」的分界是整段的關鍵,也是後面切分 bundle 的前提。
- Cdynamic import:import() 在執行期才抓模組、回傳 Promise,打包工具自動切成獨立 chunk→ 畫地圖
- P把點了才需要的功能改成動態匯入:await import("./modal") 解構出具名匯出再呼叫→ 練習
- R圖片延遲載入有原生解法 <img loading="lazy">,不必寫 JavaScript→ 存+回想
AI 補充第一張截圖標了「1MB」與「Loaded On User Scroll」:上面兩張圖已渲染,下面兩個位置是 spinner,捲到才載。第二張是最小可行的動態匯入寫法——`button.addEventListener("click", async () => { const {openModal} = await import("./modal"); openModal({step:1}); })`。三個細節值得注意:`import()` 回傳 Promise 所以要 await;解構出的是模組的具名匯出;這行程式碼會讓打包工具自動把 `./modal` 切成獨立 chunk,不需要額外設定。要補充作者沒說的部分:圖片的延遲載入現在有原生解法,`<img loading="lazy">` 不必寫 JavaScript;而延遲載入不是無代價的——把資源延到互動當下才抓,使用者會多等一次網路來回,所以會影響互動回應(見第 3 段的 INP)。實務折衷是在滑鼠移上去或元件即將進入視窗時就先預抓。
術語:module bundler
8. #6 Bundle splitting 14:46–16:40
把延遲載入的想法套到整個 bundle,就是 bundle splitting。Webpack 之類的 bundler 原本把所有模組打成單一 production bundle,好處是不用在 head 塞一堆檔案,壞處是每一頁的使用者都得下載、解析全部 JavaScript。切分後,相依套件進 vendor.js,其餘依路由切成 login / home / dashboard,進 dashboard 的人不必載 login 的程式碼。作者的第三個資深建議在此:用系統、元件、關係去思考,不要背誦——關鍵渲染路徑同時牽連 bundler 與 Core Web Vitals,這種連結才是記得住的原因。

推理作者先說明單一 bundle 為什麼曾經是進步:把幾百個模組合成一個檔案,才解決了「不可能把所有檔案都寫進 head」的問題。但同一個決定在規模變大後就變成瓶頸——每一頁的使用者都得下載、解析、執行全部 JavaScript,而這些全都發生在關鍵渲染路徑上。切分的邏輯因此很自然:相依套件變動少,抽成 vendor;其餘依路由切開,只載當前路由要的。這一段也是他第三個資深建議的落點:不要背 15 個名詞,要看見它們的關係——關鍵渲染路徑同時牽連打包工具與 Core Web Vitals,這種連結才是記得住的原因。
- Cbundle splitting:相依套件抽成 vendor,其餘依路由切開,每頁只下載自己要的 JS→ 畫地圖
- Evendor 幾乎不變,所以它的長 TTL 能跨版本存活;發新版使用者只重抓小小的路由 chunk→ 存+演練
AI 補充截圖把結構講得很完整:左邊是一堆互相依賴的 JS 模組,中間是 Webpack 圖示,右邊的 Build 方框裡是 `common.js` 加上 `/login`、`/home`、`/dashboard`、`/settings` 四個路由各自的檔案。這裡有個作者沒展開的關鍵理由,也是把相依套件單獨抽出來的真正動機:vendor 幾乎不變,所以它的長 TTL 快取能跨版本存活;你改自己的程式碼發新版時,使用者只需重新下載那個小小的路由 chunk,vendor 仍然命中快取(見第 4 段)。切分也有反效果要注意:切得太細會產生瀑布式的相依請求,而共用模組若沒被正確抽出會在多個 chunk 裡重複。在 React 的實作上,路由層的切分幾乎就是每個路由元件套一層 `React.lazy` 加 `<Suspense>`。
術語:vendor bundle
9. #7 Critical CSS 16:40–19:20
JavaScript 拆完了,CSS 呢?CSS 是設計上就 render blocking:瀏覽器無法預知哪條規則會影響首個元素,只好把 CSS 全部算完才渲染,於是大型應用的 CSS 本身成為瓶頸。Critical CSS 的做法是只挑 above-the-fold(桌機與手機視窗不同)需要的樣式:bundler 外掛用 Puppeteer 之類的無頭瀏覽器在指定視窗預渲染,算出實際用到的選擇器,把這部分內聯進 HTML(不多一次請求、讀起來極快),其餘 CSS 才用 link 從 CDN 載入且不擋渲染。想法簡單,但需要成熟工具與大量測試,因此多見於 Walmart、Amazon 這種大型電商。


推理作者先解釋為什麼 CSS 沒辦法像 JavaScript 那樣用 async 隨便延後:瀏覽器無法預知哪一條規則會影響第一個元素,只好把 CSS 全部算完才敢畫。這是設計取捨而非缺陷。既然不能不要,那就只送必要的——他把 CSS 依「是否影響首屏」切成 critical 與其餘。難點在於怎麼知道哪些是必要的,他給的答案是自動化:用無頭瀏覽器在指定視窗預渲染一次,收集實際被命中的選擇器。這個推理形狀跟上一段一樣,都是「切開 + 只送必要的」,只是判斷依據從路由換成了視窗。
AI 補充第一張截圖點出一個容易被忽略的前提:above the fold 在桌機與手機上是不同的集合,所以 critical CSS 必須依裝置分別產生,這也是這個技巧比切 JavaScript 麻煩的原因之一。第二張是完整的擷取流程——CSS 進入 module bundler,bundler 呼叫 Puppeteer 做 pre-render,回饋出被命中的規則,抽成獨立的 Critical CSS。之後 critical 的部分內聯進 HTML(省掉一次請求、而且與 HTML 同時抵達),其餘用非阻擋的方式從 CDN 載入。要補三件作者沒說的事:一是內聯的 CSS 不會被快取,所以 critical 必須夠小(一般抓 14KB 以內),太大反而拖慢 HTML 本身;二是「其餘 CSS 不阻擋」的標準寫法是 `<link rel="preload" as="style" onload="this.rel='stylesheet'">`;三是這條路線正在被更根本的方案取代——CSS Modules 與 Tailwind 這類工具讓每個路由的樣式一開始就只有自己那份,等於在源頭避免了問題。作者說它主要用於 Walmart、Amazon 這種大型網站,正確的理由是它需要成熟工具鏈與大量回歸測試,抽錯規則會直接造成首屏跑版。
10. #8 Essential state 19:34–22:06
從這裡話題從效能轉到資料建模。Essential state 是「渲染某個 UI 所需的最小資料表示」。作者用汽車工程師看車的比喻:外行看外觀,工程師看內部系統;資深前端看 Netflix 會直接看到元件結構與狀態,像有 X 光。以購物車 UI 為例,新手會把商品資訊、原價、折扣價、折扣文字、小計、運費、稅、總計全部放進 state;實際上只需要商品資訊、折扣率、運費、稅率,其餘都能算出來。狀態越少越好,因為狀態會造成重繪、也讓測試變難。


推理作者用一個換位的比喻切入:一般人看車看的是外觀,汽車工程師看到的是內部系統。資深前端看 UI 也一樣,看到的不是版面而是元件結構與狀態。接著他把這個抽象能力變成一道可作答的題目——這個購物車 UI 的 essential state 是什麼?新手會把畫面上每個數字都當成狀態,正確答案是只留無法推導的那幾項,其餘全部算出來。他給的理由不是美感而是後果:狀態會造成重繪、會讓測試變難,所以越少越好。
- Cessential state:渲染 UI 所需、且無法從其他資料推導的最小集合;其餘全部算出來→ 畫地圖
- A資深前端看 UI 像汽車工程師看車:看到的不是外觀而是內部系統(元件結構與狀態)→ 批判類比
- E購物車畫面七八個數字,essential 只有四項:商品資訊、折扣率、運費、稅率,其餘都是函式→ 存+演練
- P盤點一個元件的狀態:逐項問「能不能從別的狀態算出來」,能的就刪掉改成計算→ 練習
AI 補充兩張截圖剛好是題目與答案。第一張是原始的購物車:原價 $20.39、劃掉的 $23.99/$59.99、折扣文字、小計 $20.39、運費 $4.99、稅 $1.83、總計 $27.21。第二張把每一項都用紅框標出來,逼你面對「這些看起來都像狀態」的直覺。收斂後只剩四項:商品資訊(含原價)、折扣率、運費、稅率——其餘每一個數字都是這四項的函式。這裡值得把作者的理由講得更精確:多餘狀態真正的危險不是效能,而是它們可以彼此矛盾。如果折扣價與總價各自存一份,任何一次漏更新都會讓畫面顯示一個算術上不可能的組合,而且這種 bug 無法用型別檢查抓到。反過來,凡是能算的就算,畫面就不可能自相矛盾——這是所謂 single source of truth 的實質意義。實務上的取捨是計算成本:真的很貴的推導值可以用 memoization(見第 4 段)快取,但快取的是計算結果,不是又存一份狀態。
術語:derived state
11. #9 Reducer 模式 22:06–24:55
狀態壓到最小之後,還要處理它怎麼變。傳統做法是使用者動作 → 舊 state → 新 state → 重繪,但在 Intuit 會計軟體那種複雜 UI 上,一個全域開關會影響五六個元件,得沿著元件樹逐層更新、把 state 往上提再 prop drilling,既繁瑣又難維護。Reducer 模式把它換成單一 pure function:吃舊 state 與 action、算出新 state,元件各自訂閱新 state。上千次分散修改變成一次可測試、無副作用、確定性的計算。作者強調中階開發者談 Zustand/Redux,資深談的是背後的模式——掌握模式後學任何新函式庫幾乎是瞬間的事。


推理作者先把最小的循環畫出來:使用者動作 → 舊狀態 → 新狀態 → 重繪。然後把它放進一個壓力測試——Intuit 的會計軟體那種畫面,一個全域開關會同時影響五六個元件。傳統做法是沿著元件樹逐層更新,為此得把狀態往上提、再一路 prop drilling 傳下去,既繁瑣又脆弱。他的解法是把「散在各處的多次修改」換成「集中的一次計算」:所有動作都送進同一個純函式,由它算出新狀態,元件各自訂閱結果。上千次分散的修改變成一次可測試、無副作用、確定性的計算。
- Creducer pattern:所有變更集中到 (舊狀態, action) → 新狀態 的純函式,元件各自訂閱結果→ 畫地圖
- Rreducer 不是免費的:簡單區域狀態硬套只是多寫樣板碼,價值在「多個元件受同一次變更影響」時才出現→ 存+回想
AI 補充兩張截圖正好是改造前後。第一張是傳統循環:User Action → Old State → New State → Re-Render,四個節點連成環。第二張多了一個 Reducer 方框把 Old State 罩住,User Action 從外面射進來——差別就在於狀態的變更被關進了一個明確的邊界,外面只能送 action 進去,不能直接改。這裡值得補作者略過的一步:reducer 之所以能保證確定性,關鍵在於它是純函式而且回傳新物件而非就地修改;一旦你在 reducer 裡改了傳進來的 state(或呼叫了 API),時光旅行除錯、樂觀更新回滾、單元測試這些好處會同時失效。他說中階談 Zustand/Redux、資深談模式,這個對比可以再推一步:真正該問的是這個函式庫怎麼處理不可變性、怎麼決定哪些元件要重繪、以及訂閱的粒度有多細——這三個問題的答案決定了它在大型應用裡的表現,而它們都與函式庫名稱無關。也要誠實補一句:reducer 不是免費的,簡單的區域狀態硬套 reducer 只會多寫樣板碼,它的價值在「多個元件受同一次變更影響」時才顯現。
術語:lifting state up
12. #10 Windowing 與可視區觀察 24:55–27:35
重繪變快之後,還有一個沒解掉的 Core Web Vital:INP,Google 建議在 200 毫秒內,作者認為 100 毫秒才算好。像 Pinterest 那種無限捲動的動態牆,DOM 元素破千後瀏覽器本身就開始吃力,記憶體與 CPU 壓力讓應用即使沒做什麼也變慢。Windowing(list virtualization)只掛載視窗內的元素、其餘卸載,並多留一兩個緩衝以免捲動時來不及。判斷進出視窗用原生的 Intersection Observer,實務上多半直接用 react-virtualized 之類的函式庫。作者提醒 Intersection Observer 是常見面試題。


推理作者在這裡回收了第 3 段留下的伏筆:三個 Core Web Vitals 裡,INP 一直還沒有對應的解法,而它多半來自重繪太慢。他給出量化門檻(Google 建議 200 毫秒,他自己要求 100 毫秒),接著指出典型的犯罪現場——Pinterest 那種無限捲動的動態牆。問題的形狀是:畫面上大部分元素其實不可見,卻仍佔著 DOM 節點與記憶體。既然不可見,就不該存在,於是解法就是只掛載視窗內的元素、其餘卸載。判斷進出視窗要可靠,就需要一個原生 API 而非捲動位置的估算。
AI 補充兩張截圖是問題與解法。第一張整片黃色 Item 塞滿畫面,就是「全部都在 DOM 裡」的樣子;第二張只有中間六個是黃色(已掛載),上下都是灰色(已卸載),旁邊三行字把規則講得比口述精確:只渲染螢幕上的元素、隨捲動掛載與卸載、用 Intersection Observer 維持穩定。要補作者略過的關鍵細節:卸載的元素必須留下等高的佔位空間,否則捲軸長度會不斷跳動;如果每列高度不一,還得先估算再量測校正,這正是虛擬清單函式庫真正在解的難題。他提的 react-virtualized 現在通常換成同作者的 react-window 或 TanStack Virtual(更小、支援動態高度)。另外,Intersection Observer 的優勢不只是方便:它在瀏覽器內部非同步計算交集,不會像 `getBoundingClientRect` 那樣強制同步排版,所以捲動時不會掉幀。他提的「上千個 HTML 元素」只是概略感覺,實際門檻取決於每個節點的複雜度與 CSS 成本。
術語:viewport
「if you go after the thousand HTML elements even the browser starts to suffer」
13. #11 伺服器端渲染 27:35–29:42
前面都在優化客戶端渲染,但問題的根源是現代應用送出的 HTML 只有一個空的 root div。FCP 只畫出一個空 div,要等 bundle、React、React DOM 下載執行完才有第一次有意義的繪製,中間就是白畫面(white screen of death),在慢裝置或慢網路上使用者會以為網站壞了。SSR 把這段渲染搬回伺服器:伺服器跑 React、直接向資料庫取資料、預先產出完整 HTML 再送給客戶端。使用者立刻看到內容,但那是靜態的、還不能互動。


推理作者從症狀反推:現代單頁應用送出的 HTML 其實只有一個空的 root div,所以第 2 段講的 FCP 只畫出一個空容器,真正有內容的畫面要等 bundle、React、React DOM 下載並執行完才出現。中間那段空白在慢裝置或慢網路上長到讓使用者以為網站壞了。既然瓶頸是「渲染工作在客戶端做」,最直接的解法就是把它搬回伺服器——伺服器跑框架、直接向資料庫取資料、產出完整 HTML 再送出。他刻意把這說成「回到過去」,因為這確實是伺服器渲染時代的做法,只是現在用同一份元件程式碼。
- Cserver-side rendering:伺服器跑元件、直接取資料、產出完整 HTML;改善「看得到」不改善「能互動」→ 畫地圖
- ESPA 的 HTML 只有 <div id="root"></div>:FCP 畫的是空容器,FMP 要等 bundle 執行完→ 存+演練
AI 補充第一張截圖用一個最小的 React 頁面把問題釘死:`<div id="root"></div>` 被標成 First Contentful Paint,下面那段載入 React 並呼叫 `root.render(<App/>)` 的 script 才被標成 First Meaningful Paint——兩個標記之間的距離就是使用者盯著白畫面的時間。第二張是 SSR 的起手式(Client 送出 GET,Server 端有 Initial Render 方框)。要補一個作者沒說清楚的重點:SSR 改善的是「看得到」的時間,不是「能互動」的時間,而且它把成本轉嫁到了伺服器——每個請求都要跑一次渲染,流量大時伺服器成本與回應時間(TTFB)都會上升,所以實務上常搭配快取或改用建置期的靜態產生(SSG)。另外 SSR 的資料抓取發生在伺服器內網,通常比從瀏覽器打 API 快很多,這是它常被低估的第二個好處。
術語:server-side renderingclient-side rendering
14. #12 Rehydration 29:42–30:28
SSR 送來的 HTML 沒有互動性,使用者亂點會變成 rage clicking,補上互動的機制就是 rehydration:仍然下載並解析 bundle,在客戶端建立虛擬 DOM 後執行 hydrate,把事件與狀態接回既有的 markup,網站才真的能點。常見的坑是 hydration error,成因不只一種。

推理作者用使用者行為描述缺口:畫面看起來好了,點下去沒反應,使用者開始暴躁地連點(rage clicking)。要補上互動,客戶端還是得下載並解析 bundle,在記憶體裡建出對應的虛擬結構,然後執行 hydrate——把事件監聽與狀態接回伺服器已經送來的那份 markup,而不是重新畫一次。關鍵在於「接回」而非「重畫」:markup 已經在了,客戶端只是把它認領下來。他也順帶點出這個機制最常見的故障:hydration error。
AI 補充截圖把整條鏈完整畫出來:伺服器端的 Initial Render → Data Fetching → HTML(旁邊接著 Data Layer API),送到 Client 做 Initial Render 與 Display(右邊出現 Walmart 的靜態頁面),然後往下才是 Rehydration。這張圖說明了一件口述沒強調的事——使用者看到畫面與能互動之間,隔著一整段 bundle 下載與執行的時間,SSR 只縮短了前半段。這也解釋了 hydration error 的成因:伺服器產出的 HTML 與客戶端第一次渲染的結果必須完全一致,任何隨機值、`Date.now()`、`window` 判斷或只在客戶端才有的語系資料,都會讓兩邊對不上,React 就會警告並丟掉伺服器那份重畫,反而更慢。實務上的判斷法是把這類差異延後到 hydrate 之後再處理(例如放進 effect),而不是在渲染時直接讀。補一個版本細節:作者說的 hydrate 指令在 React 18 之後是 `hydrateRoot`,舊的 `ReactDOM.hydrate` 已被淘汰。這條鏈的長度也正是後面兩段要繼續縮短的目標。
「run the hydrate command on the client」
15. #13 Partial pre-rendering 30:28–31:42
SSR 全頁預渲染、rehydration 全頁補互動,兩端之間還有折衷:partial pre-rendering 讓同一頁同時採用不同渲染策略——盡量靜態預渲染,只把真正動態的區塊留給客戶端渲染與 hydration,由框架依互動需求決定。目標仍是優化關鍵渲染路徑:盡快出現、盡快可互動。代價是複雜度很高,通常交給 Next.js 或 Nuxt 處理,適合對效能極敏感的電商。

推理作者的推進方式是把粒度變細:既然 SSR 是整頁預渲染、rehydration 是整頁補互動,那自然的下一步就是讓同一頁同時採用不同策略——能靜態預渲染的盡量靜態,真正動態的部分才留給客戶端。決定權交給框架,依你標示的互動需求自動分區。他強調目標仍然沒變,還是那條關鍵渲染路徑:盡快出現、盡快可互動。同時他誠實地標出代價——這是本片最複雜的渲染策略,通常得靠 Next.js 或 Nuxt 這種框架才管得動。
AI 補充截圖把分區講得比口述清楚:一個 acme.com 的商品頁上,Navbar 標著 S(Static or Revalidated),Cart 與 Recommended 標著 D(Dynamic),Product Information 也是靜態的。這張圖點出一個口述沒說的關鍵——動態的通常是「跟這個使用者有關」的部分(購物車、個人化推薦),靜態的是「對所有人都一樣」的部分。這正是分界的實務判準。要補一個機制細節:真正的 partial pre-rendering 不是回退成兩次請求,而是伺服器先立刻送出含有靜態外殼與佔位的回應,再用串流把動態區塊的內容補進同一個連線裡,所以使用者看到的是骨架先出現、內容逐塊填入。這需要串流式 SSR 與 Suspense 邊界的支援,也是它「複雜」的真正來源。另外,S 標籤上寫的是「Static or Revalidated」,意味著靜態內容也可以有 TTL、在背景重新產生——這其實就是第 4 段的快取模式被套用到渲染結果上。
術語:static rendering
16. #14 伺服器元件 31:42–33:00
既然可以分區,那不需要互動的元件連 JavaScript 都不必送。Server components 檢查元件樹裡誰在監聽事件、誰會改變狀態;不需要互動的就只送 markup、零 JavaScript、不做 hydration,bundle 因此更小。這是框架層的機制:Next.js 預設全部在伺服器渲染,除非標成 client component,那部分的 JavaScript 才會被抽出送到客戶端並 hydrate。效果是 SSR 讓初次渲染快,server components 讓 rehydration 也快。

推理作者把判準說得很具體:檢查元件樹裡每個節點,它有沒有在監聽使用者事件、需不需要對事件反應、會不會改變狀態。答案全是否的,就只送 markup、零 JavaScript、也不做 hydration,bundle 因此更小。他接著指出這是框架層的預設值反轉——Next.js 預設全部在伺服器渲染,除非你明確標成客戶端元件。最後他把兩件事對起來作為收束:SSR 讓初次渲染快,server components 讓 rehydration 也快,一前一後把第 13、14 段的兩個瓶頸都補上了。
AI 補充截圖是「Client Component Tree」:A、B、D、E、F 是灰色,C、G、K、J 是黃色並用黃線相連。這張圖說明了一條口述略過但非常重要的規則——互動性會沿著樹往下傳染:C 一旦被標成客戶端元件,它底下的 G、K、J 就全部進入客戶端範圍。這是實務上決定標記位置的關鍵:`"use client"` 要盡量往葉節點放,標在根附近等於整棵樹都變成客戶端元件,好處歸零。另一個作者沒提的重點是伺服器元件真正的第二個好處:它們在伺服器上執行,可以直接讀資料庫或用只存在於伺服器的密鑰,資料抓取不必再繞一趟 API,而且這些程式碼與相依套件永遠不會出現在客戶端 bundle 裡(一個只在伺服器元件用到的 Markdown 解析套件,客戶端一個位元組都不會下載)。限制則是伺服器元件不能用 state、effect 或事件處理器,也不能被序列化成 props 傳給客戶端元件的內容必須是可序列化的資料。
17. #15 微前端與收尾 33:00–35:42
最後一個概念把尺度從一頁拉到整個組織。微前端把 UI 拆成多個獨立應用:以 Walmart 為例,頂部搜尋列、分類、Deals、精選商品各自是一支應用,可以用不同框架,由 shell 統一注入全域狀態(位置、語言、深色模式、主題、認證)並維持視覺一致。每個微前端是公司裡的小公司,有自己的 PM、BFF、微服務,能獨立部署。代價是執行期載入讓速度稍慢,換來的是開發速度與團隊可擴展性。結尾作者建議接著看前端架構模式與前端轉後端的主題。

推理作者把拆分的邏輯從技術層拉到組織層:以 Walmart 首頁為例,頂部搜尋列、分類、Deals、精選商品各自可以是獨立應用,甚至可以用不同框架,由一個 shell 統一注入全域狀態(位置、語言、深色模式、主題、認證)並維持視覺一致。他點出這個架構真正在優化的東西不是效能——執行期載入反而讓速度稍慢——而是開發速度與團隊可擴展性:每個微前端像公司裡的小公司,有自己的 PM、BFF 與微服務,能獨立部署。最後他把整支影片收在一句話上:知道這些概念還不夠,重點是看見它們彼此的關係。
AI 補充截圖標題就叫「The Shell」:Walmart 首頁被彩色框線切成幾塊——黃框的搜尋列、綠框的分類列、紅框的商品區、藍框的推薦區,外圍那圈灰底就是 shell 本身。畫面把 shell 的角色講得很清楚:它是容器,不是內容。要補作者略過的三個實務重點。第一,微前端的代價比他說的「稍慢」更具體:每個微前端各自打包意味著 React 之類的共用相依可能被下載多次,所以實務上一定要做相依共享(Module Federation 的核心功能就是這個)。第二,「可以用不同框架」在技術上成立,在實務上幾乎總是錯的選擇——那會讓共用元件、狀態同步與人員流動全部變貴;這個能力真正的價值是漸進遷移,而不是長期並存。第三,判斷該不該用微前端的標準是組織而非技術:如果你只有一個團隊,微前端帶來的協調成本會遠大於收益,這是它最常被誤用的地方。最後回到作者的收尾建議——這 15 個概念的排列本身就是一條推理鏈:量測指向瓶頸,瓶頸指向優化,優化到極限後改變架構,架構改變後再改變組織。
術語:frontend monolith
4. 總結
作者從一個觀察出發:300 多位資深前端工程師的共同點不是框架,而是同一組心智模型。於是他先立地基——critical rendering path 說明瀏覽器如何從 HTML 走到像素,並指出 head 裡的資源會阻擋渲染。有了路徑才能量它,Core Web Vitals 的 LCP/INP/CLS 分別掛在路徑的不同位置上。接著沿著路徑逐段開刀:HTTP 快取消掉重複下載、CDN 縮短物理距離、內容協商壓小位元組、lazy loading 讓東西一開始就不送、bundle splitting 把 JavaScript 依路由切開、critical CSS 只內聯首屏需要的樣式。效能面到此為止,主題轉向資料建模:essential state 要求只留無法推導的最小狀態,reducer pattern 把散落的變更收斂成一次純函式計算,windowing 則把 DOM 節點數壓下來,補上前面留著沒解的 INP。再往下是質疑渲染的位置:SSR 把首次渲染搬回伺服器解決白畫面,rehydration 補回互動性,partial pre-rendering 讓同一頁分區採用不同策略,server components 更進一步對非互動區塊連 JavaScript 都不送。最後 micro frontends 把切分的尺度從一頁拉到整個組織——用執行期的一點速度損失,換團隊的獨立部署與開發速度。整條鏈的形狀是:量測指向瓶頸 → 瓶頸指向優化 → 優化到極限就改變架構 → 架構改變後再改變組織。
勘誤總整理
確定錯誤/已過時見仁見智(取決於版本或情境)
| 段落 | 原話(transcript 逐字) | 說明 |
|---|---|---|
| 2. #1 關鍵渲染路徑 1:14 |
「with the JavaScript that it will find in the hat section of the HTML document it will build the DOM」 | DOM 是瀏覽器解析 HTML 標記本身建出來的,不是用 head 裡的 JavaScript 建的。head 裡的同步 script 反而會暫停 HTML 解析、延後 DOM 建構。作者這裡把 CSS→CSSOM 的對應關係誤套到 JS→DOM 上(同一張投影片的箭頭其實也是 HTML→DOM)。 依據: HTML Living Standard, 8.1 Parsing HTML documents;MDN「Critical rendering path」 |
| 4. #3 HTTP 快取與 TTL 9:09 |
「set that max age to 3 million milliseconds」 | Cache-Control 的 max-age 單位是「秒」,不是毫秒。畫面上的值是 30541039 秒(約 353 天),與同一張截圖裡 Expires 標示的 2026-09-29 相符;若當成毫秒只有約 8.5 小時,前後就矛盾了。數量級也念錯了:30541039 是三千萬而非三百萬。 依據: RFC 9111 §5.2.2.1(max-age 以 delta-seconds 表示) |
| 3. #2 Core Web Vitals 3:14 |
「the LCP and the CLS are basically measured during the initial render」 | LCP 確實只看初次載入到使用者第一次互動為止,但 CLS 是整個頁面生命週期持續累積的(以 session window 計算),捲動過程中晚載入的元素造成的位移一樣算分。把 CLS 說成只在初次渲染量測會讓人漏掉最常見的扣分來源。 依據: web.dev「Cumulative Layout Shift (CLS)」;CLS 自 2021 年 6 月改為 session window 演算法 |
| 6. #4 內容協商與壓縮 11:03 |
「broadly with broadly being actually the most efficient one」 | Brotli 對文字資源的壓縮率確實通常優於 gzip,但說它「最有效率」已經不完整:畫面上瀏覽器送出的 Accept-Encoding 就包含 zstd。Zstandard 自 2024 年起被 Chrome 123+ 與 Firefox 126+ 支援,壓縮率接近 Brotli 而壓縮/解壓速度快數倍,動態內容場景反而更適合。「最有效率」也要看比的是壓縮率還是速度。 依據: RFC 8878(Zstandard);Chrome 123 起支援 Content-Encoding: zstd(2024-03) |
| 12. #10 Windowing 與可視區觀察 25:38 |
「if you go after the thousand HTML elements even the browser starts to suffer」 | 沒有「一千個節點」這樣的固定門檻,作者自己也說「不記得確切數字」。實際成本取決於節點的樣式複雜度、是否觸發排版、以及每次更新影響的範圍——幾千個簡單節點可能毫無問題,而幾百個帶陰影與濾鏡的節點就會卡。Lighthouse 的參考值是 DOM 總數超過 1400 才警告、深度超過 32 層才提醒,與影片說的數量級不同。 依據: Lighthouse「Avoid an excessive DOM size」稽核門檻(警告 ~1400 節點) |
| 14. #12 Rehydration 29:55 |
「run the hydrate command on the client」 | React 18(2022 年 3 月)起改用 `hydrateRoot(container, <App/>)`,舊的 `ReactDOM.hydrate` 已標記為棄用,在 React 19 被移除。概念完全相同,但照著舊 API 名稱去查文件或寫程式會踩空。 依據: React 18 release notes;React 19 移除 ReactDOM.hydrate |
5. 推薦三個下一步
1. 往下挖深:伺服器端渲染與 hydration 的實作細節
影片把 SSR、rehydration、PPR、server components 四段講成一條線,但每一段的實作坑(hydration error 的成因、串流 SSR 的 Suspense 邊界、`"use client"` 的傳染規則)都只點到為止,作者自己也兩度說「想看的話留言」。
YouTube 搜尋:React server components explained hydration error Next.js debug streaming SSR Suspense partial prerendering Next.js
2. 往旁邊對照:其他前端架構模式與微前端的替代方案
微前端在影片裡是唯一的組織級解法,但它有明確的適用前提(多團隊)與代價(相依重複、整合測試)。看過 monorepo、module federation、islands architecture 這些對照組,才知道什麼時候不該用微前端。
YouTube 搜尋:frontend architecture patterns micro frontends module federation monorepo vs micro frontends islands architecture Astro Qwik
3. 往上應用:前端系統設計面試
這 15 個模型的實際考場是系統設計面試——面試官要的正是「先畫出渲染路徑再說要動哪一段」這種答法。把概念換成一場 45 分鐘的設計題,才知道自己是真的懂還是只記得名詞。
YouTube 搜尋:frontend system design interview design news feed frontend web performance interview questions senior frontend interview mock
- 接著看 →Frontend System Design Explained w/ Senior Engineer (Microfrontends, Monorepo, MCP UI, Reactjs) · CRP、Core Web Vitals、SSR、CDN 在這站建立,那站直接拿來用不再解釋
- 接著看 →Every Frontend Architecture Pattern Explained in 23 Minutes · SSR、hydration、RSC 在這站只講概念,那站攤開整條架構演化與取捨
- 接著看 →Real Senior Frontend System Design Interview 2026 (AI Coding Included) · essential state 與衍生狀態的刪去法,在那場模擬面試裡實際用來圈狀態
- 接著看 →Top 15 Frontend Interview Questions for 2026 (wa/ Senior Engineer) · 同一批模型換成 15 道面試題,示範怎麼在口頭作答時組織它們
- 相關 —3 Frontend Skills AI Can't Replace (become AI-proof) · 共用 essential state 與單一事實來源:一站當效能地基,一站當 AI 判準
- 相關 —9 JavaScript Concepts That Got Me To Senior Dev · 作者結尾直接指路:語言層基礎之後,用這站把前端整體概念補齊
- 接著看 →Real Frontend System Design (from a Senior Engineer) · Core Web Vitals、CSR/SSR、hydration、CDN 在那站建立,這站直接拿來當架構決策的輸入
- 接著看 ←Frontend System Design at Scale (The Senior Dev Playbook) · 共同術語 CDN、lazy loading、Core Web Vitals;那站用關鍵渲染路徑把效能講到底
- 接著看 →Senior Frontend Interview 2026 🎉 | Javascript 🎯 (Mock) [Most Asked Questions] · 面試站直接拿 critical rendering path、reconciliation、virtual DOM、memoization 當共同語言使用
- 相關 —15 Fullstack Concepts Every Frontend Should Know · 共用 ETag、TTL:一站講快取在協定裡怎麼運作,一站講瀏覽器端效能
- 接著看 →How Frontend Engineers can master the Full-stack · 快取從效能技巧深入到 Cache-Control、max-age、ETag 的機制
- 接著看 →Frontend System Design: Performance API, Chrome, React Profiler · 那站建立 main thread、CRP、lazy loading 的心智模型,這站教你怎麼量它們
- 接著看 →Core Web Vitals Explained: LCP, INP & CLS · 那站用渲染路徑掛出 LCP/INP/CLS 的位置,這站把三個指標逐一拆到瀏覽器時序
- 接著看 ←The ultimate guide to web performance · 三個指標的意義懂了,那站把它們掛回關鍵渲染路徑,看出各自量到哪一段
- 相關 —Vapor Mode is the Future of Vue · 那站建立瀏覽器渲染路徑與 virtual DOM 的成本觀,這站主張把中間那層拿掉