浏览器的工作原理

news/2024/5/19 10:51:12

参考:渲染页面:浏览器的工作原理 - Web 性能 | MDN (mozilla.org) 

           Web 性能 | MDN (mozilla.org)


Web性能影响因素

首先有两个,一个是网络延迟,一个是大部分情况下浏览器都是单线程执行的

保障页面快速加载的最大威胁是网络延迟,所以就要让网站加载速度尽可能快,以便用户尽快获取所需信息。网络延迟是将字节传输到计算机的时间。Web 性能优化需要做的就是使页面尽可能快地加载完成。

大部分情况下,浏览器被认为是单线程的。也就是说,它们在执行一个任务之前会从头到尾完成一个任务,然后才会接受另一个任务。为了实现流畅的交互,开发者的目标是确保网站的交互性能良好,从流畅的滚动到对触摸的响应。渲染时间非常关键,我们需要确保主线程能够完成交给它的所有工作,并且始终能够处理用户交互。通过理解浏览器的单线程特性,并尽可能和适当地减少主线程的责任,可以提高网页性能,以确保渲染流畅,并且对交互的响应是即时的。

也就是浏览器一次只能执行一个命令嗷,我的理解就是浏览器会尽全力去执行你下达的命令,但一次一个,全力完成

导航

导航是加载的第一步。什么时候会发生呢

它发生在以下情形:用户通过在地址栏输入一个 URL、点击一个链接、提交表单或者是其他的行为。

Web 性能优化的目标之一就是缩短导航完成所花费的时间,在理想情况下,它通常不会花费太多的时间,但是网络延迟和带宽会让它变久。

DNS查询

现在来打个比分,你要去找朋友玩,找小明,但你忘记了他们家的地址,你手上有一个地址本,你就可以通过找小明这个名字,来查询到他们家的地址

上面的情况其实就是你的浏览器,要跳转到一个网站,但是之前没有访问过,没有缓存记录,那就需要通过DNS这个地址本,来查阅网站的对应ip。

浏览器向域名服务器发起 DNS 查询请求,最终得到一个 IP 地址。第一次请求之后,这个 IP 地址可能会被缓存一段时间,这样可以通过从缓存里面检索 IP 地址而不是再通过域名服务器进行查询来加速后续的请求。

每个主机名 在页面加载时通常只需要进行一次 DNS 查询。但是,对于页面指向的不同的主机名,则需要多次 DNS 查询。如果字体、图像、脚本、广告和网站统计都有不同的主机名,则需要对每一个主机名进行 DNS 查询。

但是对于移动网络,DNS 查询可能存在性能问题。当一个用户使用移动网络时,所有 DNS 查询必须从手机发送到基站,然后到达一个权威 DNS 服务器。手机、信号塔、域名服务器之间的距离会显著增加延迟。

TCP握手

之前上的计算机网络中,大部分知识都快忘记了,唯独清晰地记得TCP的三次握手

只有获取到服务器的ip地址之后,浏览器才会通过TCP三次握手来与服务器建立连接

TCP 的“三次握手”技术经常被称为“SYN-SYN-ACK”——更确切的说是 SYN、SYN-ACK、ACK——因为通过 TCP 首先发送了三个消息进行协商,然后在两台电脑之间开始一个 TCP 会话。是的,这意味着当请求尚未发出的时候,终端与每台服务器之间还要来回多发送三条消息。

第一次握手:客户端向服务器发送一个SYN包,其中包含了客户端的初始序列号,并将标志位SYN置为1,表示要发起一个连接。客户端进入SYN_SENT状态,等待服务器的确认。

第二次握手:服务器收到SYN包后,确认客户端的SYN请求,并发送一个SYN+ACK包给客户端。这个包中包含了服务器的确认序列号和对客户端的SYN的确认,以及服务器自己的初始序列号。服务器进入SYN_RCVD状态。

第三次握手:客户端收到服务器的SYN+ACK包后,发送一个ACK包给服务器,表示已经收到并确认服务器的SYN+ACK包。这个ACK包的确认序列号是服务器初始序列号加1。发送完毕后,客户端和服务器都进入ESTABLISHED状态,表示连接已经成功建立。

如果没有第三次握手,可能会出现连接状态不一致,资源浪费,数据丢失,安全性问题等等

