Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【浏览器】从输入一个URL到网页展示的过程 #32

Open
Tracked by #6
swiftwind0405 opened this issue Mar 29, 2020 · 0 comments
Open
Tracked by #6

【浏览器】从输入一个URL到网页展示的过程 #32

swiftwind0405 opened this issue Mar 29, 2020 · 0 comments

Comments

@swiftwind0405
Copy link
Owner

swiftwind0405 commented Mar 29, 2020

image


浏览器请求与服务器响应

image

DNS 域名解析

在网络世界,你肯定记得住网站的名称,但是很难记住网站的 IP 地址,因而也需要一个地址簿,就是 DNS 服务器。DNS 服务器是高可用、高并发和分布式的,它是树状结构,如图:

image

  • 根 DNS 服务器 :返回顶级域 DNS 服务器的 IP 地址
  • 顶级域 DNS 服务器:返回权威 DNS 服务器的 IP 地址
  • 权威 DNS 服务器 :返回相应主机的 IP 地址

DNS的域名查找,在客户端和浏览器,本地DNS之间的查询方式是递归查询;在本地DNS服务器与根域及其子域之间的查询方式是迭代查询;

递归过程:

image

在客户端输入 URL 后,会有一个递归查找的过程,从浏览器缓存中查找->本地的hosts文件查找->找本地DNS解析器缓存查找->本地DNS服务器查找,这个过程中任何一步找到了都会结束查找流程。

结合起来的过程,可以用一个图表示:
image

建立TCP连接

首先,判断是不是https的,如果是,则HTTPS其实是HTTP + SSL / TLS 两部分组成,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。

浏览器渲染过程

image

浏览器渲染过程:

  1. 解析HTML,生成DOM树,解析CSS,生成CSSOM树
  2. 将DOM树和CSSOM树结合,生成渲染树(Render Tree)
  3. Layout(回流):根据生成的渲染树,进行回流(Layout),得到节点的几何信息(位置,大小)
  4. Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素
  5. Display:将像素发送给GPU,展示在页面上。(这一步其实还有很多内容,比如会在GPU将多个合成层合并为同一个层,并展示在页面中,而css3硬件加速的原理则是新建合成层)

生成渲染树

image

为了构建渲染树,浏览器主要完成了以下工作:

  1. 从DOM树的根节点开始遍历每个可见节点。
  2. 对于每个可见的节点,找到CSSOM树中对应的规则,并应用它们。
  3. 根据每个可见节点以及其对应的样式,组合生成渲染树。

第一步中,既然说到了要遍历可见的节点,那么我们得先知道,什么节点是不可见的。不可见的节点包括:

  • 一些不会渲染输出的节点,比如 scriptmetalink等。
  • 一些通过css进行隐藏的节点。比如display: none。注意,利用 visibility opacity 隐藏的节点,还是会显示在渲染树上的。只有 display: none 的节点才不会显示在渲染树上。

注意:渲染树只包含可见的节点

浏览器加载JavaScript脚本

正常加载流程

浏览器加载JavaScript脚本,主要通过<script>元素完成。其正常流程如下

  1. 浏览器的呈现引擎持有渲染的控制权,它正常解析HTML页面
  2. 解析遇到<script>标签,呈现引擎移交控制权给Javascript引擎(例如chrome的V8)
  3. 如果<script>标签引用了外部脚本那就先下载再执行,否则直接执行代码
  4. JavaScript引擎执行完毕移交控制权给呈现引擎,呈现引擎继续解析

加载外部脚本时,浏览器会暂停页面渲染,等待脚本下载并执行完成后,再继续渲染。原因是 JavaScript 代码可以修改 DOM,所以必须把控制权让给它,否则会导致复杂的线程竞赛的问题。

defer属性

浏览器解析到包含defer属性的<script>元素时,其运行流程如下

  1. 浏览器的呈现引擎持有渲染的控制权,它正常解析HTML页面
  2. 解析遇到包含defer属性的<script>标签,继续解析HTML,同时并行下载外链脚本
  3. 解析完成,文档处于交互状态时开始解析处于deferred模式的脚本
  4. 脚本解析完毕后,将文档状态设置为完成,DOMContentLoaded事件随之触发

使用defer属性时需要注意的点:

  • defer属性下载的脚本文件在DOMContentLoaded事件触发前执行(即刚刚读取完</html>标签)
  • defer属性可以保证执行顺序就是它们在页面上出现的顺序
  • 对于内置而不是加载外部脚本的script标签,以及动态生成的script标签,defer属性不起作用
  • 使用defer加载的外部脚本不应该使用document.write方法

async属性

浏览器解析到包含async属性的<script>元素时,其运行流程如下

  1. 浏览器的呈现引擎持有渲染的控制权,它正常解析HTML页面
  2. 解析遇到包含async属性的<script>标签,继续解析HTML,让另一进程同时并行下载外链脚本
  3. 脚本下载完成,浏览器暂停解析HTML,开始执行下载的脚本
  4. 脚本执行完毕,浏览器恢复解析HTML

使用async属性时需要注意的点:

  • async属性可以保证脚本下载的同时,浏览器继续渲染
  • async属性无法保证脚本的执行顺序,哪个先下载结束就先执行哪一个
  • 包含async属性的脚本不应该使用document.write方法
  • 如果同时使用async和defer属性,后者不起作用,浏览器行为由async属性决定

async、defer与不加的区别

一图胜千言: 原图地址

image

脚本的动态加载

<script>元素还可以动态生成,生成后再插入页面,从而实现脚本的动态加载。动态生成的script标签不会阻塞页面渲染,也就不会造成浏览器假死。但是问题在于,这种方法无法保证脚本的执行顺序,哪个脚本文件先下载完成,就先执行哪个。如果想避免这个问题,可以设置async属性为false。还可以监听脚本的onload事件来为脚本指定回调。

CSS阻塞JS加载

因为JS脚本可能会引用DOM的样式做计算,所以为了保证脚本计算的正确性,Firefox浏览器会等到脚本前面的所有样式表,都下载并解析完,再执行脚本;Webkit则是一旦发现脚本引用了样式,就会暂停执行脚本,等到样式表下载并解析完,再恢复执行。

此外,对于来自同一个域名的资源,比如脚本文件、样式表文件、图片文件等,浏览器一般有限制,同时最多下载6~20个资源,即最多同时打开的 TCP 连接有限制,这是为了防止对服务器造成太大压力。如果是来自不同域名的资源,就没有这个限制。所以,通常把静态文件放在不同的域名之下,以加快下载速度。

DOMContentLoaded 与 load 的区别

  • 当 DOMContentLoaded 事件触发时,仅当 DOM 解析完成后,不包括样式表、图片。我们前面提到 CSS 加载会阻塞 Dom 的渲染和后面 js 的执行,js 会阻塞 Dom 解析,所以我们可以得到结论:当文档中没有脚本时,浏览器解析完文档便能触发 DOMContentLoaded 事件。如果文档中包含脚本,则脚本会阻塞文档的解析,而脚本需要等 CSSOM 构建完成才能执行。在任何情况下,DOMContentLoaded 的触发不需要等待图片等其他资源加载完成。
  • 当 onload 事件触发时,页面上所有的 DOM、样式表、脚本、图片等资源已经加载完毕。
  • DOMContentLoaded -> load。

参考资料

@swiftwind0405 swiftwind0405 changed the title 【Day32】从输入一个URL到网页展示的过程 【浏览器】从输入一个URL到网页展示的过程 Apr 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant