
1. 浏览器从 HTML 到最终显示完整过程是什么核心回答浏览器先解析 HTML 和 CSS生成 DOM 和 CSSOM再计算布局、分层、生成绘制指令经过分块和光栅化最后把各个图层合成到屏幕上。展开可以把现代 Chromium 的渲染过程理解成HTML ↓ 解析 ↓ DOM Tree CSS ↓ 解析 ↓ CSSOM │ └──────┐ ↓ 样式计算 / 布局 ↓ 布局树 ↓ 分层 ↓ 绘制 ↓ 分块 ↓ 光栅化 ↓ 合成 ↓ 显示注意这不是简单的“一个步骤执行完才执行下一个步骤”。HTML 解析、CSS 加载/解析、资源加载、JavaScript 执行之间存在并行和相互阻塞关系。真正面试高级的地方是继续回答什么时候能继续什么会阻塞什么变化会重新走哪一步2. HTML 解析的时候浏览器到底做了什么核心回答HTML Parser 会把 HTML 字节流逐步解析成 DOM而不是等整个 HTML 下载完才一次性生成 DOM。例如htmlbodydivspanHello/span/div/body/html大致是HTML 字节流 ↓ 词法分析 ↓ Token ↓ DOM Node ↓ DOM Tree所以浏览器可以边下载、边解析、边构建 DOM。3. HTML 解析和 CSS 解析是串行还是并行核心回答不是简单的串行它们可以并行推进HTML 解析发现 CSS 后可以发起 CSS 请求同时继续解析 HTML。例如headlinkrelstylesheethrefstyle.css/headbodydivHello/div/body可以理解成HTML Parser │ ┌─────────┴─────────┐ ↓ ↓ 构建 DOM 发现 CSS ↓ 请求 CSS ↓ CSS Parser ↓ CSSOM所以不要说HTML 解析完以后才开始 CSS 解析。这不准确。4. CSS 会不会阻塞 HTML 解析核心回答普通外部 CSS 一般不会直接让 HTML Parser 停下来等 CSS 下载完但 CSS 会影响后续的样式计算和渲染而且还可能间接影响脚本执行。所以一定要区分CSS 阻塞 HTML 解析 ↓ 通常不是直接阻塞 CSS 阻塞渲染 ↓ 关键 CSS 会影响首次渲染 CSS 影响 JS 执行 ↓ 某些情况下会这也是面试里很容易被追问的地方。5. 为什么 CSS 会影响首次渲染核心回答因为浏览器必须知道元素最终是什么样子才能正确计算布局和绘制所以关键 CSS 没准备好时通常不能完成正确的首次渲染。例如.box{display:none;}如果浏览器完全不管 CSS直接把divclassboxHello/div画出来之后 CSS 到了再隐藏就会产生错误的中间画面。所以DOM │ │ CSSOM │ └──────┐ ↓ 样式计算 ↓ 布局树 ↓ 绘制6. HTML 遇到script会发生什么核心回答普通同步script会暂停 HTML 解析浏览器先下载并执行脚本执行结束后 HTML Parser 才继续。例如div1/divscriptsrcapp.js/scriptdiv2/div大致解析 div1/div ↓ 发现 script ↓ 暂停 HTML Parser ↓ 下载 JS ↓ 执行 JS ↓ 继续 HTML Parser ↓ 解析 div2/div这也是为什么大量同步脚本放在 HTML 前面可能拖慢页面构建。7.defer和async到底解决什么问题核心回答defer是“异步下载、HTML 解析完再按顺序执行”async是“异步下载、谁先下载完谁先执行”。普通 scriptHTML解析 ↓ 发现JS ↓ 暂停解析 ↓ 下载 执行JS ↓ 继续解析deferHTML解析 ─────────────────→ 完成 │ └── JS异步下载 ↓ HTML解析完成 ↓ 执行JS多个defera.js → b.js → c.js保持文档顺序。asyncHTML解析 ─────────────────→ │ └── JS异步下载 ↓ 下载完成 ↓ 立即执行所以多个asynca.js ──┐ b.js ──┼── 谁先下载完谁先执行 c.js ──┘8. DOM、CSSOM 之后为什么不是直接“Render Tree”核心回答现代浏览器更值得关注的是样式计算和布局树而不是把 Render Tree 当成一个独立的核心阶段死记。可以理解成DOM CSSOM ↓ 样式计算 ↓ 布局树布局树描述的是最终参与布局的内容以及它们的几何信息。例如display:none;对应的节点不会正常参与布局。所以布局树和 DOM Tree 并不是一模一样。9. 什么是布局核心回答布局就是确定每个元素最终放在哪里、尺寸是多少以及它和其他元素之间的几何关系。例如divclassbox/div.box{width:200px;height:100px;margin-left:50px;}布局阶段需要确定类似x 50 y ... width 200 height 100所以样式 ↓ 布局 ↓ 确定几何信息10. 什么是分层为什么需要分层核心回答分层就是把页面中的部分内容放到独立的图层里后续这些内容可以独立参与绘制和合成。可以简单理解页面 ├── Layer A ├── Layer B └── Layer C例如某些具有transform opacity或者其他特定条件的元素可能被提升到独立合成层。这样做的价值是普通情况 修改元素 ↓ 重新布局/绘制 ↓ 重新处理 独立图层 修改 transform ↓ 直接更新图层属性 ↓ 合成11. 什么是 Paint核心回答Paint 不是直接把像素画到屏幕上而是生成“怎么画”的绘制指令。例如Paint ↓ 画背景 画边框 画文字 画阴影 画图片 ... ↓ 绘制指令这是一个非常容易被忽略的细节。所以不要简单说Paint 把东西画到屏幕。更准确的是Paint 生成绘制指令后续再由光栅化把这些指令转换成像素。12. 什么是分块核心回答分块就是把需要光栅化的内容拆成一个个 tile方便浏览器按需调度和处理。可以理解成一个很大的页面 ┌────┬────┬────┐ │tile│tile│tile│ ├────┼────┼────┤ │tile│tile│tile│ ├────┼────┼────┤ │tile│tile│tile│ └────┴────┴────┘为什么要这么做因为页面可能非常大。没必要每次都把整个页面一次性光栅化。特别是滚动页面当前可视区域 ↓ 优先处理附近需要显示的 tiles13. 什么是光栅化核心回答光栅化就是把 Paint 阶段产生的绘制指令真正转换成像素数据。例如Paint ↓ “这里画一个红色矩形” “这里画一段文字” “这里画一张图片” ↓ Raster ↓ 像素所以可以把两者区别记成Paint 告诉浏览器“怎么画” Raster 真正把“怎么画”变成像素14. 什么是 Composite核心回答Composite 就是把已经准备好的不同图层/图块按照位置、层级、透明度、transform 等信息合成最终画面。例如Layer A ↓ Layer B ↓ Layer C ↓ Composite ↓ 最终画面如果一个元素已经有独立图层.box{transform:translateX(100px);}那么动画过程中可能主要改变的是图层位置 ↓ Composite而不需要每一帧重新Layout ↓ Paint ↓ Raster这就是合成动画通常性能比较好的原因。15. 修改width会发生什么核心回答修改width会影响元素几何信息所以通常需要重新布局并可能进一步触发绘制和光栅化最后重新合成。典型路径修改 width ↓ Layout ↓ Paint ↓ Raster ↓ Composite注意这是典型路径不是绝对规则。实际浏览器会根据具体元素、渲染状态、优化策略决定哪些阶段需要重新执行。16. 修改color呢核心回答修改color通常不需要重新布局但会影响绘制所以通常需要重新 Paint后续相关内容还需要重新光栅化并合成。大致color ↓ Paint ↓ Raster ↓ Composite17. 为什么transform通常性能更好核心回答transform只改变合成层的变换矩阵不触发重排和重绘直接交给 GPU 处理。例如.box{transform:translateX(100px);}可能变成原来的页面 ↓ Layout ↓ Paint ↓ Raster ↓ 独立图层 ↓ transform变化 ↓ Composite动画过程中主要处理Composite而不是反复Layout → Paint → Raster18.transform是不是一定不走主线程核心回答不是。不能把transform简单理解成“完全不走主线程”准确说法是满足条件时它可以让动画主要在合成阶段处理。transform 和 opacity 在满足合成条件时可以避免每帧重新执行 Layout 和 Paint从而降低主线程压力。19. 一帧之内修改 10 次样式会 Layout 10 次吗核心回答不一定。浏览器通常会把连续的样式修改合并在合适的渲染时机统一处理。例如box.style.width100px;box.style.width200px;box.style.width300px;通常没必要100px → Layout 200px → Layout 300px → Layout而可能最终只处理100px ↓ 200px ↓ 300px ↓ 最终300px ↓ Layout所以不要把每次 DOM/CSS 修改都等同于一次 Layout。20. 什么情况下会强制浏览器立即 Layout核心回答改完样式马上读布局值浏览器为了给出最新结果会先强制更新布局。例如box.style.width500px;console.log(box.offsetWidth);因为offsetWidth需要最新布局结果。浏览器可能修改样式 ↓ 布局失效 ↓ 读取 offsetWidth ↓ 强制 Layout ↓ 返回结果这就是性能问题的来源之一。21. 什么是 Layout Thrashing核心回答就是不断交替“修改布局”和“读取布局”导致浏览器反复被迫同步 Layout。例如for(constitemofitems){item.style.width100px;console.log(item.offsetWidth);}可能形成Write ↓ Read ↓ Layout Write ↓ Read ↓ Layout Write ↓ Read ↓ Layout大量重复计算就会拖慢页面。更合理for(constitemofitems){item.style.width100px;}for(constitemofitems){console.log(item.offsetWidth);}尽量变成Write Write Write Write ↓ Read Read Read Read22.requestAnimationFrame在这里解决什么问题核心回答requestAnimationFrame会把回调安排到浏览器下一次绘制前执行这样动画更新就能跟着浏览器的绘制节奏走。例如requestAnimationFrame((){box.style.transformtranslateX(${x}px);});但不要把requestAnimationFrame理解成“只要用了它就不会回流。”它解决的是更新时机和渲染节奏的问题。23.will-change是不是 GPU 加速开关核心回答不是。will-change是提前告诉浏览器某个元素的哪些属性可能发生变化浏览器可以提前做优化准备。例如.box{will-change:transform;}它不是will-change ↓ 强制GPU加速而是告诉浏览器 这个元素接下来可能发生 transform 变化 ↓ 浏览器自行决定是否提前优化所以不能滥用。因为独立图层本身也有GPU/内存占用 纹理管理成本 合成成本图层不是越多越好。24.contain: layout能解决什么问题核心回答它可以把布局影响限制在特定元素内部减少内部变化向外部扩散的范围。例如.card{contain:layout;}重点是限制布局影响范围。大型列表、复杂组件、局部独立区域中比较有价值。25. 首屏图片很多白屏时间长应该怎么排查核心回答我不会看到图片多就直接压图片而是先用 Performance 和 Network 定位白屏到底卡在网络、HTML/CSS、JS还是主线程渲染再针对瓶颈处理。例如白屏 ↓ 到底卡在哪里 │ ├─ TTFB 高 │ ├─ HTML 下载慢 │ ├─ CSS 下载/解析慢 │ ├─ JS 下载慢 │ ├─ JS 执行时间长 │ ├─ 首屏图片请求晚 │ ├─ 主线程任务太重 │ └─ Layout / Paint 太重这才是线上问题的正确排查思路。26. 如果发现 CSS 文件特别大应该怎么办核心回答首屏用到的 CSS 先加载首屏用不到的 CSS 后加载。可以考虑大 CSS ↓ 拆分 ↓ 关键 CSS ↓ 优先加载非首屏样式根据场景延后。比如不同媒体类型的 CSSlinkrelstylesheethrefprint.cssmediaprint核心思想就是减少关键渲染路径上的阻塞。27. 如果首屏图片特别多应该怎么优化核心回答核心不是“所有图片都加载得更快”而是让首屏真正需要的图片优先加载非首屏图片延后加载。例如首屏图片 ↓ 合理尺寸 ↓ 压缩 ↓ 现代图片格式 ↓ 优先请求 非首屏图片 ↓ loadinglazy ↓ 需要时再加载还可以结合imgsrchero.aviffetchpriorityhighalt以及imgsrcbelow-fold.avifloadinglazyalt28. 这道题真正考什么核心回答它考的不是你能不能背出渲染流程而是你能不能根据浏览器的渲染管线判断一次操作会影响哪一步以及线上性能问题到底卡在哪里。可以把能力分成四层第一层 知道流程 ↓ HTML → DOM CSS → CSSOM ↓ 布局 → 分层 → 绘制 → 分块 → 光栅化 → 合成 第二层 知道阻塞关系 ↓ script 是否阻塞 HTML CSS 是否影响渲染 defer / async 怎么工作 第三层 知道更新路径 ↓ width → Layout → Paint → Raster → Composite color → Paint → Raster → Composite transform → 满足条件时主要走 Composite 第四层 能解决线上问题 ↓ 为什么白屏 为什么滚动卡 为什么动画掉帧 为什么 Layout 很高 为什么 JS 执行把渲染卡住 到底应该优化哪一步最后真正面试时怎么答如果面试官只问“说一下浏览器的渲染过程。”不要一上来讲五分钟。核心回答浏览器会先解析 HTML 和 CSS生成 DOM 和 CSSOM然后进行样式计算和布局生成布局树接着进行分层、绘制、分块和光栅化最后把这些图层合成并显示到屏幕上。如果面试官继续追问“CSS、JS 谁会阻塞谁”再展开普通同步 JS 会暂停 HTML 解析CSS 通常不会直接阻塞 HTML 解析但关键 CSS 会影响首次渲染而且 CSS 的加载还可能影响某些脚本的执行。再追问“为什么 transform 动画性能好”再答因为满足合成条件时transform 可以直接作用在已经准备好的图层上动画过程中主要走合成不需要每一帧重新做布局和绘制。再追问“一帧改十次样式会 Layout 十次吗”再答不一定浏览器通常会把连续修改合并但如果修改后马上读取offsetWidth这类布局信息就可能强制同步 Layout连续这样做就容易产生 Layout Thrashing。这才是这道题从**“会背流程”到“真正懂浏览器渲染”**的分水岭。