【前端】浏览器的渲染流程(完整)

这篇具有很好参考价值的文章主要介绍了【前端】浏览器的渲染流程(完整)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文主要包含以下内容:

  • 浏览器渲染整体流程

  • 解析 HTML

  • 样式计算

  • 布局

  • 分层

  • 生成绘制指令

  • 分块

  • 光栅化

  • 绘制

  • 常见面试题

浏览器渲染整体流程

浏览器,作为用户浏览网页最基本的一个入口,我们似乎认为在地址栏输入 URL 后网页自动就出来了。殊不知在用户输入网页地址,敲下回车的那一刻,浏览器背后做了诸多的事情。
去除 DNS 查找等这些细枝末节的工作,整个大的部分可以分为两个,那就是 网络渲染
总体流程粗略概览
1、浏览器查找域名对应的 IP 地址(DNS 查询:浏览器缓存->系统缓存->路由器缓存->ISP DNS 缓存->根域名服务器) 2、浏览器向 Web 服务器发送一个 HTTP 请求(TCP 三次握手) 3、服务器 301 重定向(从 HTTP://example.com 重定向到 HTTP://www.example.com)
4、浏览器跟踪重定向地址,请求另一个带 www 的网址 5、服务器处理请求(通过路由读取资源) 6、服务器返回一个 HTTP 响应(报头中把 Content-type 设置为 'text/html')
7、浏览器进 DOM 树构建 8、浏览器发送请求获取嵌在 HTML 中的资源(如图片、音频、视频、CSS、JS 等)9、浏览器显示完成页面 10、浏览器发送异步请求
浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

首先,浏览器的网络线程会发送 http 请求,和服务器之间进行通信,之后将拿到的 html 封装成一个渲染任务,并将其传递给渲染主线程的消息队列。在事件循环机制的作用下,渲染主线程取出消息队列中的渲染任务,开启渲染流程。

网络线程和服务器之间通信的过程主要是三次握手建立tcp链接,服务器收到请求后返回响应报文,但是本文主要讲述浏览器的渲染进程如何将一个密密麻麻的 html 字符串渲染成最终页面的。

我们先来看一下整体流程,整个渲染流程分为多个阶段,分别是: HTML 解析、样式计算、布局、分层、生成绘制指令、分块、光栅化、绘制:

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

每个阶段都有明确的输入输出,上一个阶段的输出会成为下一个阶段的输入。

这样,整个渲染流程就形成了一套组织严密的生产流水线。

接下来,咱们就一起来看一下每一个阶段的各个流程究竟是在干什么。

解析 HTML

首先第一步就是解析 html,生成 DOM 树。

当我们打开一个网页时,浏览器都会去请求对应的 HTML 文件。虽然平时我们写代码时都会分为 HTML、CSS、JS 文件,也就是字符串,但是计算机硬件是不理解这些字符串的,所以在网络中传输的内容其实都是 01 这些字节数据。

当浏览器接收到这些字节数据以后,它会将这些字节数据转换为字符串,也就是我们写的代码。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

当数据转换为字符串以后,浏览器会先将这些字符串通过词法分析转换为标记( token ),这一过程在词法分析中叫做标记化tokenization )。

为什么需要标记化呢?原因很简单,现在浏览器虽然将字节数据转为了字符串,但是此时的字符串就如何一篇标题段落全部写在一行的文章一样,浏览器此时仍然是不能理解的。

例如:

<!DOCTYPE html><htmllang="en"><head><title>Document</title></head><body><p>this is a test</p></body></html>

因此现在所做的标记化,本质就是要将这长长的字符串分拆成一块块,并给这些内容打上标记,便于理解这些最小单位的代码是什么意思。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

将整个字符串进行了标记化之后,就能够在此基础上构建出对应的 DOM 树出来。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

上面的步骤,我们就称之为解析 HTML。整个流程如下图:

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

在解析 HTML 的过程中,我们可以能会遇到诸如 style、link 这些标签,聪明的你应该已经想到了,这是和我们网页样式相关的内容。此时就会涉及到 CSS 的解析。

为了提高解析效率,浏览器在开始解析前,会启动一个预解析的线程,率先下载 HTML 中的外部 CSS 文件和外部的 JS 文件。

如果主线程解析到 link 位置,此时外部的 CSS 文件还没有下载解析好,主线程不会等待,继续解析后续的 HTML。这是因为下载和解析 CSS 的工作是在预解析线程中进行的。这就是 CSS 不会阻塞 HTML 解析的根本原因。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

最终,CSS 的解析在经历了从字节数据、字符串、标记化后,最终也会形成一颗 CSSOM 树。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

