ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

网页的渲染流程

2021-11-16 08:33:00  阅读:164  来源: 互联网

标签:浏览器 渲染 流程 dom 进程 网页 界面 css


broswer_theory.jpg

要说清楚从浏览器输入一串URL输入到界面展示的过程是一个并不容易的工作。这个问题确实可以全面考察一个人的计算机知识,以及对它们的熟悉深度。如果细说这些理论,完全可以编辑成一本书;而如果说简单的说,也可以寥寥数语就说完。我们这篇博文总体是从一名前端工程师的角度来看待这件事情的。从计算机基础,到网络传输再到浏览器的渲染原理,每一部分涉及的深度和广度都会不一样。例如:我们会更少地涉及计算机基础,而更多地关注浏览器渲染原理,因为后者才是前端工程师的主战场;在介绍网络篇的时候我们也只是列出了网络包体发送的几个耗时间的关键步骤,如果要深究细节,一篇博文是远远不够的。最后,对底层原理越是深入了解,在实际应用中就越能透过现象看到问题的本质,并且最终解决它。

系统阶段

为了了解浏览器是如何讲用户的输入行为转化称应用界面的,我们需要向下看一点,回到我们学习过的计算机基础层面,了解这些概念,有助于从宏观视角上去理解浏览器是如何工作的。

CPU、进程

cpu是电脑的最核心部件。它处理了每一个电脑的动作上的每一条信息。一个cpu就是一台有效能的机器人,你在电脑上的所有操作最终都会被cpu处理。早期的电脑只有一个cpu,随着电子科学以及芯片制造技术的进步,现在一台电脑都拥有多个cpu,我们平时称拥有多个cpu的电脑为多核电脑,多核意味着处理性能的提升。cpu属于计算机的底层硬件设置,在这之是是操作系统,操作系统是应用程序的底层执行平台。
你打开某个应用,电脑就会为你分配一块内存地址,并且开启一系列的进程为你这个进程服务,每个进程之后都可以通信,我们称这种通信方式为IPC(Internal Processing Communication)。当应用关闭后,内存被释放,进程也随之消失。
16.png

浏览器的多进程架构

浏览器与其他应用一样,启动的时候系统会为他分配一块内存,启动相关的进程,以及GPU服务。一般来说,浏览器启动一个标签的时候打开了至少以下几个进程:

  1. 浏览器进程(Broswer Process):浏览器进程是多个服务的合集。chrome为了权衡服务与内存分配,把多个进程合并到了该进程之中。例如UI进程,设备进程,本地存储以及网络进程。它的主要责任是负责浏览器的UI控制,侦听各种事件响应:如窗口的放大缩小,滚动条的滚动,手势的判断,input的组件的输入以及其他用户交互行为,然后将这些行为通过ipc传递给渲染进程进行处理。
  2. GPU进程(GPU Process):GPU作为图形输出的重要进程,参与到各个应用当中,不仅仅是浏览器应用,其他需要图形服务的应用都会启用该进程。
  3. 渲染进程(Render Process):渲染进程就是主要负责界面的进程。这个进程上运行的v8引擎解析和编译javascrit,负责生成dom的解析器以及以及css解析器生成CSSOM。渲染进程能同时运行多条线程,但是大多数的交互和显示工作是在主线程上完成的。而主线程采用的是事件循环机制,单线程处理各种宏任务和微任务。
  4. 插件进程(Plugin Process):插件进程在运行过程中主要运行的是浏览器的各种插件。插件进程是个沙箱,它与其他的进程是完全隔离的。因为第三方插件很有可能危害用户的信息安全。

17.png
早期的浏览器是单进程的,这是因为那时的电脑大多数是单核浏览器,用户的电脑难以支持多经常的分配操作,所有的进程都合二为一,插件,渲染,网络所有的功能模块都挤在一起,这样就导致了糟糕的用户体验——某个标签卡死了,整个浏览器都奔溃了。单进程的另外一个缺点就是不安全,插件脚本容易被第三方的恶意代码注入html,造成用户的隐私泄漏。2008年11月发布的chrome浏览器采用了多进程的架构,浏览器为每个标签都开辟了一个不同的不同的进程,这些进程互不干扰,彼此为自己的标签页提供相关服务。