想到之前计算机网络课本上的一个例子,红蓝两军约定好一起进攻一座敌方基地,他们可以通信,但光靠一方力量是不够的,所以就必须约定好,如果没有限制握手次数的话,就可能出现这样一种情况,红蓝两方一直在确认对方有没有收到自己的上一条信息,所以其实和TCP一样的三次握手就够了,再多也只是浪费

4次挥手就是断开连接的时候用的了

TLS协商

对于通过 HTTPS 建立的安全连接,还需要另一次 "握手"。这种握手,或者说 TLS 协商,决定使用哪种密码对通信进行加密,验证服务器,并在开始实际数据传输前建立安全连接。这就需要在实际发送内容请求之前,再往返服务器五次。

虽然建立安全连接的步骤增加了等待加载页面的时间,但是为了建立一个安全的连接而增加延迟是值得的,因为在浏览器和 web 服务器之间传输的数据不可以被第三方解密。

 

响应

一旦我们建立了和 web 服务器的连接,浏览器就会代表用户发送一个初始的 HTTP(GET)请求对于网站来说,这个请求通常是一个 HTML 文件。一旦服务器收到请求,它将使用相关的响应头和 HTML 的内容进行回复。

初始请求的响应包含所接收数据的第一个字节。首字节时间(TTFB)是用户通过点击链接进行请求与收到第一个 HTML 数据包之间的时间。第一个内容分块通常是 14KB 的数据。

拥塞控制/TCP慢启动

浅谈TCP拥塞控制:慢启动和拥塞避免、快速重传和快速恢复_tcp慢启动-CSDN博客

在传输过程中,TCP 包被分割成段。由于 TCP 保证了数据包的顺序,因此服务器在发送一定数量的分段后,必须从客户端接收一个 ACK 包的确认。

如果服务器在发送每个分段之后都等待 ACK,那么客户端将频繁地发送 ACK,并且可能会增加传输时间,即使在网络负载较低的情况下也是如此。

另一方面,一次发送过多的分段会导致在繁忙的网络中客户端无法接收分段并且长时间地只会持续发送 ACK,服务器必须不断重新发送分段的问题。

为了平衡传输分段的数量,TCP慢启动算法用于逐渐增加传输数据量,直到确定最大网络带宽,并在网络负载较高时减少传输数据量。

传输段的数量由拥塞窗口(CWND)的值控制,该值可初始化为 1、2、4 或 10 MSS(以太网协议中的 MSS 为 1500 字节)。该值是发送的字节数,客户端收到后必须发送 ACK。

如果收到 ACK,那么 CWND 值将加倍,这样服务器下次就能发送更多的数据分段。相反,如果没有收到 ACK,那么 CWND 值将减半。因此,这种机制在发送过多分段和过少分段之间取得了平衡。

解析

浏览器收到第一个数据分块之后,就会开始解析收到的信息,解析是浏览器将通过网络接收的数据转换成为DOM和CSSOM的步骤,通过渲染器在屏幕上将他们绘制成页面

DOM是文件对象模型,是HTML文档的内存中对象表示,它提供了一种表述形式将文档作为一个结构化的节点组以及包含属性和方法的对象,使得开发者可以通过JavaScript代码对页面进行重构,从而增强与页面的交互性。

CSSOM是CSS对象模型,是对CSS样式表的对象化表示,提供了相关API用来操作CSS样式。在W3C标准中,CSSOM包含两部分:Model部分,用于描述样式表和规则的模型;以及View部分,提供与元素视图相关的API。主要用来渲染web页面

即使请求页面的 HTML 大于初始的 14KB 数据包,浏览器也将根据其拥有的数据开始解析并尝试渲染。这就是为什么在前 14KB 中包含浏览器开始渲染页面所需的所有内容,或者至少包含页面模板(第一次渲染所需的 CSS 和 HTML)对于 web 性能优化来说是重要的。但是在渲染到屏幕上面之前,HTML、CSS、JavaScript 必须被解析完成。

构建DOM树

第一步是处理 HTML 标记并构造 DOM 树。

        HTML 标记包括开始和结束标记,以及属性名和值。如果文档格式良好,则解析它会简单而快速。解析器将标记化的输入解析到文档中,构建文档树。

