浏览器解析流程

news2024/9/24 21:29:03

思考

不知道大家是否思考过这几个问题:
当我们在浏览器中输入url后,到底发生了什么?
h5,css,js代码执行的顺序是什么?什么情况下会阻塞页面?又有什么办法可以提高页面响应速度呢?
如果你也一时半会无法完整回答,那么请跟着我的文章一起看看~

一,解析URL

https://blog.csdn.net/sleep_i_like/article/details/136065513?spm=1001.2014.3001.5502

协议:https
域名:blog.csdn.net
路径:sleep_i_like/article/details/136065513
端口:https默认端口是443,也就是说以上的url和
https://blog.csdn.net :443/sleep_i_like/article/details/136065513?spm=1001.2014.3001.5502
访问效果是一样的
参数:?spm=1001.2014.3001.5502

这里需要说明的是DNS解析是耗时的,我们可以通过dns-prefetch来将除站点域名以外的其它域名进行异步预解析:

<link rel="dns-prefetch" href="https://ant.design/components/overview-cn/">

没有使用dns-prefetch页面处理流程:
没有预加载DN流程
使用了dns-prefetch后的处理流程,因为提前异步解析了DNS所以在后续使用时候不会阻塞页面
预加载DNS后的流程

二,渲染页面

首先要知道浏览器解析是从上往下一行一行地解析的。
基于http协议是不用担心数据包丢失的问题与乱序的,因为丢包和重传都是在tcp层解决的。http能保证数据按照顺序接收的!

接收到http响应头中的「content-type」类型时就开始准备渲染进程了,渲染进程是不需要等待所有资源加载完成才进入渲染,当接收到数据流之后,就会开启解析渲染进程,网络进程和渲染进程之间我们可以理解为一根管道,当网络进程接收到数据之后就会往管道里面输送,渲染进程就会在另外一端进行接收,响应体数据一旦接受到便开始做DOM解析了。
浏览器获取HTML并开始构建DOM(文档对象模型 - Document Object Model)。然后获取CSS并构建CSSOM(CSS对象模型 - CSS Object Model)。然后将DOM与CSSOM结合,创建渲染树(Render Tree)。然后找到所有内容都处于网页的哪个位置,也就是布局(Layout)这一步。最后,浏览器开始在屏幕上绘制像素。
合成线程拿到每个层、每个块的位图后,生成一个个「指引(quad)」信息。
指引会标识出每个位图应该画到屏幕的哪个位置,以及会考虑到旋转、缩放等变形。
变形发生在合成线程,与渲染主线程无关,这就是transform效率高的本质原因。
合成线程会把 quad 提交给 GPU 进程,由 GPU 进程产生系统调用,提交给 GPU 硬件,完成最终的屏幕成像。

1.构建DOM

浏览器从磁盘或网络读取HTML的原始字节,并根据(响应头中content-type)文件的指定编码(例如 UTF-8)将它们转换成字符。

符号化是词法分析的过程(Tokenizer),将输入解析为符号,html的符号包括开始标签、结束标签、属性名及属性值。
符号识别器识别出符号后,将其传递给树构建器,并读取下一个字符,以识别下一个符号,这样直到处理完所有输入。
那么如何保证节点之间的父子关系和兄弟关系呢?

HTML 解析器维护了一个 Token 栈结构,该 Token 栈主要用来计算节点之间的父子关系,在第一个阶段中生成的 Token 会被按照顺序压到这个栈中。具体的处理规则如下所示:

如果压入到栈中的是 StartTag Token,HTML 解析器会为该 Token 创建一个 DOM 节点,然后将该节点加入到 DOM 树中,它的父节点就是栈中相邻的那个元素生成的节点。
如果分词器解析出来是文本 Token,那么会生成一个文本节点,然后将该节点加入到 DOM 树中,文本 Token 是不需要压入到栈中,它的父节点就是当前栈顶 Token 所对应的 DOM 节点。
如果分词器解析出来的是 EndTag 标签,比如是 EndTag div,HTML 解析器会查看 Token 栈顶的元素是否是 StarTag div,如果是,就将 StartTag div 从栈中弹出,表示该 div 元素解析完成。

第三步(生成节点对象并构建DOM):事实上,构建DOM的过程中,不是等所有Token都转换完成后再去生成节点对象,而是一边生成Token一边消耗Token来生成节点对象。换句话说完整的一个开始和结束token化后就会被加载在dom中

带有结束标签标识的Token不会创建节点对象
节点对象包含了这个节点的所有属性。例如<img src=’'xx.png/>'标签最终生成出的节点对象中会保存图片地址等信息。