渲染进程的分配规则

渲染进程理论上是对每个标签页面进行分配的,这个我们在上文中已经提到。Chrome在版本64中引入了站点隔离技术(site isolation),为每一个iframe也启用一个渲染进程,这样就再次将隔离站点细化。但是每分配一个渲染进程,意味着需要多消耗cpu以及内存,在标签页面过多的时候就会出现内存或者cpu的占用率飙升的情况。不管是window转到mac os系统,chrome浏览器确实是吃掉内存的罪魁祸首。针对内存消耗的问题,浏览器需要对这种固化的原则进行灵活处理。下面我们就来看看chrome团队如何去在性能和体验上作出权衡的。首先我们明确一下两个概念:
浏览器中上下文(Browsing contexts)

A browsing context is an environment in which Document objects are presented to the user.
浏览器上下文指呈现给用户的文档对象所处的环境。例如window对象,历史记录,导航,滚动等文档对象。这些文档对象就被包含在浏览器的上下文中。

浏览器中上下文组(Groupings of browsing contexts)

A browsing context group holds a browsing context set (a set of top-level browsing contexts).
浏览器上下文组,是指一系列文档对象环境的集合。例如从一个界面当中通过标签或者脚本打开的下一个标签,这些标签共同组成一个上下文组。

同一浏览器上下文组打开的同一站点,多个标签会共用一个渲染进程

  1. 不同的上下文组或者不同的站点,浏览器会开辟新的渲染进程。
  2. a标签设置了rel=noopener属性时,通过该标签访问的新标签,会被渲染新的进程。
  3. 标签页和iframe如果是同一站点,也共用同一渲染进程。

以上便是一些渲染进程分配的细节和原则。你可以打开自己的浏览器,通过task面板查看相关的信息。chrome的进程分配使得我们的浏览器更加安全和有效。但这样做也是有代价的:你的电脑cpu和内存消耗会徒然上升,电脑的温度直线飙升。如果你是chrome的用户,我想你一定经历过这样的事情:买电脑,送暖手宝。

开始输入地址

现在,在打开浏览器之后,我们可以开始输入地址了,首先登场的是浏览器进程。万维网的地址为了便于记忆,一般采用单词或者容易记住的字母组合,例如baidu.com|google.com。而服务器IP地址则是按照一定的规则排列的数字组合。所以当用户按下回车键,浏览器进程会首先会拿用户的输入去DNS服务器查找对于的ip地址,同时更新浏览器历史堆栈。浏览器的UI上这时也有变化,一个是亮起的回退键,另外一个是标签页左上角开始转圈圈。

网络阶段

传播速度

科学告诉我们光在真空中的传播速度大约为30万千米每秒,但在其他介质中的速度并没有在真空中那么快。例如光在水中或者在其他介质当中传播的速度就会明显的下降。现在的多数网线采用了光学纤维替代了铜线,而电子信号在这些光学纤维中传播速度大概只有光速的2/3,也就是20万千米每秒。听起来也是很快,但考虑到实际的物理距离,电子信号从相隔较远的亮点之前做一个来回所产生的时间,足够造成用户体验上的损失。例如,中国距离美国大概一万四千公里,数据在客户端到服务端的一个来回(RTT),大概是140ms。140ms听起来不算太久,但是考虑到TCP世界中的游戏规则,我们总共花的时间可能要多少好几倍。

TCP建立链接

在收到浏览器的通知,网络进程便开始去与服务器交互了。网络进程属于浏览器进程中的一部分,负责建立TCP链接,发送和接受网络请求并且与将收到的数据发给渲染进程进行处理。首先网络进程驱动操作系统,建立tcp链接,两台机器建立链接需要相互确认动作,它们会给彼此发送序列号,来表示自己的身份,也就是我们经常听到的三次握手:

  • 客户端生成一个随机序列(SYN) 给服务器。
  • 服务器拿到随机数列,在此随机数上加1,返回另外一个之前的随机数SYN,并且也生成随机数列ACK
  • 客户端收到SYN确认和并且同时确认ACK加一,发送给服务器端,服务器验证了客户端便开始请求后立即发送请求信息。