浏览器构建 DOM 树时,这个过程占用了主线程。同时,预加载扫描器会解析可用的内容并请求高优先级的资源,如 CSS、JavaScript 和 web 字体。多亏了预加载扫描器,我们不必等到解析器找到对外部资源的引用时才去请求。它将在后台检索资源,而当主 HTML 解析器解析到要请求的资源时,它们可能已经下载中了,或者已经被下载。预加载扫描器提供的优化减少了阻塞。

关键渲染路径 - Web 性能 | MDN (mozilla.org)

第二步是处理 CSS 并构建 CSSOM 树。CSS 对象模型和 DOM 是相似的。DOM 和 CSSOM 是两棵树。它们是独立的数据结构。浏览器将 CSS 规则转换为可以理解和使用的样式映射。浏览器遍历 CSS 中的每个规则集,根据 CSS 选择器创建具有父、子和兄弟关系的节点树。

与 HTML 类似,浏览器需要将接收到的 CSS 规则转换为可处理的格式。因此,它重复了 HTML 到对象的过程,但这次是针对 CSS。

CSSOM 树包括来自用户代理样式表的样式。浏览器从适用于节点的最通用规则开始,并通过应用更具体的规则递归地优化计算的样式。换句话说,它级联属性值。

构建 CSSOM 非常快,并且在当前的开发工具中没有以独特的颜色显示。相反,开发人员工具中的“重新计算样式”显示解析 CSS、构建 CSSOM 树和递归计算计算样式所需的总时间。在 web 性能优化方面,它是可轻易实现的,因为创建 CSSOM 的总时间通常小于一次 DNS 查询所需的时间。

渲染

渲染步骤包括样式、布局、绘制,在某些情况下还包括合成。在解析步骤中创建的 CSSOM 树和 DOM 树组合成一个渲染树,然后用于计算每个可见元素的布局,然后将其绘制到屏幕上。在某些情况下,可以将内容提升到它们自己的层并进行合成,通过在 GPU 而不是 CPU 上绘制屏幕的一部分来提高性能,从而释放主线程。

样式

第三步是将 DOM 和 CSSOM 组合成渲染树。计算样式树或渲染树的构建从 DOM 树的根开始,遍历每个可见节点。不会被显示的元素就不会被包含在渲染树中

布局

第四步是在渲染树上运行布局以计算每个节点的几何体。布局是确定呈现树中所有节点的尺寸和位置,以及确定页面上每个对象的大小和位置的过程。重排是后续过程中对页面的任意部分或整个文档的大小和位置的重新计算。

渲染树构建完毕后,浏览器就开始布局。渲染树标识了哪些节点会显示(即使不可见)及其计算样式,但不标识每个节点的尺寸或位置。为了确定每个对象的确切大小和位置,浏览器会从渲染树的根开始遍历。

在网页上,大多数东西都是一个盒子。不同的设备和不同的桌面设置意味着无限数量的不同视区大小。在此阶段,根据视口大小,浏览器将确定屏幕上所有盒子的大小。以视口大小为基础,布局通常从 body 开始,设置所有 body 后代的大小,同时给不知道其尺寸的替换元素(例如图像)提供占位符空间,空间大小以相应元素盒模型的属性为准

就是在CSS中经常提及的box,那就是浏览器中绝大部分的对象都是一块一块的,而不是显示出来的一个个

第一次确定每个节点的大小和位置称为布局。随后对节点大小和位置的重新计算称为重排。在我们的示例中,假设初始布局发生在返回图像之前。由于我们没有声明图像的尺寸,因此一旦知道图像的尺寸,就会出现重排。

绘制

关键渲染路径中的最后一步是将各个节点绘制到屏幕上

在绘制或光栅化阶段,浏览器将在布局阶段计算的每个盒子转换为屏幕上的实际像素。绘制涉及将元素的每个可见部分绘制到屏幕上,包括文本、颜色、边框、阴影以及按钮和图像等替换元素。浏览器需要以超快的速度执行这个过程。

绘制可以将布局树中的元素分解为多个层。将内容提升到 GPU 上的层(而不是 CPU 上的主线程)可以提高绘制和重新绘制性能。有一些特定的属性和元素可以实例化一个层。

合成+交互