上面也有提到,预解析线程除了下载外部 CSS 文件以外,还会下载外部 JS 文件,那么这里同学们自然也会好奇针对 JS 代码浏览器是如何处理的?

如果主线程解析到 script 位置,会停止解析 HTML,转而等待 JS 文件下载好,并将全局代码解析执行完成后,才能继续解析 HTML

为什么呢?

这是因为 JS 代码的执行过程可能会修改当前的 DOM 树,所以 DOM 树的生成必须暂停。这就是 JS 会阻塞 HTML 解析的根本原因。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

因此,如果你想首屏渲染的越快,就越不应该在最前面就加载 JS 文件,这也是都建议将 script 标签放在 body 标签底部的原因。

<html>
  <head>
    ...
  </head>
  <body>
    <p></p>
    <scriptsrc="..."></script>
  </body>
</html>

另外,在现代浏览器中,为我们提供了新的方式来避免 JS 代码阻塞渲染的情况:

  • async

  • defer

  • prefetch

  • preload

关于这几种方式的区别,我们在另外一篇文章中再具体来看。

最后总结一下此阶段的成果,第一步完成后,会得到 DOM 树和 CSSOM 树,浏览器的默认样式、内部样式、外部样式、行内样式均会包含在 CSSOM 树中。

得到了两棵树,如下图所示:

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

样式计算

接下来进入第二步:样式计算

拥有了 DOM 树我们还不足以知道页面的外貌,因为我们通常会为页面的元素设置一些样式。主线程会遍历得到的 DOM 树,依次为树中的每个节点计算出它最终的样式,称之为 Computed Style

在这一过程中,很多预设值会变成绝对值,比如 red 会变成 rgb(255,0,0);相对单位会变成绝对单位,比如 em 会变成 px

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

浏览器会确定每一个节点的样式到底是什么,并最终生成一颗样式规则树,这棵树上面记录了每一个 DOM 节点的样式。

另外需要注意的是,这里所指的浏览器确定每一个节点的样式,是指在样式计算时会对所有的 DOM 节点计算出所有的样式属性值。如果开发者在书写样式时,没有写某一项样式,那么大概率会使用其默认值。例如:

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

关于样式计算的详细过程,请参阅文章《CSS 属性计算过程》。

这一步完成后,我们就得到一棵带有样式的 DOM 树。也就是说,经过样式计算后,之前的 DOM 数和 CSSOM 数合并成了一颗带有样式的 DOM 树。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

布局

前面这些步骤完成之后,渲染进程就已经知道页面的具体文档结构以及每个节点拥有的样式信息了,可是这些信息还是不能最终确定页面的样子。

举个例子,假如你现在想通过电话告诉你的朋友你身边的一幅画的内容:“画布上有一个红色的大圆圈和一个蓝色的正方形”,单凭这些信息你的朋友是很难知道这幅画具体是什么样子的,因为他不知道大圆圈和正方形具体在页面的什么位置,是正方形在圆圈前面呢还是圆圈在正方形的前面。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

渲染网页也是同样的道理,只知道网站的文档流以及每个节点的样式是远远不足以渲染出页面内容的,还需要通过布局(layout)来计算出每个节点的几何信息(geometry)。

生成布局树的具体过程是:主线程会遍历刚刚构建的 DOM 树,根据 DOM 节点的计算样式计算出一个布局树(layout tree)。布局树上每个节点会有它在页面上的 x,y 坐标以及盒子大小(bounding box sizes)的具体信息。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

布局树大部分时候,和 DOM 树并非一一对应。虽然它长得和先前构建的 DOM 树差不多,但是不同的是这颗树只有那些可见的(visible)节点信息。

比如 display:none 的节点没有几何信息,因此不会生成到布局树;

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

又比如使用了伪元素选择器,虽然 DOM 树中不存在这些伪元素节点,但它们拥有几何信息,所以会生成到布局树中。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

还有匿名行盒、匿名块盒等等都会导致 DOM 树和布局树无法一一对应。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

分层

在确认了布局树后,接下来就是绘制了么?

还不急,这里还会有一个步骤,就是分层

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

分层的好处在于,将来某一个层改变后,仅会对该层进行后续处理,从而提升效率。

