浏览器原理✅
浏览器架构及主要组成部分?
答案
参考 浏览器的工作方式
浏览器核心组成部件如下图
- 界面:包括地址栏、后退/前进按钮、书签菜单等。浏览器界面的每个部分,但显示请求网页的窗口除外。
- 浏览器引擎:在界面和渲染引擎之间协调操作。
- 渲染引擎:负责显示请求的内容。例如,如果请求的内容是 HTML,则呈现引擎会解析 HTML 和 CSS,并在屏幕上显示解析的内容。
- 网络:对于 HTTP 请求等网络调用,在平台无关接口后面为不同平台使用不同的实现。
- 界面后端:用于绘制组合框和窗口等基本 widget。此后端公开的接口并非平台专用。在底层,它使用操作系统界面方法。
- JavaScript 解释器:用于解析和执行 JavaScript 代码。
- 数据存储:这是持久层。浏览器可能需要在本地保存各种数据,例如 Cookie。浏览器还支持 localStorage、IndexedDB、WebSQL 和 FileSystem 等存储机制。 浏览器的主要组成部分是什么
整个进程模型参考 https://www.chromium.org/developers/design-documents/multi-process-architecture/
- Borwser Process 主进程 管理渲染进程和其他进程
- Main Thread 主线程,管理渲染进程
- IO Thread IO线程,处理网络请求
- Renderer Process 渲染进程,负责渲染页面
- Main Thread 渲染进程的主线程,负责解析HTML、CSS和JavaScript
- Render Thread 工作线程,处理后台任务等
这是一个概念上的示意图,实际上 chrome 还包含插件进程、GPU 进程等其他进程,此外也可通过配置等控制进程执行模式。
延伸阅读
常见浏览器内核及区别?
答案
内核 | 概述 |
---|---|
Blink | 由Google和Opera Software共同开发,基于WebKit内核,是Chrome浏览器和Opera浏览器的渲染引擎。 |
WebKit | 由苹果公司开发,为Safari浏览器所用。Kit内核在HTML、CSS和JavaScript处理方面都表现出色,支持的CSS特性较多。 |
Gecko | 由Mozilla开发,主要用于Firefox浏览器。 |
Trident | 由Microsoft开发,主要用于Internet Explorer浏览器,也是Windows系统自带的默认浏览器内核。从 2018 微软切换到基于 chromium 的 Blink 内核的 Edge 浏览器后,Trident 内核逐渐被淘汰。 |
输入 url 到页面渲染全过程?
答案
- Loading(加载阶段)
- URL 解析 , 浏览器解析 URL,提取协议、域名、路径等信息。
- Cache Check ,检查缓存,判断资源是否新鲜,决定是否重新请求。
- DNS, 进行 DNS 查询,解析出服务器 IP 地址。
- TCP, 建立 TCP 连接(三次握手)。
- TLS, 如果是 HTTPS 协议,进行 TLS 握手,建立安全连接。
- HTTP, 发送 HTTP 请求,获取资源。
- Parsing(HTML 和资源解析)
- DOM Tree 解析 HTML 文档,构建 DOM 树。注意 DOM 树的解析是流式的,浏览器会在解析过程中逐步构建 DOM 树,而不是等到整个文档加载完成再解析
- JS Execution 解析并执行 JavaScript,可能会修改 DOM 树或触发其他资源加载。
- CSSOM Tree 解析 CSS,构建 CSSOM 树
- Style(样式计算)
详见 style
- CSSOM 将样式表解析为 CSSOM(CSS 对象模型)。
- RenderObject Tree 基于 DOM 节点和 CSSOM 构建渲染对象树。
- Layout(布局计算)
详见 layout
- RenderLayer Tree 依据 RenderObject 和层叠上下文生成 RenderLayer 树。
- Layout 计算每个渲染对象的实际位置与尺寸。
- Paint(绘制阶段)
将样式化的内容转化为图层绘制命令与位图,完成从逻辑表示到图像数据的过渡。
- GraphicsLayer Tree 根据是否具有合成需求(如
transform
、opacity
、will-change
等)从 RenderLayer 构建 GraphicsLayer Tree,每个 GraphicsLayer 可单独绘制和合成。 - Paint Setup 为每个图层生成绘制命令(Display List,如 SkPicture),这些命令是可复用的中间格式。
- Rasterization 将绘制命令发送至 GPU 或 Raster 线程栅格化为位图,可存储于内存或 GPU 纹理中,等待合成。
- GraphicsLayer Tree 根据是否具有合成需求(如
- Compositing(合成阶段)
将所有图层位图合成为最终帧并显示。详见 Compositing
- Layer Compositing Compositor 线程根据 GraphicsLayer Tree 的结构,决定图层叠加顺序、混合与裁剪,并通过 GPU 将各图层位图合成为完整画面。
- Presentation 合成帧经由 GPU 管线提交至操作系统显示系统(如 Windows DWM 或 macOS Quartz),完成屏幕更新。
- Display(显示阶段)
将合成的图像数据发送到显示设备(如屏幕、投影仪等),完成最终的视觉呈现。
- Display Output GPU 负责将合成的图像数据发送到显示设备进行渲染
关键流程参考 了解关键路径 如下图
延伸阅读
- Life of a Pixel blink 渲染管线的工作原理, 对应 PPT
- Blink Rendering 更加通俗的讲解 blink 渲染管线的工作原理
- RenderingNG chrome 新的渲染管线
- The Rendering Critical Path
- render pipeline
- life of frame 图示说明渲染帧的执行逻辑
- Rendering Architecture Diagrams 更细节的渲染图,详细说明了涉及的对象
- CompositeAfterPaint 讲解 compositeAfterPaint 的工作原理
- Rendering Core 一系列资料了解 blink 选的个模块
DOM/CSSOM/渲染树构建?
答案
核心概念
DOM(文档对象模型)和 CSSOM(CSS对象模型)是浏览器渲染页面的基础数据结构。浏览器会将 HTML 解析为 DOM 树,将 CSS 解析为 CSSOM 树,然后结合两者生成渲染树(Render Tree),用于后续的布局和绘制。
- html 解析可以参考 html parser 规范
- cssom 可以参考 cssom
详细解释
- 解析 HTML 生成 DOM 树:浏览器自上而下读取 HTML,遇到标签就创建节点,嵌套结构形成父子关系,属性和文本也会作为节点挂载。
- 解析 CSS 生成 CSSOM 树:CSS 解析器将样式表转为规则对象,形成树状结构,便于后续样式计算。
- 构建渲染树:DOM 树与 CSSOM 树结合,过滤掉 display: none 的节点,仅保留可见元素,生成渲染树。每个渲染树节点都包含 DOM 元素及其最终计算样式。
- 渲染树用于布局(Layout)和绘制(Paint)阶段,决定元素的几何信息和视觉表现。
CSS选择器从右往左解析原理
浏览器在匹配 CSS 选择器时,从选择器最右侧(即目标元素)开始,逐级向左查找父节点是否匹配,直到根节点或选择器左端。这样可以快速排除不匹配的分支,提升性能。例如 .a .b .c
,会先查找 .c
,再判断其父节点是否有 .b
,依次类推。
代码示例
<div class="a">
<div class="b">
<span class="c">text</span>
</div>
</div>
.a .b .c { color: red; }
浏览器会先定位 .c
,再判断其父级是否有 .b
,再向上查找 .a
,而不是从 .a
开始遍历所有后代。
常见误区与开发建议
- 误区:以为 CSS 选择器是从左往右解析,导致过度嵌套选择器以期望优化性能,实则适得其反。
- 建议:减少层级选择器和通配符(*)的使用,优先使用类选择器,提升样式匹配效率。
合理优化选择器结构,能显著提升页面渲染性能,尤其在大型 DOM 树下效果明显。
延伸阅读
事件循环原理、宏任务与微任务?
答案
浏览器事件循环详见 HTML 规范 event loops 章节, 基于规范定义的 事件循环处理模型
- 宏任务本质就是 task
- 例如:
setTimeout
、setInterval
、I/O 操作
、UI 事件
等。会按照顺序放入任务队列中。执行存在优先级
- 例如:
- 微任务本质就是 microtask
- 例如:
Promise.then
、MutationObserver
等。 - 必须在一个宏任务执行完毕后,检查微任务队列是否有任务,如果有,则执行所有微任务,直到微任务队列清空。
- 例如:
- 此外对于
setTimeout
和setInterval
的任务,在浏览器处于后台模式超过 5 分钟的时候默认会触发 throttle 逻辑,会被延缓到 1 分钟触发一次,具体的不同事件类型限制情况详见 task type
chromium 的任务类型,详见 task_typs 文件, event_loop 说明详见 event_loop
延伸阅读
- Tasks, Microtasks, Queues and Schedules 详细讲解浏览器事件循环
- blink 调度 详细讲解 blink 调度模式
- node event loop 详解讲解 node event
- schedule docs chromium 调度文档汇总,有很多有用的信息
- Event Loop 運行機制解析 - 瀏覽器篇 浏览器详解
重排和和重绘及优化?
答案
- 重排(reflow) 发生在浏览器重新计算网页的某些部分的位置和几何形状时(例如在交互式站点更新后)。这通常会紧接着重绘(repaint),即浏览器重新绘制网页以显示更新后的视觉效果。
- 重绘(repaint) 重绘在浏览器重新绘制网页以显示由 UI 更改引起的视觉更新时发生,例如在交互式站点上进行更新后。这通常是在重排之后发生的,重排是浏览器重新计算网页的某些部分的位置和几何形状。
重排和重绘是导致浏览器性能下降的主要原因之一,这里重点关注重排,因为它比重绘更耗费资源。
参考 What forces layout / reflow 常见触发重排的操作如下
- 直接修改元素的几何属性,如
width
、height
、top
、left
、margin
、padding
、border-width
等。 - 插入、删除 DOM 节点,或更改节点结构(如
appendChild
、removeChild
、insertBefore
等)。 - 读取会触发布局的属性和方法,如
offsetWidth
、offsetHeight
、offsetTop
、offsetLeft
、clientWidth
、clientHeight
、getBoundingClientRect()
、getClientRects()
。 - 访问滚动相关属性和方法,如
scrollTop
、scrollLeft
、scrollWidth
、scrollHeight
、scrollTo()
、scrollBy()
、scrollIntoView()
。 - 设置或获取元素的
focus()
、select()
、innerText
。 - 读取
window.getComputedStyle()
,尤其是访问返回对象的属性时。 - 修改表单元素的选区(如
input.select()
、textarea.select()
)。 - 读取或设置 SVG 某些属性和方法(如
getBBox()
、getComputedTextLength()
)。 - Canvas2D API 某些操作(如
fillText()
、strokeText()
、设置direction
、filter
)。 - 读取窗口尺寸相关属性,如
window.innerWidth
、window.innerHeight
、window.scrollX
、window.scrollY
(部分浏览器实现)。
在错误的触发重排的场景下,通过如下方式优化性能
- 批量修改 DOM:将多次 DOM 操作合并为一次操作,减少重排次数。例如,使用
DocumentFragment
或cloneNode
批量插入节点。 - 使用 CSS 类:通过添加或删除 CSS 类来批量修改样式,而不是逐个修改样式属性。这样可以减少重排次数。
- 使用
requestAnimationFrame
:将需要重排的操作放在requestAnimationFrame
回调中执行,这样可以确保在浏览器下一次重绘之前进行布局计算。 - 避免频繁读取布局属性:如果需要多次读取布局属性,可以先将其存储在变量中,避免多次触发重排。例如,使用
let rect = element.getBoundingClientRect()
存储布局信息,然后在需要时使用该变量。 - 使用
will-change
:对于需要频繁更新的元素,可以使用will-change
CSS 属性来提示浏览器提前进行优化,减少重排的开销。 - 使用 CSS 动画:尽量使用 CSS 动画而不是 JavaScript 动画,CSS 动画通常会触发 GPU 加速,减少重排的开销。
对于 css 详见 CSSTriggers 讲解哪些 CSS 属性会触发重排和重绘。
延伸阅读
- Understanding Reflow and Repaint in the browser 详细讲解 repaint 和 reflow 概念
- 理解 Web 的重排和重绘 大漠详细讲解重排和重绘
浏览器缓存中 Memory Cache 和 Disk Cache, 有啥区别?
答案
- Memory Cache(内存缓存):资源直接存储在内存中,访问速度极快(纳秒级),但容量有限,通常在刷新或关闭页面后失效。适合当前会话内频繁访问的资源。
- Disk Cache(磁盘缓存):资源存储在硬盘上,访问速度比内存慢(毫秒级),但容量大,关闭浏览器后依然保留。适合长期存储和较大体积的资源。
核心概念
Memory Cache(内存缓存)和 Disk Cache(磁盘缓存)都是浏览器用来提升资源加载速度的缓存机制,区别在于存储介质和访问速度。
详细解释
- Memory Cache:资源被直接缓存在内存中,访问速度极快(纳秒级),但容量有限,重启浏览器或刷新页面后通常会失效。适合短期、频繁访问的资源。
- Disk Cache:资源被缓存在本地硬盘,访问速度比内存慢(毫秒级),但容量大,关闭浏览器后依然保留。适合长期存储、较大体积的资源。