当文档的各个部分以不同的层绘制,相互重叠时,必须进行合成,以确保它们以正确的顺序绘制到屏幕上,并正确显示内容。

当页面继续加载资源时,可能会发生回流,回流会触发重新绘制和重新合成。如果我们定义了图像的大小,就不需要重新绘制,只需要绘制需要重新绘制的层,并在必要时进行合成。但如果我们没有定义图像大小,所以从服务器获取图像后,渲染过程将返回到布局步骤并从那里重新开始。

当页面中的元素的大小、位置或布局方式发生改变时,浏览器就需要进行回流来调整布局。这个过程涉及到遍历渲染树,计算每个元素的几何属性,然后更新布局。回流是一种非常消耗性能的操作,因为它会触发浏览器重新布局整个页面的过程。

但主线程绘制页面完成还有一项工作,如果主线程正在解析、编译和执行 JavaScript,则无法及时(小于 50ms)响应用户交互。我的理解就是,呐,页面现在很漂亮了,但只是看起来很漂亮而已,还要等JavaScript加载完成,这样子用户的点击或者什么操作才能被及时响应,如果说,浏览器还在加载其他对象,那对于交互事件就是没有响应的了


http://www.mrgr.cn/p/45602677

相关文章

创建钉钉审批流实例

1、依赖 <!--钉钉 api --> <dependency><groupId>com.aliyun</groupId><artifactId>dingtalk</artifactId><version>2.0.14</version> </dependency> <!--钉钉 事件订阅--> <dependency><groupId>co…

MATLAB实现蚁群算法栅格路径优化

蚁群算法是一种模拟自然界中蚂蚁觅食行为的优化算法&#xff0c;常用于解决路径规划问题。在栅格路径优化中&#xff0c;蚁群算法可以帮助找到从起点到终点的最优路径。以下是蚁群算法栅格路径优化的基本流程步骤&#xff1a; 初始化参数&#xff1a; (1)设置蚂蚁数量&#xff…

NumPy 1.26 中文官方指南(五)

NumPy 许可证原文:numpy.org/doc/1.26/license.htmlCopyright (c) 2005-2023, NumPy Developers. All rights reserved.Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:* …

NumPy 1.26 中文官方指南(一)

NumPy 用户指南原文:numpy.org/doc/1.26/user/index.html本指南是一个概述,解释了重要特性;细节请参阅 NumPy 参考文档。 入门指南什么是 NumPy?安装NumPy 快速入门NumPy:初学者的绝对基础基础知识和用法NumPy 基础知识数组创建对 ndarrays 进行索引使用 NumPy 进行 I/O数…

5分钟——快速搭建后端springboot项目

5分钟——快速搭建后端springboot项目 1. idea新建工程2. 构建pom.xml文件3. 构建application.yml配置文件4. 构建springboot启动类5. 补充增删改查代码6. 运行代码7. 下一章 1. idea新建工程 点击右上角新建一个代码工程 别的地方不太一样也不用太担心&#xff0c;先创建一个…

NumPy 1.26 中文官方指南(二)

NumPy 1.26 中文官方指南(二) NumPy: 绝对初学者的基础知识原文:numpy.org/doc/1.26/user/absolute_beginners.html欢迎来到 NumPy 的绝对初学者指南!如果你有评论或建议,请不要犹豫联系我们! 欢迎来到 NumPy! NumPy(Numerical Python)是一个开源的 Python 库,几乎在…

spark standalone同时运行pyspark和spark-shell