为了确定哪些元素需要放置在哪一层,主线程需要遍历整颗布局树来创建一棵层次树(Layer Tree

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

滚动条、堆叠上下文、transformopacity 等样式都会或多或少的影响分层结果,也可以通过使用 will-change 属性来告诉浏览器对其分层。

生成绘制指令

分层工作结束后,接下来就是生成绘制指令。

主线程会为每个层单独产生绘制指令集,用于描述这一层的内容该如何画出来。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

这里的绘制指令,类似于“将画笔移动到 xx 位置,放下画笔,绘制一条 xx 像素长度的线”,我们在浏览器所看到的各种复杂的页面,实际上都是这样一条指令一条指令的执行所绘制出来的。

如果你熟悉 Canvas,那么这样的指令类似于:

context.beginPath(); // 开始路径

context.moveTo(10, 10); // 移动画笔

context.lineTo(100, 100); // 绘画出一条直线

context.closePath(); // 闭合路径

context.stroke(); // 进行勾勒

但是你要注意,这一步只是生成诸如上面代码的这种绘制指令集,还没有开始执行这些指令。

另外,还有一个重要的点你需要知道,生成绘制指令集后,渲染主线程的工程就暂时告一段落,接下来主线程将每个图层的绘制信息提交给合成线程,剩余工作将由合成线程完成。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

分块

合成线程首先对每个图层进行分块,将其划分为更多的小区域。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

此时,它不再是像主线程那样一个人在战斗,它会从线程池中拿取多个线程来完成分块工作。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

光栅化

分块完成后,进入光栅化阶段。所谓光栅化,就是将每个块变成位图。

更简单的理解就是确认每一个像素点的 rgb 信息,如下图所示:

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

光栅化的操作,并不由合成线程来做,而是会由合成线程将块信息交给 GPU 进程,以极高的速度完成光栅化。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

GPU 进程会开启多个线程来完成光栅化,并且优先处理靠近视口区域的块。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

绘制

最后一步,我们总算迎来了真正的绘制。

当所有的图块都被栅格化后,合成线程会拿到每个层、每个块的位图,从而生成一个个「指引(quad)」信息。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

指引会标识出每个位图应该画到屏幕的哪个位置,以及会考虑到旋转、缩放等变形。

变形发生在合成线程,与渲染主线程无关,这就是 transform 效率高的本质原因。

合成线程会通过 IPC 向浏览器进程(browser process)提交(commit)一个渲染帧。这个时候可能有另外一个合成帧被浏览器进程的 UI线程(UI thread)提交以改变浏览器的 UI。这些合成帧都会被发送给 GPU 完成最终的屏幕成像。

如果合成线程收到页面滚动的事件,合成线程会构建另外一个合成帧发送给 GPU 来更新页面。

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

最后总结一下浏览器从拿到 html 文档到最终渲染出页面的整体流程,如下图:

浏览器渲染页面的过程,工作经验总结,javascript,html,前端,Powered by 金山文档

常见面试题

  1. 什么是 reflow

reflow 的本质就是重新计算 layout 树。
当进行了会影响布局树的操作后,需要重新计算布局树,会引发 layout。
为了避免连续的多次操作导致布局树反复计算,浏览器会合并这些操作,当 JS 代码全部完成后再进行统一计算。所以,改动属性造成的 reflow 是异步完成的。
也同样因为如此,当 JS 获取布局属性时,就可能造成无法获取到最新的布局信息。
浏览器在反复权衡下,最终决定获取属性立即 reflow。
  1. 什么是 repaint

repaint 的本质就是重新根据分层信息计算了绘制指令。
当改动了可见样式后,就需要重新计算,会引发 repaint。
由于元素的布局信息也属于可见样式,所以 reflow 一定会引起 repaint。
  1. 为什么 transform 的效率高?文章来源地址https://www.toymoban.com/news/detail-758618.html

因为 transform 既不会影响布局也不会影响绘制指令,它影响的只是渲染流程的最后一个「draw」阶段
由于 draw 阶段在合成线程中,所以 transform 的变化几乎不会影响渲染主线程。反之,渲染主线程无论如何忙碌,也不会影响 transform 的变化。

到了这里,关于【前端】浏览器的渲染流程(完整)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 前端性能优化之浏览器渲染优化

    在当今互联网高速发展的时代,用户对于网页加载速度和性能的要求越来越高。作为前端开发者,我们需要关注并致力于提升网页的加载和渲染性能,以提供更好的用户体验。而浏览器渲染优化正是我们实现这个目标的关键。在本文中,我们将探讨一些关于浏览器渲染优化的

    2024年02月11日
    浏览(12)
  • 面试:浏览器从输入url到渲染页面,发生了什么

    用户输入阶段 合成 URL :浏览区会判断用户输入是合法 URL,比如用户输入的是搜索的,默认的搜索引擎会合成新的,如果符合url规则会根据url协议,在这段内容加上协议合成合法的url      查找缓存 网络进程获取到 URL,先去本地缓存中查找是否有缓存资源,如果有则

    2024年02月06日
    浏览(11)
  • 前端秘法进阶篇----这还是我们熟悉的浏览器吗?(浏览器的渲染原理)

    前端秘法进阶篇----这还是我们熟悉的浏览器吗?(浏览器的渲染原理)

    目录 一.浏览器渲染原理 二.渲染时间点 三.渲染流水线 1.解析html(Parse HTML) 1.1解析成DOM树(document object model) 1.2解析成CSSOM树(css object model) 2.样式计算(Recalculate Style) 3.布局(Layout) 4.分层(Layer) 5. 绘制(Paint) 6.分块(Tiling) 7. 光栅化(Raster) 8. 画(Draw) 四.附加面试题 1.什么是 reflow? 2.什

    2024年02月21日
    浏览(10)
  • 【前端八股文】浏览器系列:性能优化——HTML、CSS、JS、渲染优化

    【前端八股文】浏览器系列:性能优化——HTML、CSS、JS、渲染优化

    本系列目录:【前端八股文】目录总结 是以《代码随想录》八股文为主的笔记。详情参考在文末。 代码随想录的博客_CSDN博客-leecode题解,ACM题目讲解,代码随想录领域博主 性能优化,从以下几个方面来进行。 避免HTML中直接写CSS viewport加速页面渲染 使用语义化标签 减少标签的

    2023年04月20日
    浏览(33)
  • 前端面试:【浏览器与渲染引擎】Web APIs - DOM、XHR、Fetch、Canvas

    嗨,亲爱的读者!当我们在浏览器中浏览网页时,我们常常会与各种Web API打交道。这些API允许我们与网页内容、服务器资源和图形进行交互。本文将深入探讨一些常见的Web API,包括DOM、XHR、Fetch和Canvas,以帮助你了解它们的用途和如何使用它们。 1. DOM(文档对象模型): 用

    2024年02月11日
    浏览(13)
  • 前端面试的话术集锦第 7 篇:高频考点(浏览器渲染原理 & 安全防范)

    这是记录 前端面试的话术集锦第七篇博文——高频考点(浏览器渲染原理 安全防范) ,我会不断更新该博文。❗❗❗ 注意:该章节都是⼀个⾯试题。 1.1.1 浏览器接收到HTML⽂件并转换为DOM树 当我们打开⼀个⽹⻚时,浏览器都会去请求对应的 HTML ⽂件。虽然平时我们写代码时

    2024年02月03日
    浏览(17)
  • 在浏览器中输入URL到显示页面经历哪些过程,涉及到哪些协议?

    作为一个大学学过计算机网络的人,在工作后。。。几乎把TCP/IP模型和OSI模型忘得干干净净的了,重新根据百度词条,对浏览器地址解析做了粗略的总结,也当是给自己加深一下印象。 首先浏览器要将URL解析为IP地址,解析域名就要用到DNS协议,首先主机会查询DNS的缓存,如

    2024年02月09日
    浏览(12)
  • 从输入URL到浏览器显示页面的过程中都发生了什么?

    用户在浏览器中输入一个 url 或直接点开一个 url 后,就可以看到网页内容了。虽然可以直接显示,但在这背后却经过了非常复杂的操作,主要有五大过程:         ip 指的是网络为每一台电脑分配的一个地址。由于 ip 地址不容易被记住,所以有了域名,浏览器拿到域名后

    2024年02月11日
    浏览(12)
  • 在浏览器的舞台上演:前端如何挑战页面刷新的极限

    在无尽的数字海洋中,用户和浏览器之间建立了一座看不见的桥梁,连接了网页的现实与虚拟。而在这座桥上,JavaScript像是一位魔法师,可以通过各种巧妙的技巧,让页面焕然一新,展示出绚丽的景象。 这个博客将带你走进前端的奇妙世界,揭示页面刷新的幕后秘密。从简

    2024年02月04日
    浏览(9)
  • Java教程:如何读取服务器文件并推送到前端并下载,图片格式以浏览器渲染模式

    Java教程:如何读取服务器文件并推送到前端并下载,图片格式以浏览器渲染模式

    ----在我们做文件上传时,通常会保存文件的相对路径在数据库中,然后返回前端http访问路径,来对文件进行下载或图片预览功能,但是有时候我们并不想直接返回文件访问地址给前端,这就用到了Java当中的文件输入输出流,将文件以流的方式响应给浏览器,并渲染出图片或

    2024年02月03日
    浏览(20)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包