浏览器原理
约 777 字大约 3 分钟
浏览器原理渲染
2024-08-13
浏览器架构
主流浏览器
| 浏览器 | 内核 | JavaScript 引擎 |
|---|---|---|
| Chrome | Blink | V8 |
| Firefox | Gecko | SpiderMonkey |
| Safari | WebKit | JavaScriptCore |
| Edge | Blink | V8 |
多进程架构
┌─────────────────────────────────────┐
│ Browser Process │
│ (地址栏、书签、前进后退) │
├─────────────────────────────────────┤
│ ┌─────────┐ ┌─────────┐ ┌───────┐ │
│ │ Renderer│ │ Renderer│ │ GPU │ │
│ │ Process │ │ Process │ │Process│ │
│ │ (Tab) │ │ (Tab) │ │ │ │
│ └─────────┘ └─────────┘ └───────┘ │
├─────────────────────────────────────┤
│ Plugin Process │
└─────────────────────────────────────┘渲染过程
关键渲染路径
HTML → DOM → CSSOM → Render Tree → Layout → Paint → Composite步骤详解
- 解析 HTML → 构建 DOM 树
- 解析 CSS → 构建 CSSOM 树
- 合并 DOM + CSSOM → Render Tree
- Layout → 计算每个节点的位置和大小
- Paint → 将节点绘制为多个图层
- Composite → 合成图层并显示
事件循环
宏任务与微任务
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve()
.then(() => console.log('3'))
.then(() => console.log('4'));
console.log('5');
// 输出顺序: 1, 5, 3, 4, 2任务队列
| 类型 | 示例 | 执行时机 |
|---|---|---|
| 宏任务 | setTimeout, setInterval, I/O | 当前任务执行完成后执行 |
| 微任务 | Promise.then, MutationObserver | 当前任务执行完成后,DOM更新前 |
垃圾回收
V8 垃圾回收器
| 回收器 | 适用场景 |
|---|---|
| Scavenge | 新生代 (短生命周期对象) |
| Mark-Sweep | 老生代 (长生命周期对象) |
| Mark-Compact | 老生代空间整理 |
内存泄漏
// 常见内存泄漏
// 1. 全局变量
function leak() {
leaked = 'something'; // window.leaked
}
// 2. 未清理的定时器
setInterval(() => {
// 没有 clearInterval
}, 1000);
// 3. 闭包
function createLeak() {
const largeData = new Array(1000000);
return () => largeData;
}
// 4. DOM 引用
const elements = [];
elements.push(document.getElementById('large'));
// 移除 DOM 但 elements 仍持有引用性能优化
重排 (Reflow) 与重绘 (Repaint)
// 触发重排的操作
element.style.width = '100px'; // 改变尺寸
element.style.height = '100px';
element.style.padding = '10px'; // 改变边距
element.innerHTML = 'new content'; // 改变内容
element.offsetTop; // 获取布局信息会强制重排
// 只触发重绘的操作
element.style.color = 'red'; // 只改变外观
// 优化:批量操作
const fragment = document.createDocumentFragment();
// 多次 DOM 操作
document.body.appendChild(fragment);
// CSS 动画优化
element.style.transform = 'translateX(100px)'; // 使用 transform 触发 GPU 加速懒加载
<img src="placeholder.jpg" data-src="real-image.jpg" class="lazy">// Intersection Observer 实现
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
document.querySelectorAll('.lazy').forEach(img => observer.observe(img));浏览器存储
Cookie vs LocalStorage vs SessionStorage
| 特性 | Cookie | LocalStorage | SessionStorage |
|---|---|---|---|
| 容量 | 4KB | 5MB | 5MB |
| 作用域 | 可设置路径 | 源 (origin) | 标签页 |
| 过期 | 可设置 | 永不过期 | 关闭标签页 |
| 发送请求 | 自动携带 | 不自动 | 不自动 |
IndexedDB
// 打开数据库
const request = indexedDB.open('MyDatabase', 1);
// 创建存储
request.onupgradeneeded = (event) => {
const db = event.target.result;
const store = db.createObjectStore('users', { keyPath: 'id' });
store.createIndex('name', 'name', { unique: false });
};
// 添加数据
const transaction = db.transaction(['users'], 'readwrite');
const store = transaction.objectStore('users');
store.add({ id: 1, name: 'John', age: 30 });
// 读取数据
const getRequest = store.get(1);
getRequest.onsuccess = () => console.log(getRequest.result);Web Worker
// worker.js
self.onmessage = (event) => {
const result = heavyComputation(event.data);
self.postMessage(result);
};
// main.js
const worker = new Worker('worker.js');
worker.postMessage(1000000);
worker.onmessage = (event) => {
console.log('Result:', event.data);
};
worker.terminate();安全
CSP (Content Security Policy)
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';">XSS 防护
// 转义 HTML
function escapeHTML(str) {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}CORS
// 服务器端设置 CORS 头
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://example.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});