TCP的建立一共需要三次握手,就是1.5个RTT,如果考虑到如果使用了TSL协议,那么总数达到 2.5RTT。前面我们讲过,不同区域网络传输时长会因为客户端与服务器之间的物理距离而不同,如果物理距离过大,这个时间经过倍数叠加就会变得很长,所以我们常说建立tcp链接是昂贵的。在http1.0的时代,一个域名只允许建立一个tcp链接,并且在http传输完成之后自动关闭tcp链接,客户端如果同时出现很多请求,会被浏览器排队。你可以通过network面板中看到这些信息被阻塞的时长和状态。这种低效的传输模式显然无法支撑日益增长的互联网用户的需求。http急需改良性能。现代浏览器一般同时允许建立4~8个tcp链接,并且保持长久开启(keep alive)的状态,以便继续发送http请求。这暂时缓解了三次握手以及多请求阻塞的问题。但显然,这些都还只是权宜之计。
14.png

TCP传输过程

  • 拥塞窗口

TCP传输的数据并不是一次性全部传输完成的,这些信息会被切分成一个个的小的数据包,分批次传输。为了防止一次性大量发送数据从而导致收发端无法处理,服务器和客户端都对发送的数据包大小做了限制:给定一个初始数据发送大小的值,每次发送数据量都不超过窗口值,窗口值随着rtt的次数增加(在前一个窗口的值上翻倍)。这个限制数据量大小的窗口,我们称之为拥塞窗口****Congestion window (rwnd)。而这种处理数据流的发送方式的行为,我们称之为TCP的慢启动(slow start)
15.png

  • 拥塞避免

TCP在传输过程中有可能出现丢包的情况,为了保障数据的完整性,tcp采用个两种办法避免因为丢包而造成的时间损失。第一种是快速重传(fast retransmit),快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期需要注意的是,重传的起始窗口不再使用初始拥塞窗口值,而是回归在上一次窗口值。这种做称之为快速恢复(fast recovery)
13.png

  • 队头阻塞

我们之前说过tcp传输数据是分片的,并且会出现丢包,重传,慢启动。一个TCP通道只负责传输一个http,这些http就串行起来,在等待重传的过程中,造成了其他后续的包的时间阻塞,网络带宽也被白白浪费了。这就是tcp的对头阻塞。对头阻塞总得来说是http管道技术的不成熟,以及tcp为了保证成的数据包发送策略的结果。对头阻塞对http影响非常大,不过这个问题在http2中被解决了。

TCP小结

http发送之前确实需要做很多事情。tcp就是在为这些事情做准备。总的来说,它花费在握手,慢启动,拥塞窗口算法控制。续后我们会出一篇博文对其进行优化,本篇值对这些影响时间的因素进行说明,无论如何,每个http请求都需要走以便上面的过程。同时,chrome的network面板中还有这些时间的详。关于tcp的数据传输我们完全可以另外开一篇博文甚至是一本书来讲解。不过本篇仅仅把它当作网页加载的一个阶段进行简单的说明。

服务器阶段

动静分离

请求到服务器后一般都是由方向代理服务器负责处理请求分发的。一般来说服务器上都有http的代理服务器,例如我们比较熟悉的Nginx,Apache。这些代理服务器将80端口代理成html的静态资源路径,当我们请求发过来的时候,资源文件会被直接作为字节流返回到浏览器中。

服务器脚本