需要限制资源数量,使用 spark.cores.max 或 --total-executor-cores 来指定最大核数。 假设集群一共4c5.6g pyspark(使用2c2g) from pyspark.sql import SparkSessionspark = SparkSession.builder \.master("spark://worker1:7077") \.appName("pysparkApp&…

解决Vue3项目运行控制台警告

运行Vue3项目,控制台警告:Feature flag VUE_PROD_HYDRATION_MISMATCH_DETAILS is not explicitly defined. You are running the esm-bundler build of Vue, which expects these compile-time feature flags to be globally injected via the bundler config in order to ge…

Redis入门到通关之数据结构解析-SkipList

文章目录 ☃️概述☃️总结 欢迎来到 请回答1024 的博客 &#x1f353;&#x1f353;&#x1f353;欢迎来到 请回答1024的博客 关于博主&#xff1a; 我是 请回答1024&#xff0c;一个追求数学与计算的边界、时间与空间的平衡&#xff0c;0与1的延伸的后端开发者。 博客特色&…

解决警告

运行Vue3项目,控制台警告:Feature flag VUE_PROD_HYDRATION_MISMATCH_DETAILS is not explicitly defined. You are running the esm-bundler build of Vue, which expects these compile-time feature flags to be globally injected via the bundler config in order to ge…

日本岛津电子天平UW UX 系列series 精密电子天平Shimadzu使用说明

日本岛津电子天平UW UX 系列series 精密电子天平Shimadzu使用说明

python-自动化篇-终极工具-用GUI自动控制键盘和鼠标-pyautogui-键盘

文章目录 键盘键盘——记忆宫殿入门——通过键盘发送一个字符串——typewrite()常规——键名——typewrite()常规——按下键盘——keyDown()常规——释放键盘——keyUp()升级——热键组合——hotkey() 键盘 pyautogui也有一些函数向计算机发送虚拟按键&#xff0c;让你能够填充…

微信小程序4~6章总结

目录 第四章 页面组件总结 4.1 组件的定义及属性 4.2 容器视图组件 4.2.1 view 4.2.2 scroll-view 4.2.3 swiper 4.3 基础内容组件 4.3.1 icon ​编辑 4.3.2 text 4.3.3 progress ​编辑 4.4 表单组件 4.4.1 button 4.4.2 radio 4.4.3 checkbox 4.4.4 switch …

手撕sql面试题:根据分数进行排名,不使用窗口函数

分享一道面试题&#xff1a; 有一个分数表id 是该表的主键。该表的每一行都包含了一场考试的分数。Score 是一个有两位小数点的浮点值。 以下是表结构和数据&#xff1a; Create table Scores ( id int(11) NOT NULL AUTO_INCREMENT, score DECIMAL(3,2), PRIMARY KEY…

OpenAI未至,Open-Sora再度升级!已支持生成16秒720p视频

Open-Sora 在开源社区悄悄更新了!现在支持长达 16 秒的视频生成,分辨率最高可达 720p,并且可以处理任何宽高比的文本到图像、文本到视频、图像到视频、视频到视频和无限长视频的生成需求。我们来试试效果。 生成个横屏圣诞雪景,发b站再生成个竖屏,发抖音还能生成16秒的长视…

解决宏定义后面无法加分号

总结&#xff1a;注意是针对单行if语句使用&#xff0c;并且宏定义后面必须带分号&#xff08;格式统一&#xff09; 参考连接 C语言种do_while(0)的妙用_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1vk4y1R7VJ/?spm_id_from333.337.search-card.all.click&vd_…

OpenCV——Bernsen局部阈值二值化方法

目录 一、Bernsen算法1、算法概述2、参考文献二、代码实现三、结果展示Bernsen局部阈值二值化方法由CSDN点云侠原创,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、Bernsen算法 1、算法概述 Bernsen 算法是另一种流行的局部阈值二值化方…

Jenkins CI/CD 持续集成专题四 Jenkins服务器IP更换

一、查看brew 的 services brew services list 二、编辑 homebrew.mxcl.jenkins-lts.plist 将下面的httpListenAddress值修改为自己的ip 服务器&#xff0c;这里我是用的本机的ip 三 、重新启动 jenkins-lts brew services restart jenkins-lts 四 、浏览器访问 http://10.…

Microchip 32位MCU CAN驱动图文教程-附源码

文章目录 创建一个新的32位MCU工程Microchip MCC Harmony配置界面说明在MCC下配置系统的时钟在MCC下配置所需要使用的模块配置调试打印模块配置CAN模块配置管脚功能修改系统堆栈大小生成代码 添加用户代码 创建一个新的32位MCU工程 确保电脑上已经安装最新的MPlab X IDE、XC32编…

黑龙江—等保测评三级安全设计思路

需求分析 6.1、 系统现状 6.2、 现有措施 目前&#xff0c;信息系统已经采取了下述的安全措施&#xff1a; 1、在物理层面上&#xff0c; 2、在网络层面上&#xff0c; 3、在系统层面上&#xff0c; 4、在应用层面上&#xff0c; 5、在管理层面上&#xff0c; 6.…