2.构建CSSOM

不完整的CSS是无法使用的,因为CSS的每个属性都可以改变CSSOM,所以会存在这样一个问题:假设前面几个字节的CSS将字体大小设置为16px,后面又将字体大小设置为14px,那么如果不把整个CSSOM构建完整,最终得到的CSSOM其实是不准确的。所以必须等CSSOM构建完毕才能进入到下一个阶段,哪怕DOM已经构建完,它也得等CSSOM,然后才能进入下一个阶段。
所以,CSS的加载速度与构建CSSOM的速度将直接影响首屏渲染速度

3.构建渲染树

浏览器使用 DOM 和 CSSOM 构建出 Render Tree。此时不像构建 DOM 一样把所有节点构建出来,浏览器只构建需要在屏幕上显示的部分,因此像< head>,< meta>这些标签就无需构建了。同时,对于 display: none的元素,也无需构建。

display: none告诉浏览器这个元素无需出现在 Render Tree 中,但是 visibility: hidden只是隐藏了这个元素,但是元素还占空间,会影响到后面的 Layout,因此仍然需要出现在 Render Tree 中。

当Render Tree构建完成后,已经得到了所有元素的自身信息,但是还不知道它们相对于 Viewport 的位置和大小,Layout 这过程需要计算的就是这两个信息。布局完成后,GPU根据「指引(quad)」信息 将渲染树转换成屏幕上的像素。

4.加载javascript

上面在生成cssom时候我们说过,不完整的CSS是无法使用的,因为css每个属性都可以改变CSSOM,那么js代码不光可以改变cssom也可以更改dom,所以JavaScript的加载、解析与执行,如果放在了< head >中是会阻塞DOM和CSSOM的构建
当然这个还是需要分情况的:
情况1:如果js代码在h5和css后面,并且并没有修改dom和cssom,那么并不牵扯js阻塞问题
情况2:当js文件被放置在head标签内部时,浏览器会先加载js文件并执行它,然后才会继续解析HTML文档。因此,如果JavaScript文件过大或服务器响应时间过长,就会导致页面一直处于等待状态,进而影响DOM和CSSOM的构建。
情况3:如果dom已经构建,在随后的JavaScript代码执行时,有对DOM结构或者CSSOM进行了修改,那么浏览器需要重新计算布局(reflow)和重绘(repaint),这个过程会较为耗时,并且会阻塞DOM和CSSOM的构建。

首先弄明白2个script的属性defer和async:
async:表示应该立即开始下载脚本,但不能阻止其他的页面动作,比如下载资源或等待其他脚本加载。
使用async就相当于告诉浏览器立即下载脚本,此时和页面的渲染是异步的,但是当脚本加载完毕后会立即执行该脚本如果此时HTML还未解析完成,会造成阻塞。

<!DOCTYPE html>
<html>
<head>
    <title>使用 async 修饰的 script 标签</title>
    <script async src="script1.js"></script>
    <script async src="script2.js"></script>
</head>
 
<body>
    <h1>使用 async 修饰的 script 标签</h1>
</body>
 
</html>

由于脚本是异步加载的,它将在加载完成后立即执行,而不会按照它们在文档中的顺序执行。这意味着如果引入多个js脚本可能先下载完成的 script2.js 脚本执行。会优先于script1脚本执行;因此,如果脚本之间有依赖关系,需要谨慎管理加载顺序。
此外,因为 async 修饰的脚本会在它们被加载时立即执行,而不需要等待整个文档解析完成。
这可能会导致一些问题,例如脚本可能无法访问尚未解析的 DOM 元素。为了避免这些问题,通常建议将脚本放置在 元素的结尾,以确保在脚本执行时 DOM 已经完全解析。

defer 属性也用于异步加载脚本,但与 async 不同的是,defer加载完后不会立即执行, 会延迟到整个页面解析完成在执行, defer 会保持脚本的执行顺序与其在文档中的顺序一致。
与 async 不同,使用 defer 修饰的脚本会在整个文档解析完成后执行,但在 DOMContentLoaded 事件之前执行。这意味着脚本可以访问完整的 DOM 结构,而不必等待整个文档加载完成。

1.DOMContentLoaded事件
在 HTML 文档解析过程中,当浏览器完成构建 DOM 树,所有的初始 HTML 已经完全加载和解析,但外部资源(如图片、样式表和嵌入的框架)可能还没有完全下载时触发。也就是说,DOMContentLoaded 事件标志着页面的基本结构已经准备就绪,可以进行操作和修改 DOM 元素。