凡事都有由例外,如今很多前端架构,工程师经常需要动态生成html(如SSR架构的前端网页应用),这种时候html就并非直接由静态服务器直接放回,而是需要经过后台语言的插入数据,生成模板,解析转化html标签等操作生成的。这种操作能够动态生成html,能有效减少因为依赖脚本而界面的时间,所以在前端架构中经常被用到。不过,因为需要经过编程语言,数据查询,异步I/O等处理,这种效率是远远低于前一种方式的。不管采用哪一种方式,我们最终生成的是html格式的文件,这样浏览器才能继续执行我们下面的操作。当然也可以是其他文本类型。不过我们这篇博文主要讲的是html的界面渲染过程,因此暂时忽略其他格式的静态资源。请求内容准备好了之后,服务器便开始讲这些内容返回到客户端了进行下载了。

TTFB

服务器收到了TCP请求,经过了一系列动作,例如:解析参数,分析地址,执行代码,读写文件或者数据库操作等,最终将一段头信息以及内容返回给客户端。从请求发出,到客户端收到服务器发回的第一个字节信息所经历的时间,我们称之为TTFB(Time To First Byte)。TTFB受网络条件和服务器架构影响,在资源体积较小的情况下通常会占有网络过程的大部分时间,TTFB同时是衡量网页性能的一个重要指标,你可以在chrome浏览器的network中查看每个资源的TTFB时间。
25.png

浏览器阶段

接收信息

我们的请求经过万水千山的跋涉,终于回到了浏览器的中。网络进程接收到第一个字节便交给浏览器渲染进程。通常,为了减少包的体积,服务器通常会对资源进行压缩处理。浏览器进程根据服务器返回的压缩包的方式进行对应的解压工作。解压后的信息渲染进程就可以开始处理了。

渲染进程

网络进程收到了第一个字节后,通过ipc通信给渲染进程。渲染进程便开始对dom进行解析。解析的动作是和下载的动作同时进行的,字节一点点的下载下来,同时也被一点点的被渲染引擎解析。dom通过文档结构告知浏览器开始序列化,token等操作生成一棵dom树,这棵数的根节点是html,接下来一点点开枝散叶。

除了字节下载的速度,在渲染过程中还有很多因素制约着DOM文档结构的生成以及绘制。这其中最主要的就是css和javscript文件的下载和执行。Javascript和Css都会影响Dom的解析和渲染,我们后面将会详细地介绍到。其他资源,如视频,图片都会随着dom的解析被下载到浏览器中,但它们都不影响html的解析。我们将css和js这些能影响到界面渲染绘制的资源称之为关键资源(Critical Resources),而这些关键资源的个数和,我们称之为CRP(Critical Rendering Path),通过判断关键资源路径(CRP)可以从宏观的角度计算我们的网络加载速度。

需要注意的是,并非所有js和css都算关键资源,例如添加了defer或者async熟悉的脚本或者根据媒体样式进行分类加载查询的层叠样式表。

现在,我们来对渲染的过程进行稍微深入一点的讲解。大致来说,我们在渲染的过程主要干了以下几件事情:

1.解析dom
将返回的html文本解析成dom树是浏览器的首要任务。随着网络进程一点点的把字节信息返回给渲染浏览器,dom结构便开始一点点的生成。html语法结构宽松,对大小写以及不规范的书写方式较为友好和兼容,在生成dom的时候有些元素比如head或者display:none的元素不会被纳入dom树。渲染引擎解析dom的速度非常非常快,以至于很多时候都必须等待字节被下载下来,为了尽快的渲染出界面,渲染引擎会把首先下载并且渲染过的界面部分直接绘制到屏幕上。等待内容被下载下载,再继续解析和绘制下面的元素。你可以把网速调低一些,打开google,看看它的界面是如何呈现在你的眼前的。dom被完全解析后会触发DomContentLoaded事件。
23.png

2.子资源的下载
早期的html,只有纯文本。而且文字是随着html文档一起被下载下来的。随着web应用的发展,网页应用出现了图片,视频,脚本,样式表等资源文件用来丰富自身的体验。因此,html早不再是一个单份的文本文档。通过特殊的标签(<a><img> <script> 以及<link>),浏览器渲染引擎对其进行解析后会再次发送对应的http请求,整个解析html的过程,同时也是继续下载子资源的过程。
24.jpg

