百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

浏览器渲染原理 浏览器渲染原理事件循环机制

suiw9 2024-11-14 19:13 25 浏览 0 评论

在我们正式开始学习之前,首先让我们了解一些浏览器的一些知识点,然后再对浏览器渲染原理深刻的理解一下,这次学习是针对Chrome浏览器的渲染机制。

最新的Chrome浏览器包括:1个浏览器主进程,一个GPU进程,一个网络进程,多个渲染进程和多个插件进程。

浏览器进程:主要负责界面显示、用户交互、子进程管理、同时提供存储等功能

渲染进程:核心任务将HTML、CSS和JavaScript转化为用户可以交互的网页,排版引擎Blink和JavaScript引擎V8都是运行在该线程。默认情况下,Chrome浏览器为每个标签页创建一个渲染进程,但从一个页面打开另一个页面,而新页面和当前页面属于同一站点的话,那么新页面会复用父页面的渲染流程

GPU进程:GPU的初衷是为了使用3D CSS效果,随后网页、Chrome的UI界面都采用了GPU来绘制,使得GPU成为浏览器普遍的需求,Chrome在其多进程架构上也引入了GPU进程

网络进程:主要负责页面的网络资源加载

插件进程:主要负责插件的运行,因插件容易崩溃,所以需要通过插件进程来隔离,保证插件进程崩溃不会对浏览器和页面造成影响。[1] [张2]

1. 构建DOM树

服务器响应浏览器的HTML请求后,浏览器进程开始准备渲染流程,浏览器进程解析HTML文件,构建DOM树

2. 样式计算

CSS解析

CSS样式来源主要有三种:

1. 通过link或@import引入外部CSS

2. 标记内的CSS

3. 元素style的属性内嵌的CSS

解析CSS的顺序是浏览器样式>用户自定义样式>页面link标签等引进来的样式>style标签的内联样式

浏览器的渲染引擎接收到CSS文本时,将CSS文本转换为浏览器可以理解的结构styleSheets(CSSOM)

3. 布局阶段

1. 创建布局树

DOM树中的所有可见节点,并把这些节点加到布局中

忽略不可见节点,比如:head标签,具有display:node样式的元素

2. 布局计算

根据布局树对各节点的几何坐标位置进行计算,输出带有坐标位置的布局树

4. 分层(layer)

在生成布局树之后不能直接绘制,渲染进程会将一些复杂的3D动画,滚动条,z-index层级高的生成图层,并生成一颗图层树交给GPU加速渲染。

可以通过chrome开发工具,选择more tool下的layers标签,来查看网页的图层状态。

拥有层叠上下文对象的元素会被提升为单独的一层。

文档中层叠上下文满足以下任意一个条件的元素形成:

1. 根元素(html)

2. z-index值不为auto的绝对/相对定位元素

3. fixed/sticky定位

4. z-index值不为auto的flex子项

5. opacity属性值小于1的元素

6. transform、filter、perspective、clip-path、mask、mask-image、mask-border属性值不为none的元素

7. isolation属性被设置为isolate的元素

8. -webkit-overflow-scrolling属性值为touch的元素

9. 在will-change中指定任意CSS属性

10. contain属性为layout、paint或者综合值(如:strict、content)

在层叠上下文中,子元素同样按照这个规则进行层叠。重要的是,子级层叠上下文的z-idnex值只在父级中有意义,子级层叠上下文被自动视为父级层叠上下文的一个独立单元。

需要剪裁(clip)的地方会被创建图层

当子元素需要展示的区域大于父元素的大小时,就会需要剪裁。出现剪裁情况的时候,渲染引擎回味文字部分单独擦护功能键一个层,如果出现滚动条,滚动条也会被提升为单独的层。

下面看这么一个案例:

总结:元素有了层叠上下文属性或者需要被剪裁,满足任意一点,就会提升为单独一层。

5. 图层绘制:

渲染引擎会把一个图层的绘制拆分成很多小绘制指令,然后把这些指令按照顺序组成待绘制列表

6.栅格化(光栅化):

栅格化的过程就是将图块转化成位图的过程。图块是栅格化的最小单位(通常为256×256或者512×512)。合成线程会按照视口附近的图块优先生成位图的原则将图块生成位图,而实际生成位图的操作是由栅格化来执行的。渲染过程中借用GPU来加速生成,最后将生成的位图保存到GPU内存中。

7. 合成:

图块被栅格化后完成后,合成线程会生成绘制图块的指令-DrawQuad并提交给浏览器进程。浏览器进程viz组件,用来接收DrawQuad指令,然后将页面内容会知道内存中,最后将内存数据显示在屏幕上。

8.总结

完整的渲染流程大致总结如下:

1.渲染引擎将HTML内容转换为DOM树结构

2.渲染引擎将CSS样式表转化为浏览器理解的styleSheets,计算DOM节点样式

3.创建布局树,计算元素的布局信息

4.对布局树进行分层,生成分层树

5.对每个图层生成绘制列表,并将其提交到合成线程