2.load事件 load 事件是在整个 HTML 文档以及所有的外部资源(如图片、样式表、嵌入的框架等)都已经完全加载和解析完成后触发的事件。

使用 load 事件可以确保页面的所有资源都已经被下载并解析完成,可以进行一些比较耗时或需要等待资源加载的操作。不过需要注意的是,load事件的触发时间比 DOMContentLoaded 事件要晚,所以在处理一些与页面元素相关的操作时,需要选择合适的事件来监听

其次我们弄明白浏览器的重绘(repaint)与重排(reflow)
对DOM的修改引发了DOM几何元素的变化,渲染树需要重新计算,会触发重排 而只会改变visibility、outline、背景色等属性导致样式的变化,使浏览器需要根据新的属性进行重绘
相比而言,重排会产生比重绘更大的开销。所以,我们在实际生产中要严格注意减少重排的触发。
触发重排的操作:
1页面初始渲染:页面第一次渲染所有组件都要进行首次布局,这是开销最大的一次重排。
2.浏览器窗口尺寸改变
3.元素位置和尺寸发生改变的时候
4.新增和删除可见元素
5.元素内容发生改变(文字数量或图片大小等等)
6.元素字体大小变化。
7.激活CSS伪类(例如::hover)。
8.设置style属性
9.查询某些属性或调用某些方法。比如说:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight
除此之外,当我们调用getComputedStyle方法,或者IE里的currentStyle时,也会触发重排,原理是一样的,都为求一个“即时性”和“准确性”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2073964.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

再说圆的面积

在微积分-圆的面积和周长(1)介绍微积分方法求解圆的面积&#xff0c;本文使用蒙特卡洛方法求解圆面积。 取&#xff08;0&#xff0c;1&#xff09;* (0,1)区间&#xff0c;也就是单位圆第一象限的端点区间对应的正方形区间。下面是计算机给出的结果&#xff1a;很显然第一象限…

基于vue3和audio封装的简易音频播放器

样式如图所示 <template><div class"audio-player"><div class"player_top" flex-ac flex-justify-between ><div class"fileName genericTitle" fs-28 l-height-32 height-64 pr-42 flex-ac><span class"t…

UE管理内容 —— FBX Morph Target Pipeline

目录 Naming Setting Up Morph Targets Importing Morph Targets Morph Target 是特定网格体的顶点位置的快照&#xff0c;该网格体在某种程度上已经变形&#xff1b;例如&#xff0c;可以使用一个角色模型&#xff0c;对其面部进行重塑以创建一个面部表情&#xff0c;然后将…

Linux 流式DMA映射(DMA Streaming Mapping)

流式DMA相关的接口为dma_map_sg(),dma_unmap_sg(),dma_map_single(),dma_unmap_single()。流式DMA一般用于已经分配好的内存&#xff0c;然后再对其进行DMA操作&#xff0c;而不是提前申请好一块cache一致性的内存给DMA用。例如从协议栈里发下来的一个包&#xff0c;想通过网卡…

day41| 01背包问题一 01背包问题二(滚动数组篇)416. 分割等和子集 1049.最后一块石头的重量II 494. 目标和 474. 一和零

文章目录 背景介绍01背包问题一思路方法一方法二01背包问题二(滚动数组篇)思路方法一方法二416. 分割等和子集思路方法一1049.最后一块石头的重量II思路方法一494. 目标和思路方法方法二 回溯法474. 一和零思路方法总结由于笔试的时候会判重,而这里面的代码都是我自己写的,…

不同场景下的负载均衡器

负载均衡主要用于分配来自互联网或局域网的请求或任务负载到多个服务器中。 这样做可以避免任何单个服务器的过载&#xff0c;提高响应速度&#xff0c;增加系统的整体处理能力&#xff0c;并确保系统的高可用性和可靠性。 负载均衡器大概可以分为 3 类&#xff0c;包括&#…

Argo/BGC-Argo数据下载

BGC-Argo官方网站 网址&#xff1a; https://biogeochemical-argo.org/data-access.php 信息&#xff1a;提供BGC-Argo位置及剖面预览 数据ftp下载&#xff1a;ftp://ftp.ifremer.fr/ifremer/argo 或者 ftp://usgodae.org/pub/outgoing/argo 问题&#xff1a;dac文件按照数据中…

Image Stride(内存图像行跨度)