3.脚本的执行

JavaScript是设计给人读写的高级语言,它需要被翻译成底层的,能被计算机读懂的代码才能被执行。V8的引擎的主要工作就是把JS“变成”计算机读懂的机器码。这个过程主要分为以下几个步骤:源码-词法分析-AST树转化-编译成字节码-解释成机器码执行结果:

  • 源码就是你编写的JavaScript代码:let a = 1;
  • 词法分析是将源码进行分词(token),然后根据JS的语法规则进行分析,如果有错误就直接抛出错误,终止后面的步骤。

所谓的token分词,就是将每个代码字符转转化成单元字符串。例如:let 是关键字,a是标识符,=是赋值运算,1则是字符串类型的值。

  • AST Tree即抽象语法树,是为了两种代码互相转化而成的一种中间抽象数据结构。AST应用非常广泛,大多数不同语言的转化甚至是同一语言的不同版本转化都会用到AST。

babel也是采用了AST树来对不同的ES版本进行转化。

  • 字节码是介于AST和机器码之间的一种编码。字节码由V8引擎中的Ignition进行解释。

早期chrome直接将AST转化成机器码,机器码运行速度非常快,但是机器码占用的体积却十分大。这种内存在手机上变得更加紧张。

  • 机器码即计算机能读懂的二进制编码。

20.png

v8编译过的代码,会通过键值对的关系(源码为键,字节码为值)存到一张散列表中,当再次需要编译文件时,V8会从散列表中去查找对应的源码的字节码,无需再次编译。我们都知道,散列表的查找速度非常快O(1),这使得v8在执行重复的脚本时速度非常快。同时,V8对JS重复编译的脚本文件做了大量的优化工作:

  1. 冷启动:如果JS文件是首次被下载下来,V8对其进行编译,同时将其存储在浏览器的缓存中(是运行内存缓存或者硬盘缓存视运行的次数和当前上下文而定)。
  2. 暧启动:该文件第二次请求时,会重浏览器缓存中读取文件,并且被引擎打为这些script打上了metadata缓存的标记。
  3. 热启动:第三次执行该文件时,跳过编译流程。

下图表示了JavaScript代码在三种情况下编译的状况。冷启动中所有代码必须全部进行编译,暧启动则是部分编译;热启动则是完全不需要进行编译的流程了。因此,合理利用缓存不仅仅能够提升网络下载速度,还能提升JavaScript脚本执行速度。
19.png
除了在启动阶段的优化,V8还引入了字节码概念,将重复执行的热代码片段保存在运行内存当中,后续这些代码就无需再次编译了。这个就是著名的即使编译器(Just In Time)技术。被标记的代码由V8中的解释器Turbine进行解析到机器码并且保存在运行内存中,下次无需再次编译直接运行。JIT实际上是用内存中的空间,换取了编译器Ignition生成字节码的时间,是一种典型的用空间换时间的做法。字节码的另外一个优点是可以抽象不同系统硬件架构的机器码,减少了为了兼容硬件设备而需要多写的兼容代码。
以上两点便是V8在启动时和运行时为提高JavaScript执行效率而做的优化。大体来说,都是通过缓存的方式来提高效率。当然,这其中有对于时间和空间的取舍,这种算法策略也会随着硬件性能的提升而变化。

** 4.样式计算**
子资源的另外一种就是css资源。css资源作为界面的样式脚本,由css解析器负责解析计算,并且根据对应的dom树结构,生成一个全新的对象,我们把这样的样式结构称之为CSSOM(层叠样式对象模型)。CSSOM需要和DOM合并生成RenderDom(渲染对象模型)之后,才会被绘制为到网页上。我们上面说过下载中的css是会阻止dom的渲染的,但有时候,它也会阻止dom的解析:

  • css阻止dom的渲染:css本身来说其实是并不会阻止dom的解析,而是阻止dom生成渲染树被绘制到界面上去。浏览器这样做的主要是为了规避闪现给用户造成的不友好体验而涉及的。我们可以假设这样一种情况:Dom已经被绘制到界面上去,而css之后才加载完成,那么整个界面会突然的改变样式。就跟我们把css放到html文档底部是一个道理。如果css放到head中,可以利用css的render blocking机制来实现界面的一次性渲染绘制。
  • css阻止dom的解析:css的下载会阻止Javascript的执行,从而间接地影响Dom的解析。这是因为脚本文件中有操作css的动作,这种操作虽然很少见,但是浏览器是需要预防这种情况的发生的,不让我们的脚本会因为获取不到对象而报错。因此,Javascript需要等待css下载完成之后才能被执行。