6.合成线程将图层分成图块,并在栅格化线程池中将图块转换成位图

7.合成线程发送绘制图块命令DrawQuad给浏览器进程

8.浏览器进程根据DrawQuad生成页面,显示在显示器上

[3] [张4]

CSS解析和JS解析

1. CSS不会阻塞DOM解析,但会阻塞页面渲染

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
div {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
</style>
<link rel="stylesheet" href="./index.css" />
<script src="./index.js" defer></script>
</head>
<body>
</body>
</html>

//index.js
const div = document.querySelector("div");
console.log(div);
//index.css
div {
width: 200px;
height: 200px;
background: gray;
}
//server.js
const express = require("express");
const fs = require("fs");
const app = express();

app.get("/", (req, res) => {
fs.readFile("./index.html", (err, data) => {
res.send(data.toString());
});
});
app.get("/index.css", (req, res) => {
res.set("Content-Type", "text/css");
fs.readFile("./index.css", (err, data) => {
console.log(data);
setTimeout(() => {
res.send(data.toString());
}, 3000);
});
});
app.get("/index.js", (req, res) => {
fs.readFile("./index.js", (err, data) => {
res.send(data.toString());
});
});
app.listen(8080, (err) => {
if (err) {
console.log(err);
} else {
console.log("服务器启动成功");
}
});

script标签上的defer属性是通知浏览器该脚本在文档完成解析后执行,这样在DOM解析后马上能打印出来div。

通过结果看的出来,css文件内容会延迟3秒后响应,通过效果看出来的是控制台先打印的div标签,3秒后div蓝色背景样式出来,这就证明了css是不会阻塞DOM解析的。

CSS解析不会阻塞DOM解析,那我们认为的应该是div背景色的一个改变,从红色变为灰色,但是效果是仅仅呈现了最终结果灰色,没有变色这个过程,因此CSS是阻塞页面渲染的。

2. JS阻塞DOM解析,浏览器遇到<script>标签时,会触发页面渲染

当把scrpit标签的defer属性删除掉,我们延迟加载js文件,发现我们打印的结果是null,随后页面才会出现效果,这个效果说明JS阻塞了DOM解析。

现代浏览器会先提前下载script,link,src等标签的资源,不会等解析到标签的时候才下载。

当我们把script标签和link标签放在div标签下面加载的时候,发现页面会先展示红色然后变成灰色的一个过程,浏览器在遇到script标签的时候渲染了一次页面,加载完css文件后,由重新渲染了一次。这是因为浏览器不知道脚本内容,因此碰到脚本内容时,先渲染一遍页面,确保脚本获取到最新的DOM信息。

总结:

1. CSS不会阻塞DOM解析,但会阻塞DOM渲染

2. JS阻塞DOM解析,但浏览器会预先下载相关资源

3. 浏览器遇到scirpt且没有defer或async属性的时,会触发页面渲染,如果前面CSS资源未加载完毕,浏览器会等待加载完成后执行脚本

DOM的重绘和回流(Repaint&Reflow)

1. 重绘:元素样式的改变(但宽高、大小、位置等不变)如:outline,visibility,color等

2. 回流(重排):元素的大小或者位置发生了变化(当页面布局和几何信息发生变化的时候),触发了重新布局,导致渲染树重新计算布局和渲染。如:添加或删除可见的DOM元素;元素的位置、尺寸发生变化,内容发生变化(文本变化或图片被另一个尺寸图片替代)

注意:回流一定会触发重绘,重绘不一定发生回流,回流比重绘会更消耗性能,他们会导致web应用的UI反映迟钝。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
#box {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
let box = document.getElementById("box");
/*
分离读写:
box.style.width = "200px";
console.log(box.clientHeight) 这一步会修改渲染机制,会造成两次回流
box.style.height = "200px";
box.style.margin = "200px";
现代浏览器有渲染等待机制,会触发一次回流(重排),老版浏览器会触发三次回流(重排)
*/

/*
批量处理(样式集中改变)
box.style.cssText="width:20px,height:20px"
box.className="box"
*/

/*
缓存布局信息
因为有读操作box.clientWidth和box.clientHeight 会触发两次回流
box.style.width = box.clientWidth+10+'px'
box.style.heght = box.clientHeight+10+'px'
实现(本质:分离读写):
a=box.clientWidth b=box.clientHeight
box.style.width = a+10+'px'
box.style.heght = b+10+'px'
*/
/*
元素批量修改
1.文档碎片
let frg = document.createDocumentFragment()
for (let i = 0; i < 5; i++) {
let newLi = document.createElement("li");
newLi.innerHTML = i;
//box.appendChild(frg); 触发5次回流
frg.appendChild(newLi);
}
// 一次性把内容放到容器中,触发一次回流
box.appendChild(frg);
frg = null;
2. 字符串拼接
let str=''
for (let i = 0; i < 5; i++) {
str+= '<li>i</li>'
}
box.innerHTML(str); //触发一次回流
str = ''
*/
/*
动画效果应用到postion属性为absolute或fixed的元素(脱离文档流,防止影响其他元素)
*/
/*
CSS3硬件加速(硬件加速规避回流)
使用CSS样式:transform、opacity等这些属性会触发硬件加速,不会引入回流和重绘
box.style.left = '100px'//触发一次回流
box.style.transform='translateX('200px')'
*/
/*
牺牲平滑度换取速度
每次1像素移动动画,如果动画使用100%CPU,动画就会看上去跳动的,浏览器不断的在更新回流
每次移动3像素效果的话平滑度降低了,但不会导致在CPU较慢的机器中抖动
*/
/*
避免table布局和使用CSS的javascript表达式(尽可能不使用table)
*/
</script>
</body>
</html>

[5] [张6] 我们可以通过以下几种方式来避免DOM的回流

1. 放弃传统操作DOM,基于vue、react数据影响视图模数

2. 分离读写操作(现代浏览器都有渲染队列的机制)

3. 样式集中改变

4. 缓存布局信息

5. 元素批量修改

6. 动画效果应用到position属性为absolute或fixed的元素(脱离文档流)

7. CSS3硬件加速

8. 牺牲平滑度换取速度

9. 避免table布局


web前端之二叉搜索树

web页面重构如何操作

Webpack优化构建速度

WebView和原生是如何通信

Web Services 平台元素

相关推荐

俄罗斯的 HTTPS 也要被废了?(俄罗斯网站关闭)

发布该推文的ScottHelme是一名黑客,SecurityHeaders和ReportUri的创始人、Pluralsight作者、BBC常驻黑客。他表示,CAs现在似乎正在停止为俄罗斯域名颁发...

如何强制所有流量使用 HTTPS一网上用户

如何强制所有流量使用HTTPS一网上用户使用.htaccess强制流量到https的最常见方法可能是使用.htaccess重定向请求。.htaccess是一个简单的文本文件,简称为“.h...

https和http的区别(https和http有何区别)

“HTTPS和HTTP都是数据传输的应用层协议,区别在于HTTPS比HTTP安全”。区别在哪里,我们接着往下看:...

快码住!带你十分钟搞懂HTTP与HTTPS协议及请求的区别

什么是协议?网络协议是计算机之间为了实现网络通信从而达成的一种“约定”或“规则”,正是因为这个“规则”的存在,不同厂商的生产设备、及不同操作系统组成的计算机之间,才可以实现通信。简单来说,计算机与网络...

简述HTTPS工作原理(简述https原理,以及与http的区别)

https是在http协议的基础上加了一层SSL(由网景公司开发),加密由ssl实现,它的目的是为用户提供对网站服务器的身份认证(需要CA),以至于保护交换数据的隐私和完整性,原理如图示。1、客户端发...

21、HTTPS 有几次握手和挥手?HTTPS 的原理什么是(高薪 常问)

HTTPS是3次握手和4次挥手,和HTTP是一样的。HTTPS的原理...

一次安全可靠的通信——HTTPS原理

为什么HTTPS协议就比HTTP安全呢?一次安全可靠的通信应该包含什么东西呢,这篇文章我会尝试讲清楚这些细节。Alice与Bob的通信...

为什么有的网站没有使用https(为什么有的网站点不开)

有的网站没有使用HTTPS的原因可能涉及多个方面,以下是.com、.top域名的一些见解:服务器性能限制:HTTPS使用公钥加密和私钥解密技术,这要求服务器具备足够的计算能力来处理加解密操作。如果服务...

HTTPS是什么?加密原理和证书。SSL/TLS握手过程

秘钥的产生过程非对称加密...

图解HTTPS「转」(图解http 完整版 彩色版 pdf)

我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。...

HTTP 和 HTTPS 有何不同?一文带你全面了解

随着互联网时代的高速发展,Web服务器和客户端之间的安全通信需求也越来越高。HTTP和HTTPS是两种广泛使用的Web通信协议。本文将介绍HTTP和HTTPS的区别,并探讨为什么HTTPS已成为We...

HTTP与HTTPS的区别,详细介绍(http与https有什么区别)

HTTP与HTTPS介绍超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的...

一文让你轻松掌握 HTTPS(https详解)

一文让你轻松掌握HTTPS原文作者:UC国际研发泽原写在最前:欢迎你来到“UC国际技术”公众号,我们将为大家提供与客户端、服务端、算法、测试、数据、前端等相关的高质量技术文章,不限于原创与翻译。...

如何在Spring Boot应用程序上启用HTTPS?

HTTPS是HTTP的安全版本,旨在提供传输层安全性(TLS)[安全套接字层(SSL)的后继产品],这是地址栏中的挂锁图标,用于在Web服务器和浏览器之间建立加密连接。HTTPS加密每个数据包以安全方...

一文彻底搞明白Http以及Https(http0)

早期以信息发布为主的Web1.0时代,HTTP已可以满足绝大部分需要。证书费用、服务器的计算资源都比较昂贵,作为HTTP安全扩展的HTTPS,通常只应用在登录、交易等少数环境中。但随着越来越多的重要...

取消回复欢迎 发表评论: