文章中英模式
常见的前端面试题目 - 页面加载 - 解释网页的渲染过程(CRP路径)
深入解析浏览器的关键渲染路径(CRP),包含 DOM、CSSOM、渲染树的构建过程,以及重排、重绘的优化策略和面试常见问题的完整解答。
文章中英模式

懒得看文章?那就来看视频吧
基本概念
浏览器将 HTML、CSS 和 JavaScript 转换为像素的过程称为关键渲染路径(Critical Rendering Path,简称 CRP)。理解这个过程对于优化网页性能至关重要。
用户请求 URL ex: https://www.google.com
│
↓
服务器处理请求 ─────────────────────────────┐
│ │
├─→ SSR (Server-Side Rendering) │
│ 服务器生成完整 HTML │
│ │
├─→ SSG (Static Site Generation) │
│ 返回预先生成的静态 HTML │
│ │
└─→ SPA (Single Page Application) │
返回基础 HTML 框架 │
│ │
↓ │
HTML 返回浏览器 ◄───────────────────────────┘
│
↓
HTML ──────┐
↓
DOM Tree CSS ──────┐
│ ↓
│ CSSOM Tree
│ │
└─────────┬─────────┘
↓
Render Tree ◄─── JavaScript 执行
│ (可修改 DOM 和 CSSOM)
↓
Layout
│
↓
Paint
│
↓
Composite1. HTML 解析 → DOM Tree
浏览器将 HTML 转换为 DOM (Document Object Model),作为网页的对象表示和 JavaScript 操作接口。解析过程是渐进式的,允许逐步处理内容。
2. CSS 解析 → CSSOM Tree
CSS 被解析为 CSSOM (CSS Object Model),这是渲染阻塞资源,必须完成构建才能进行下一步。
3. JavaScript 执行
JavaScript 是解析阻塞资源,当浏览器遇到 script 标签时,会暂停 DOM 构建,先下载并执行 JavaScript。JavaScript 可以修改 DOM 和 CSSOM,因此必须等待前面的 CSS 解析完成。使用 async 或 defer 属性可改变执行时机。
4. DOM + CSSOM → Render Tree
結合 DOM 和 CSSOM 形成渲染樹,只包含可見元素(display: none 的元素會被排除)及其樣式信息。
5. Layout(Reflow)
计算每个可见元素的精确位置和大小,确定其在视窗中的定位。视窗大小改变时会触发重新布局。
6. Paint(Repaint)
将布局转换为实际像素,包括文字、颜色、边框、阴影等视觉效果,通常在多个层上进行。
7. Composite
将不同绘制层合成最终画面,处理层叠顺序和透明度。使用 GPU 加速可提升性能。
性能优化建议
最小化关键资源
- •减少 HTML、CSS、JavaScript 文件大小
- •移除未使用的 CSS/JavaScript
- •使用 Code Splitting 和延迟加载
减少重排和重绘
- •批量修改 DOM
- •使用 CSS Transform 和 Opacity 进行动画
- •避免频繁改变元素位置和大小
🔥 常见面试题目
(一)什么是 Reflow 和 Repaint?它们的区别是什么?
解答:
- •Reflow(重排):当元素的大小、位置或文档流中的位置发生改变时触发
- •Repaint(重绘):当元素外观改变但不影响布局时触发,如颜色、背景等变化
- •Reflow 一定会导致 Repaint,但 Repaint 不一定会导致 Reflow
(二)为什么说 CSS 是渲染阻塞资源?
解答:
- •CSS 被视为渲染阻塞资源是因为浏览器需要等待 CSSOM 完全构建后才能进行渲染树的构建
- •即使 JavaScript 不依赖 CSS,如果存在未完成下载的样式表,JavaScript 执行也会被阻塞
- •这是为了确保页面渲染的正确性和一致性
(三)会影响 Reflow 和 Repaint 的 CSS 属性有哪些?如何避免频繁触发?
解答:
- •触发 Reflow 的属性:width、height、margin、padding、border、position、top、left、right、bottom、font-size、font-family、display、float
- •主要触发 Repaint 的属性:color、background、visibility、text-decoration、box-shadow、outline
- •高性能属性:transform、opacity、filter(这些属性通常只触发合成层,由 GPU 加速处理,不触发 CPU 密集的 Reflow 操作)
避免频繁触发的策略:
// ------------------------- 1. 批量修改 DOM 而非逐个修改 -------------------------
// 不好的做法 - 多次触发 Reflow
const element = document.getElementById('myElement');
element.style.width = '100px';
element.style.height = '200px';
element.style.margin = '10px';
// 好的做法 - 只触发一次 Reflow
const element = document.getElementById('myElement');
element.classList.add('new-layout');
// 或使用 style.cssText
element.style.cssText = 'width: 100px; height: 200px; margin: 10px;';
/* CSS */
.new-layout {
width: 100px;
height: 200px;
margin: 10px;
}
// ------------------------- 2. 使用 DocumentFragment 批量添加多个元素 -------------------------
const fragment = document.createDocumentFragment();
for (let i = 0; i < 10; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
fragment.appendChild(li);
}
document.getElementById('myList').appendChild(fragment);
// ------------------------- 3. 使用 transform 代替位置调整 -------------------------
// 不好的做法 - 触发 Reflow
element.style.left = '10px';
element.style.top = '20px';
// 好的做法 - 只触发合成
element.style.transform = 'translate(10px, 20px)';
// ------------------------- 4. 先设置 display: none,修改后再显示 -------------------------
element.style.display = 'none';
// 进行多次修改...
element.style.width = '100px';
element.style.height = '200px';
element.style.margin = '10px';
// 最后再显示,只触发一次 Reflow
element.style.display = 'block';