22.png
从图中可以看出,css通过阻塞脚本的执行,从而间接地阻断了dom的解析。css是一种关键资源,它不仅仅关系到dom的绘制流程,也同时会阻塞关键资源的下载和执行。

5.界面的布局和绘制
Render Tree生成之后,渲染进程会根据Render Tree计算出一颗布局树(Layout tree)。布局树上包含了每个元素在界面的坐标信息,包括x,y的坐标。同时,也会将display为node的元素剔除。之后,浏览器会计算文档对象书写的顺序以及postion属性对应的值,按次序地将元素绘制到网页上去。
样式计算-布局-绘制这三者按时间保持顺序,它们执行的顺序是按照时间先后的。一旦样式计算发生变化,后面的浏览器又必须重新执行一次,这就是我们经常听到的重绘(repaint)和回流(reflow)。导致repaint和reflow的因素很多,其中大多数是脚本操作样式或者dom元素造成的。比如我们对一个元素的位置信息读取或者重新赋值,都会导致repaint和reflow。你可以在css triger中查看哪些属性变化会导致界面的重排和重回。

6.合成层
现在我们已经到了网页显示的最后一步:合成阶段。合成就是将界面的不同部分到不同的层级中去。我们看到的界面,其实并非仅仅由一层组成,而是由不同的层层叠而成的。如果你用过photoshop这种图片处理工具,那么就完全能理解合成的原理。界面的元素除了会被布局到不同的水平位置上,还会按照一定的规则(css属性,以及render进程的计算原则进程分层处理)在垂直方向上进行摆放。
首先,主进程会在生成布局树之后(Layout tree)后会同时生成一棵分层树(Layer tree)。这时渲染进程中的光删线程根据不同的层级把不同界面分成一个个小的模块(quads)。然后通过合成线程(Compositor thread)把所有的模块合成一张图(frame)。此时通过ipc把这张图发给GPU进程,让它最终绘制到屏幕上去,这样就完成了一个界面帧的显示。60fps的速率才会使人类觉得运动是流程流畅,大多数的屏幕刷新频率也是60fps,合成线程就是按照这个速率,合成每一桢画面交给GPU显示,才实现我们的网页任何变化进行实时显示。下面是关于quads和frame的定义:

Draw quads Contains information such as the tile's location in memory and where in the page to draw the tile taking in consideration of the page compositing.
Compositor frame A collection of draw quads that represents a frame of a page.

你可看到,分层的过程中主要由渲染进程(render process)中的光删线程(raster thread)以及合成线程(cpmpositor thread)完成的,主线程(main thead)不参与到其中,这意味着主线程和合成线程分开工作,即使主线程被长时间的任务霸占着,我们也可以继续执行绘制图像的任务。这就是我们经常听到的css利用cpu加速——不受主线程的阻塞而保持动画的流畅。其次,分层技术能够使我们移动不同层级的元素时,无需重新计算其他层级的元素位置变化,这有效的减少了我们之前提到过的重绘和重排。你可以在css triger中你可以查看到这些属性,合理得运用,能够帮助你得动画变得流畅。关于光删化的更详细的工作细节你可以参考这篇文档

小结

