我的文档库

浏览器原理

从 JavaScript 执行模型、Event Loop、渲染流水线到网络与浏览器安全边界

前端开发真正的底层能力,不是记住:

宏任务
微任务
DOM
BOM

而是理解:

浏览器到底是如何把一段 JavaScript 变成用户看到的画面的。


1. 浏览器不是一个 JavaScript 执行器

现代浏览器可以粗略理解为:

Browser
├── Network
├── Browser Process
├── Renderer Process
├── JavaScript Engine
├── DOM
├── CSS Engine
├── Layout
├── Paint
├── Compositor
└── GPU

所以:

JavaScript

只是浏览器的一部分。


2. JavaScript 为什么通常是单线程模型?

JavaScript 操作:

DOM
State
UI

如果多个线程同时修改:

<div>

就会产生复杂的同步问题。

因此浏览器将大量 UI 操作集中在主线程模型中。

但现代浏览器并不是:

“整个浏览器只有一个线程。”

实际上还存在:

Network Threads
GPU
Workers
Compositor
IO

3. Event Loop

一个简化模型:

Call Stack
    ↓
Task
    ↓
Microtask
    ↓
Render

例如:

console.log('A')

setTimeout(() => {
  console.log('B')
})

Promise.resolve().then(() => {
  console.log('C')
})

console.log('D')

输出:

A
D
C
B

原因是:

同步代码
 ↓
Microtask
 ↓
Task

4. 为什么 Promise 比 setTimeout 更早?

因为:

Promise callback = Microtask

而:

setTimeout = Task

事件循环在一个任务结束后,通常会先处理 microtask checkpoint,再进入后续调度阶段。

因此:

Task
 ↓
全部 Microtask
 ↓
Render opportunity
 ↓
下一个 Task

可以帮助理解很多:

UI 更新时机
Promise
MutationObserver
setTimeout

相关问题。


5. 为什么 Microtask 也能卡死页面?

例如:

function loop() {
  Promise.resolve().then(loop)
}

loop()

虽然没有:

while(true)

但 microtask 不断产生新的 microtask。

结果:

Microtask
 ↓
Microtask
 ↓
Microtask
 ↓
Microtask

浏览器可能长期无法获得正常渲染机会。

所以:

“异步”不等于“不会阻塞”。


6. 浏览器渲染流水线

可以简化成:

DOM
 ↓
Style
 ↓
Layout
 ↓
Paint
 ↓
Composite

其中 Layout 主要负责:

位置
尺寸
几何关系

Paint:

文字
背景
边框
阴影

Composite:

图层合成

7. 什么操作会触发 Layout?

例如:

element.offsetHeight

浏览器需要知道最新布局。

如果之前有未提交的样式变化:

Style Change
 ↓
读取 Layout
 ↓
Forced Layout

大量交替:

write()
read()
write()
read()

可能导致 Layout Thrashing。


8. 为什么 transform 经常用于动画?

因为:

transform: translateX(...)

很多情况下可以在合成阶段处理。

相比频繁修改:

top
left
width
height

更容易避免大量布局计算。

但不能简单理解为:

“transform 永远不会触发性能问题。”

因为:

Layer
Memory
Paint
Composite

仍然有成本。


9. 浏览器网络模型

访问:

https://example.com

大致涉及:

URL
 ↓
DNS
 ↓
Connection
 ↓
TLS
 ↓
HTTP
 ↓
Response

现代网络还需要考虑:

  • HTTP/2
  • HTTP/3
  • QUIC
  • Connection Reuse
  • Multiplexing
  • CDN
  • Edge

10. HTTP/2 为什么重要?

HTTP/1.1:

多个请求
 ↓
多个连接 / pipeline 等限制

HTTP/2:

一个连接
 ↓
多个 Stream
 ↓
多个请求并行传输

因此现代前端:

不应该继续简单套用“HTTP/1.1 下尽量减少请求数量”的所有旧经验。

需要根据:

  • 协议
  • 资源类型
  • 缓存
  • 连接
  • 服务器

综合判断。


11. 浏览器存储

常见:

  • Cookie
  • localStorage
  • sessionStorage
  • IndexedDB
  • Cache Storage

它们不是简单的:

“五种 LocalStorage。”

而是不同能力:

Cookie
→ HTTP 状态 / Session

localStorage
→ 简单持久化

sessionStorage
→ 页面会话

IndexedDB
→ 结构化大数据

Cache Storage
→ Request / Response 缓存

例如:

Cookie: session=abc

浏览器会根据:

  • Domain
  • Path
  • Secure
  • SameSite

等规则决定是否发送。

这也是:

CSRF

能够成立的重要原因之一。


13. 输入 URL 后发生什么?

URL Parse
 ↓
Cache
 ↓
DNS
 ↓
Connection
 ↓
TLS
 ↓
HTTP
 ↓
Response
 ↓
HTML Parse
 ↓
DOM
CSSOM
 ↓
Render Tree
 ↓
Layout
 ↓
Paint
 ↓
Composite
 ↓
Pixels

同时补充:

JavaScript
Font
Image
Async Data

可能穿插其中。


本页目录