When a video image is stored in memory, the memory buffer might contain extra padding bytes after each row of pixels. The padding bytes affect how the image is store in memory, but do not affect how the image is displayed. 当视频图像存储在内存时&#xff0…

EVE-NG安装部署使用

EVE-NG安装部署使用 一、EVE的虚拟化安装1、下载EVE-NG(社区版)2、导入虚拟机-配置-登录二、EVE中设备的连接sercureCRT连接wireshark连接一、EVE的虚拟化安装 1、下载EVE-NG(社区版) 官网下载地址(科学上网): https://www.eve-ng.net/index.php/download/ 中文网下载…

基于python django的图书数据分析系统,包括图书推荐和可视化大屏分析,带有后台

研究背景 随着数字化技术的发展&#xff0c;图书管理与数据分析在图书馆和在线图书销售平台中变得越来越重要。传统的图书管理方式通常只关注图书的借阅和归还&#xff0c;忽视了数据分析在图书管理中的潜力。通过对图书借阅、购买、和用户偏好等数据的分析&#xff0c;能够深入…

数论之组合数

组合数1&#xff1a; 预处理每一个组合数的大小 类似于dp&#xff0c;从a个苹果里面选b个出来&#xff1a;首先从a个苹果里面拿出来一个&#xff0c;这样就分成了两种&#xff0c;一种是包括这个拿出来的苹果的方案数&#xff0c;此时就只需要拿b-1个苹果。一种是不包括这种苹…

嵌入式笔记:半加器与全加器

一&#xff0c;门电路 本文使用digital软件中的双掷继电器来实现以下的门电路&#xff0c;并结合这些门电路实现半加器与八位全加器。 与门 当输入信号A&#xff0c;B都置高电平时&#xff0c;继电器带电具有磁性&#xff0c;将下方双刀开关吸附&#xff0c;使电路导通。在输出…

C++20中的约束与概念

类模板、函数模板和非模板函数(通常是类模板的成员)可能与约束(constraint)相关联&#xff0c;该约束指定对模板参数的要求(requirements)&#xff0c;可用于选择最合适的函数重载和模板特化。约束是使用模板时需要通过模板参数满足的条件或要求。这些要求的命名集合称为概念(c…

Ai+若依(系统接口--Swagger):04篇

Swagger&#xff0c;能够自动生成 API 的同步在线文档&#xff0c;并提供Web界面进行接口调用和测试。 可以直接去测试&#xff1a;--有的接口测试需要权限 我们可以去这样操作 F12 报错404 是因为多了个前缀 /dev-api 我们去后台删掉&#xff1a; 重启刷新&#xff1a;

day 39 代码随想录 | 打家劫舍 动态规划

198.打家劫舍 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个…

Ruby+Watir进行web UI自动化测试

1.新建工程文件 打开RubyMine&#xff0c;新建一个工程文件目录如下&#xff1a; login_mail.rb文件 # encoding:UTF-8 # frozen_string_literal: true当(/^打开谷歌浏览器&#xff0c;进入163邮箱登陆页面$/) do$driver Watir::Browser.new :chromesleep(2)$driver.window.…

裸机:串口通信

串口通信的基本原理 单工通信和双工通信 (1)单工就是单方向&#xff0c;双工就是双方同时收发&#xff0c;同时只能但方向但是方向可以改变叫半双工 (2)如果只能A发B收则单工&#xff0c;A发B收或者B发A收&#xff08;两个方向不能同时&#xff09;叫半双工&#xff0c;A发B收…

【C++】类与对象篇一

【C】类与对象篇一 一 .面向过程和面向对象初步认识二 .类的详解1.类的引入2.类的定义3.类的访问限定符及封装&#xff08;面试题&#xff09;4.类的作用域5.类的实例化6.类对象模型 三 . 结构体内存对齐规则&#xff08;面试题&#xff09;四 . this指针1.this指针的特性2.thi…

WOFOST的web应用

目录 运行可视化 参考链接 https://github.com/irripro/WOFOST_streamlit/tree/main 运行 运行主程序.py之后&#xff0c;得到一串命令 将该命令放到命令台中运行 然后会转到WOFOST的web端上 可视化 目前好像只支持欧洲区域的模拟运行

C++篇:C向C++迈进(上)

引言 C语言作为编程基石&#xff0c;其高效与直接性深受开发者喜爱。然而&#xff0c;随着软件复杂度的增加&#xff0c;C以其面向对象及高级特性成为了新的选择。我们接下来将学习C&#xff0c;从C语言迈向C。 什么是C C 是一种高级语言&#xff0c;由 Bjarne Stroustrup 于…