所有的子资源被加载之后,渲染进程会通知浏览器进程进行的UI更新,例如标签页的loading小图标变成网页的icon,触发load事件等。整个界面的渲染流程可以从各个指标(FP,FCP,FMP,CLS)来评估加载的状态。对于这些指标的含义以及详情,web vitals 中提供了详尽的文档说明。从第一个像素被绘制到屏幕上,到呈现整个网页,这中间浏览器其实是做了大量的工作的,了解浏览器的渲染原理,有助于我们后续为网页做加载性能的优化。

浏览器之后

持续交互

一个完整的界面,除了在视觉上做到呈现,还需要做到可持续交互。而我们需要脚本需要对界面进行注册,才能够与界面交互。评估一个界面是否可以交互有几种指标,TTI(time to interactive)就是其中重要的指标之一。TTI是指用户可交互的事件,浏览器并没有指定的API去评估这个指标,需要我们自己的计算。在这篇博文中我阐述了较为详细的计算方法。

事件绑定

关于浏览器注册事件的过程,我们在这里也简略讲解一下。我们之前提到过,主线程和合成线程分别处理自己任务,主线程运行脚本,合成线程负责合成帧,合成线程会将有注册事件的区域标记为non-fast scrollable region。若在这个区域里面发生事件,合成线程会把事件对应的元素,位置,大小,类型等信息交给主线程脚本,并且等待脚本执行完成。而合成线程如果等待的时间过长,就会导致了绘制图像的速率不足60fps,那么界面上的动画,或者你的滚动动作,会出现卡顿(jank)或者响应(delay)延迟。反之事件发生不在这块区域内,则不会有任何印象。我们经常在开发中使用“委托”的方式来监听事件,这种方式的好处是不用在代码层面频繁地绑定元素而造成性能的损耗,但实际上该以大代小的方法,意味着我们扩大了这块non-fast scrollable region,从而有更加严重的阻碍合成线程的任务。不过,有个小技巧,你可以通过给addEventListener添加第三个参数,来告诉渲染进程合成任务线程不需要等到脚本执行完毕,也就是说依旧向以前一样并行处理即可。

document.body.addEventListener('touchstart', event => {
    if (event.target === area) {
        event.preventDefault()
    }
 }, {passive: true});

XHR异步请求

很多界面,比如三大框架生成的html骨架代码。需要通过js和异步数据获取后套用数据再进行展示。因此这一步也是在url的过程中的。异步生成的界面大小体积依照不同的业务需要而不同,有的很多,有的则很少。为了评估多大的程度造成了用户的摆平感觉,我们需要用其他的指标衡量。

总结

到此位置,我们讨论了从打开浏览器输入网址信息到界面最终渲染到用户的面前经历过的过程。这个过程设计到的各个历程如果展来讲几乎可以写成一本书籍。但是作为前端工程师来说,对上述历程有一个清晰的结果,会让你对你编写代码有更清楚的了解。并且,这也可以帮助你定位网页发生的性能和加载问题,从而快速优化自己的网页应用。本篇博文对网页优化没有进一步阐述,后续我们会专开一篇博文对此进行讲述。现在,我们总结一下我们提到过的一些知识:

  • 网页打开大致经历了系统,网络,浏览器,服务器等几个阶段。
  • 每个阶段设计到的知识,并非全部前端知识,需要针对各自的问题进行逐步的分析和解决。
  • 我们分析网页的打开的性能其实也就是为了解决网页加载速度慢的问题。
  • 最后我们展望未来,希望能够针对以上这些点针对性的进行解决和优化。

参考文档

谷歌的开发这文档是这篇博文内容的主要来源,上面对基础的web应用知识做了非常丰富的讲解。推荐大家经常去看看上面的文章,能购帮助你解决大部分基础设计问题,同时了解最新的web技术。MDN社区也补充了这篇博文的一些不足,我也建议你经常去上面看看。另外查阅w3c文档能帮助你了解第一手的资料,我们看到的大多数技术文章都是对它的复述和通俗化解释,虽然它们的技术文档写得又臭又长。

标签:浏览器,渲染,流程,dom,进程,网页,界面,css
来源: https://www.cnblogs.com/constantince/p/15475276.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有