目录
1.解析合成url->本地缓存?->域名缓存?->DNS解析IP/端口号
2.与对应服务器建立TCP->HTTPS请求->返回html文件
3.关键渲染路径(CRP,Critical Rendering Path)
style代码放在头部:避免无样式内容闪烁(FOUC,Flash of Unstyled Content)
1.1格式化样式表:->浏览器可识别的结构-styleSheets
1.2标准化样式表:相对/助记->具体值(em->px,red->rgba(255,0,0,0))
2.DOM树 + CSSOM 树=渲染树:确定DOM样式,不包括不显示元素
createDocumentFragment批量操作DOM:避免插入引起的重排
will-change**性能问题的最后手段(不要过度准备),脚本开启和关闭will-change
DNS,缓存,TCP,https,dom详情介绍等见超链接,此处不再赘述
1.解析合成url->本地缓存?->域名缓存?->DNS解析IP/端口号
浏览器缓存: HTTP 标头中的缓存控制信息(如 Cache-Control、Expires、ETag 等)
2.与对应服务器建立TCP->HTTPS请求->返回html文件
3.关键渲染路径(CRP,Critical Rendering Path)
渲染进程
- GUI渲染线程:渲染浏览器界面,解析 HTML,CSS,构建 DOM 树和 RenderObject 树,布局和绘制等。如重绘(Repaint)、回流(Reflow)时
- JS引擎线程: 与GUI互斥,当JS执行过程会导致页面出现阻塞
- 事件触发线程:触发时入队事件,等待JS处理(因为JS单线程)
- 定时器触发器:因为JS单线程,如果阻塞会影响计时准确,所以需要单独线程
- Http请求线程:XMLHttpRequest
0.解析HTML标签
a. 并行加载额外资源
猜测预加载(现代浏览器):全文扫描,额外HTML和CSS
现代浏览器会有一个轻量级的HTML(或CSS)扫描器继续在文档中扫描,查找那些将来可能能够用到的资源文件的url(如link标签)
也可手动设置link rel="preload"
b.增量构建 DOM 树
c.CSS并行
style代码放在头部:避免无样式内容闪烁(FOUC,Flash of Unstyled Content)
d.JS阻塞
同步加载
普通js/sync:阻塞 DOM加载+解析
JS可以监听 DOMContentLoaded
事件来确保 DOM 树已经完全构建以防引用还未生成
DOMContentLoaded 事件触发代表初始的 HTML 被完全加载和解析,不需要等待 CSS,JS,图片加载。
JS代码放在底部:HTML解析完再加载执行脚本
异步加载
async:脚本加载完就执行,无依赖
<script type="text/javascript" src="x.min.js" async="async"></script>
defer:HTML解析完再执行脚本,依赖
<script type="text/javascript" src="x.min.js" defer="defer"></script>
1.HTML增量构建DOM树:与构建CSSOM并行
DOM 使用逻辑树的形式来表示文档。树的每个分支末端都是一个节点,每个节点都包含对象。DOM 方法允许以编程方式来访问树。
DOM 构建是增量的,浏览器可以逐步解析文档并显示内容,提高页面加载的效率,逐步显示。
CSS 是渲染阻塞的:规则可以被覆盖,所以内容不能被渲染直到 CSSOM 完成。
1.CSS构建CSSOM 树:快
CSS 对象模型(CSSOM)可用JS动态地读取和修改 CSS 样式 的 API
1.1格式化样式表:->浏览器可识别的结构-styleSheets
浏览器的控制台document.styleSheets
可以来查看
1.2标准化样式表:相对/助记->具体值(em
->px
,red
->rgba(255,0,0,0))
默认全屏浏览器通常是 960px。
1.3计算每个DOM节点具体样式
计算规则:继承,
层叠(样式优先级)
级联(Cascading):
CSS (Cascading Style Sheets),级联遵循以下优先级顺序(从高到低):
- 重要性(!important):使用
!important
声明的样式具有最高优先级。- 来源:浏览器默认样式 < 外部样式表 < 内部样式表 < 内联样式。
- 特殊性:选择器的特殊性越高,优先级越高。
- 顺序:后定义的规则会覆盖之前定义的规则,即后面的规则具有更高的优先级。
计算完,会被挂在到window.getComputedStyle,
通过JS来获取计算后的样式
1.4JS解析和执行可能修改 DOM 结构和 CSS 样式
2.DOM树 + CSSOM 树=渲染树:确定DOM样式,不包括不显示元素
从 DOM 树的根节点开始,并且决定哪些 CSS 规则被添加
不显示元素及其子代都不会出现在渲染树
增量更新,优先用户可见区域
一旦特定的 DOM 节点和相应的 CSSOM 规则都可用,浏览器就会开始渲染那部分内容
3.在渲染树上布局:确定DOM尺寸位置(如重排/回流)
4.绘制:盒子->像素(如重绘)
硬件加速层:布局树分层,用GPU加速绘制
优化绘制性能:一些 CSS 属性(例如 opacity
、transform
、filter
等)会触发浏览器使用图形加速硬件(如 GPU)来处理。这些属性的变化需要更高的计算能力和帧速率来实时渲染,并且硬件加速能够更有效地利用设备的 GPU 资源,减少 CPU 的负担,从而提升页面的响应速度和动画的流畅度。
减少页面重绘和重排频率:浏览器需要实时更新元素的位置、尺寸和样式。
如果一个节点没有对应的层,那么这个节点就从属于父节点的图层。
创建新图层的情况
a.层叠上下文
- 文档根元素(
html
); - position 值为
absolute
(绝对定位)或relative
(相对定位)且 z-index 值不为auto
的元素; - position 值为
fixed
(固定定位)或sticky
(粘滞定位)的元素(沾滞定位适配所有移动设备上的浏览器,但老的桌面浏览器不支持); - flex (flex) 容器的子元素,且 z-index 值不为
auto
; - grid (grid) 容器的子元素,且 z-index 值不为
auto
; - opacity 属性值小于
1
的元素(参见 the specification for opacity); - mix-blend-mode 属性值不为
normal
的元素; - 以下任意属性值不为
none
的元素: - isolation 属性值为
isolate
的元素; - will-change 值设定了任一属性而该属性在 non-initial 值时会创建层叠上下文的元素
- contain 属性值为
layout
、paint
或包含它们其中之一的合成值(比如contain: strict
、contain: content
)的元素。
DIV #4,DIV #5 和 DIV #6 是 DIV #3 的子元素,所以它们的层叠完全在 DIV #3 中被处理,不和外部元素比较z-index,遵循样式计算的继承规则
一旦 DIV #3 中的层叠和渲染处理完成,DIV #3 元素就被作为一个整体传递与兄弟元素的 DIV 在 root(根)元素进行层叠。
b.剪裁:滚动条和内容提升为一个图层
剪裁(clip)是指通过 CSS 或者 HTML 属性限制可视区,超出这个区域的内容通常会被隐藏或者通过滚动条来查看。
Overflow 属性
overflow: visible;
:内容不会被剪裁,会超出父容器显示。
overflow: hidden;
:超出部分被隐藏,不显示在父容器之外。
overflow: scroll;
:显示滚动条,用户可以滚动查看内容。
overflow: auto;
:如果内容超出,显示滚动条;否则不显示。
优化性能,滚动条和其内容可以在渲染过程中独立处理,而不会影响主要文档流的渲染。
层爆炸
- 内存压力增大:每个合成层都可能消耗GPU(图形处理单元)内存,过多的图层会增加内存的使用,尤其是在资源受限的设备上。
- 性能下降:虽然单个合成层可以提升性能,但过多的合成层需要额外的处理和内存读写,这可能降低页面的渲染性能。
- 可能导致页面崩溃:在极端情况下,内存压力过大可能导致应用程序或浏览器标签页崩溃。
5.合成分层:正确顺序显示
不回流/重绘只用合成举例:transform来实现动画效果
6.交互
如果加载包括正确延迟加载的 JavaScript,并且仅在 onload 事件触发后执行,那么主线程可能会忙于执行脚本,无法用于滚动、触摸和其他交互操作。
Load :页面的所有资源(DOM,CSS,图片)
DOMContentLoaded:DOM
可交互时间(TTI)是测量从第一个请求导致 DNS 查询和 SSL 连接到页面可交互时所用的时间可交互是在首次内容绘制之后页面在 50ms 内响应用户的交互。
实践意义
防抖/节流
createDocumentFragment
批量操作DOM:避免插入引起的重排
文档片段存在于内存中,并不在 DOM 树中,所以将子元素插入到文档片段时不会引起页面回流
var element = document.getElementById("ul"); // assuming ul exists
var fragment = document.createDocumentFragment();
var browsers = ["Firefox", "Chrome", "Opera", "Safari", "Internet Explorer"];
browsers.forEach(function (browser) {
var li = document.createElement("li");
li.textContent = browser;
fragment.appendChild(li);
});
element.appendChild(fragment);
*代表实用程度
*固定大小的图像可定义尺寸:避免计算引起的重排
will-change**性能问题的最后手段(不要过度准备),脚本开启和关闭will-change
- 脚本开启和关闭:将
will-change
直接添加到样式表中意味着目标元素通常会在不久的将来发生变化,而浏览器会保留优化更长的时间。 - 过度使用
will-change
将导致内存使用过多,并导致更复杂的渲染发生,因为浏览器试图为可能的更改做准备。这将导致更差的性能。
/* 关键字值 */
will-change: auto;
will-change: scroll-position;
will-change: contents;
will-change: transform; /* <custom-ident> 示例 */
will-change: opacity; /* <custom-ident> 示例 */
will-change: left, top; /* 两个 <animatable-feature> 例子 */
/* 全局值 */
will-change: inherit;
will-change: initial;
will-change: revert;
will-change: revert-layer;
will-change: unset;