
概念概覽
flowchart TD BP[Browser Process 主進程] --> UI[UI 介面] BP --> NET[網路請求] BP --> STR[儲存管理] BP --> RP1[Renderer Process Tab 1] BP --> RP2[Renderer Process Tab 2] BP --> GPU[GPU Process] RP1 --> MT[主執行緒 JS/DOM/CSS] RP1 --> CT[合成執行緒] RP1 --> RT[光柵化執行緒] MT --> EL[Event Loop] EL --> MIC[Microtask Queue] EL --> MAC[Macrotask Queue]
瀏覽器的多進程架構
你可能會想:「我是前端工程師,幹嘛要了解瀏覽器內部怎麼運作?」但其實,你遇到的很多效能問題——頁面卡頓、動畫不流暢、JavaScript 阻塞畫面——都跟瀏覽器的底層機制有關。搞懂它,你才知道為什麼 transform 比 top/left 效能好、為什麼 setTimeout(fn, 0) 不是真的零延遲、為什麼一個分頁掛了不會影響其他分頁。
現代瀏覽器(如 Chrome)採用多進程架構:
| 進程 | 職責 |
|---|---|
| Browser Process | 主進程,管理 UI、網路、儲存 |
| Renderer Process | 渲染網頁,每個 Tab 獨立進程 |
| GPU Process | 處理 GPU 相關任務 |
| Plugin Process | 執行瀏覽器外掛 |
| Extension Process | 執行擴充功能 |
┌─────────────────────────────────────────────┐
│ Browser Process │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ UI │ │ Network │ │ Storage │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Renderer │ │ Renderer │ │ Renderer │
│ (Tab 1) │ │ (Tab 2) │ │ (Tab 3) │
└─────────────┘ └─────────────┘ └─────────────┘
Renderer Process 的組成
每個渲染進程包含多個執行緒:
1. 主執行緒(Main Thread)
- 解析 HTML、CSS
- 執行 JavaScript
- 計算樣式和佈局
- 單執行緒,這就是為什麼 JS 會阻塞渲染
2. 合成執行緒(Compositor Thread)
- 處理圖層合成
- 處理滾動等不需要主執行緒的操作
3. 光柵化執行緒(Raster Thread)
- 將向量圖形轉換為像素
JavaScript 引擎
V8 引擎(Chrome)
JavaScript 程式碼
↓
┌─────────────────┐
│ Parser │ 解析成 AST
└────────┬────────┘
↓
┌─────────────────┐
│ Ignition │ 解譯器,產生 Bytecode
└────────┬────────┘
↓
┌─────────────────┐
│ TurboFan │ JIT 編譯器,優化熱點程式碼
└────────┬────────┘
↓
機器碼
記憶體管理
- Stack:存放基本類型、函數呼叫
- Heap:存放物件、陣列
- 垃圾回收:自動釋放不再使用的記憶體
了解了瀏覽器的多進程架構和 JS 引擎之後,還有一個關鍵問題:JavaScript 明明是單執行緒,那它是怎麼處理非同步操作的?答案就是事件循環。
事件循環(Event Loop)
JavaScript 是單執行緒,透過事件循環處理非同步操作:
┌─────────────────────────────────────────────┐
│ Call Stack │
│ ┌─────────────────────────────────────┐ │
│ │ │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
↑
│ 執行
│
┌─────────────────────────────────────────────┐
│ Event Loop │
│ │
│ ┌────────────────────┐ ┌────────────────┐ │
│ │ Microtask Queue │ │ Macrotask │ │
│ │ (Promise, queueM) │ │ (setTimeout) │ │
│ └────────────────────┘ └────────────────┘ │
└─────────────────────────────────────────────┘
執行順序
- 執行同步程式碼(Call Stack)
- 清空 Microtask Queue(Promise.then、queueMicrotask)
- 執行一個 Macrotask(setTimeout、setInterval)
- 重複 2-3
console.log('1'); // 同步
setTimeout(() => {
console.log('2'); // Macrotask
}, 0);
Promise.resolve().then(() => {
console.log('3'); // Microtask
});
console.log('4'); // 同步
// 輸出順序:1, 4, 3, 2渲染管線(Rendering Pipeline)
JavaScript → Style → Layout → Paint → Composite
│ │ │ │ │
│ │ │ │ └─ 合成圖層
│ │ │ └─ 繪製像素
│ │ └─ 計算位置大小
│ └─ 計算最終樣式
└─ 可能修改 DOM
重排(Reflow)vs 重繪(Repaint)
| 類型 | 觸發條件 | 效能影響 |
|---|---|---|
| 重排 | 改變幾何屬性(寬高、位置) | 高(需重新計算佈局) |
| 重繪 | 改變外觀(顏色、背景) | 中(只需重新繪製) |
| 合成 | transform、opacity | 低(只在 GPU 處理) |
效能優化
// ❌ 多次重排
element.style.width = '100px';
element.style.height = '100px';
element.style.left = '10px';
// ✅ 使用 class 一次修改
element.classList.add('new-style');
// ✅ 使用 transform 代替位置改變
element.style.transform = 'translateX(10px)';Web APIs
瀏覽器提供的 API,由瀏覽器執行緒處理:
- DOM API:操作網頁元素
- Fetch API:網路請求
- Timer API:setTimeout、setInterval
- Storage API:localStorage、sessionStorage
- Canvas/WebGL:圖形繪製
- Web Workers:背景執行緒
// Web Worker 範例 - 不阻塞主執行緒
const worker = new Worker('worker.js');
worker.postMessage({ data: heavyData });
worker.onmessage = (e) => {
console.log('計算結果:', e.data);
};延伸閱讀
Inside look at modern web browser JavaScript Visualized: Event Loop 瀏覽器發出request後經歷了什麼 JavaScript