答寒冬九问之讲讲输入完网址按下回车,到看到网页这个过程中发生了什么。

  无意中看到寒冬关于前端的九个问题,细细想来我也只是对第一、二、九问有所了解,正好也趁着这个机会梳理一下自己的知识体系。由于本人对http协议以及dns对url的解析问题并不了解,所以这里之探讨url请求加载到浏览器端时,浏览器对html的解析到呈现过程。该过程主要分为以下步骤:

  1. 解析HTML
  2. 构建DOM树
  3. DOM树与CSS样式进行附着构造呈现树
  4. 布局
  5. 绘制

解析与构建DOM树

  前两步我们放在一起讨论,浏览器的实际工作也是将他们放在一起进行的。对于HTML浏览器有专门的html解析器来解析HTML,并在解析的过程中构建DOM树。在这里我们讨论两种DOM元素的解析,即样式(link、style)与脚本文件(script)。由于浏览器采用自上而下的方式解析,在遇到这两种元素时都会阻塞浏览器的解析,直到外部资源加载并解析或执行完毕后才会继续向下解析html。对于样式与脚本的先后顺序同样也会影响到浏览器的解析过程,究其原因主要在于:script脚本执行过程中可能会修改html界面(如document.write函数);DOM节点的CSS样式会影响js的执行结果。在我的测试中得到以下四条结论:

  1)外部样式会阻塞后续脚本执行,直到外部样式加载并解析完毕。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
  <script>var start = +new Date;</script>
  <link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">

</head>

<body>
  <span id="result"></span>
  <script>
    var end = +new Date;
    document.getElementById(‘result‘).innerHTML = (end-start);
  </script>
</body>
</html>

  2)外部样式不会阻塞后续外部脚本的加载,但会阻塞外部脚本的执行。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
  <script>var start = +new Date;</script>
  <link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">

</head>

<body>
  test
  <script src="http://udacity-crp.herokuapp.com/time.js?rtt=1&a"></script>
  <div id="result"></div>
  <script>var end = +new Date;document.getElementById("result").innerHTML = end-start;</script>

</body>
</html>

主页代码

var loadTime = document.createElement(‘div‘);
loadTime.innerText = document.currentScript.src + ‘ executed @ ‘ + window.performance.now();
loadTime.style.color = ‘blue‘;
document.body.appendChild(loadTime);

外部脚本

  从瀑布图中我们可以看到,外部脚本与外部样式是并行加载,但直到外部样式加载完毕,外部脚本才开始执行

  3)如果后续外部脚本含有async属性(IE下为defer),则外部样式不会阻塞该脚本的加载与执行

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
  <script>var start = +new Date;</script>
  <link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">

</head>

<body>
  test
  <script src="http://udacity-crp.herokuapp.com/time.js?rtt=1&a" async></script>
  <div id="result"></div>
  <script>var end = +new Date;document.getElementById("result").innerHTML = end-start;</script>

</body>
</html>

  从瀑布图中可以看到外部脚本的加载与执行并不受link的阻塞

  4)对于动态创建的link标签不会阻塞其后动态创建的script的加载与执行,不管script标签是否具有async属性,但对于其他非动态创建的script,以上三条结论仍适用

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
  <script>var start = +new Date;</script>

</head>

<body>
  test
  <script>
    var link = document.createElement(‘link‘);
    link.href = "http://udacity-crp.herokuapp.com/style.css?rtt=2";
    link.rel = "stylesheet";
    document.head.appendChild(link);
    var script = document.createElement(‘script‘);
    script.src = "http://udacity-crp.herokuapp.com/time.js?rtt=1&a";
    document.head.appendChild(script);
  </script>
  <div id="result"></div>
  <script>var end = +new Date;document.getElementById("result").innerHTML = end-start;</script>

</body>
</html>

  这是最终页面结构

  通过瀑布图与页面结果可以看到动态创建的外部脚本并未受link的阻塞。

  link或style标签都会被解析成DOM节点。浏览器对于样式表还会生成CSSStyleSheet对象(C++代码),他集成子CSSStyle,指标是样式表对象而不管该对象来自于Style还是link。该对象主要包含以下几个重要属性和方法

  • CSSRules 即css样式代码
  • type 表示样式表类型的字符串。对CSS样式表而言,这个字符串是“type/css”。
  • href 通过link生成的为样式链接,否则为undefined
  • insertRule(rule,index):向cssRules集合中指定的位置插入rule字符串。IE不支持这个方法,但支持一个类似的addRule()方法。
  • deleteRule(index):删除cssRules集合中指定的位置的规则。IE不支持这个方法,但支持一个类似的removeRule()方法。

  文档中对于所有的样式表集合可以通过document.styleSheets来访问。同时对于style或link DOM元素可以通过element.sheet来访问CSSStyleSheet对象,IE中则通过element.styleSheet来访问。

  html解析完毕,DOM树创建完成后DOMContentLoaded事件即触发,这时候可以用过script来操作DOM节点。

构建呈现树  

  HTML解析完毕后,开始构建呈现树RenderTree,这一步的主要工作在于将css样式应用到DOM节点上,WebKit内核将这一过程称为附着,其他浏览器有不同的概念。对前端工程师而言这个过程会涉及到CSS层叠问题。

  首先将根据样式重要性排序,由低到高依次为:

    1. 浏览器声明
    2. 用户普通声明
    3. 作者普通声明
    4. 作者重要声明
    5. 用户重要声明

  对于同一重要级别,则是根据CSS选择符的特指度来判定优先级;一条样式声明的特指度由以下四个部分决定:S-I-C-E

    1. 声明来自内联的style属性则 S+1;
    2. 声明中含有id属性则 I+1;
    3. 声明中含有类、伪类、属性选择器则 C+1;
    4. 生命中含有元素、伪元素选择器则 E+1;

  特指度的比较类似于两个字符串之间比较大小。

  呈现树的每一个节点即为与其相对应的DOM节点的CSS框,框的类型与DOM节点的display属性有关,block元素生成block框,inline元素生成inline框。每一个呈现树节点都有与之相对应的DOM节点,但DOM节点不一定有与之相对应的呈现树节点,比如display属性为none的DOM节点,而且呈现树节点在呈现树中的位置与他们在DOM树中的位置不一定相同,比如float与绝对定位元素。

  下图为呈现树与其相对应的DOM树节点

布局

  呈现树构造完成后浏览器便进行布局处理,及计算每个呈现树节点的大小和位置信息。有道友可能要问,前面已将杨师傅捉到DOM节点上,不是已经有了样式信息为何还要计算大小。这里可以这样理解,以上包含大小的样式信息只是存在内存里,并没有实际使用,浏览器要根据窗口的实际大小来处理呈现树节点的实际显示大小和位置,比如对于margin为auto的处理。

  布局是一个递归过程,从跟呈现节点开始,递归遍历子节点,计算集合几何信息。具体过程还是比较复杂偶也不甚了解,道友们还是查阅其他资料吧。

绘制

  布局完成后,便是将呈现树绘制出来显示在屏幕上。对于每一个呈现树节点来说,主要绘制顺序如下:

  1. 背景颜色
  2. 背景图片
  3. 边框
  4. 子呈现树节点
  5. 轮廓

参考资料:

文章有错误之处欢迎各位道友不吝指正

时间: 2024-08-01 10:45:43

答寒冬九问之讲讲输入完网址按下回车,到看到网页这个过程中发生了什么。的相关文章

从输入网址到显示网页的过程中发生了什么?

从用户输入一个网址到网页最终展现到用户面前,中间究竟发生了什么?这是一个简单而复杂的问题.大致流程总结如下:1.输入地址2.浏览器查找域名的 IP 地址(这一步包括 DNS 具体的查找过程,包括:浏览器缓存->系统缓存->路由器缓存...)3.浏览器向 web 服务器发送一个 HTTP 请求4.服务器的永久重定向响应(从 http://example.com 到 http://www.example.com)5.浏览器跟踪重定向地址6.服务器处理请求7.服务器返回一个 HTTP 响应8.浏览器

从输入网址到显示网页的过程中发生了什么?(转自88旧港)

转自88旧港 http://www.cnblogs.com/xingyue1988/ 从用户输入一个网址到网页最终展现到用户面前,中间究竟发生了什么?这是一个简单而复杂的问题.大致流程总结如下:1.输入地址2.浏览器查找域名的 IP 地址(这一步包括 DNS 具体的查找过程,包括:浏览器缓存->系统缓存->路由器缓存...)3.浏览器向 web 服务器发送一个 HTTP 请求4.服务器的永久重定向响应(从 http://example.com 到 http://www.example.com)

一个页面从输入URL到页面加载显示完成,这个过程中发生了什么?

1.浏览器通过DNS查找域名对应的IP地址(DNS查询:浏览器缓存-->系统缓存-->路由器缓存-->ISP DNS 缓存 -->根域名服务器) 2.浏览器向Web服务器发送一个HTTP请求(TCP三次握手) 3.服务器301重定向(从http://example.com重定向到http://www.example.com) 4.浏览器跟踪重定向地址,请求另一个带www的网址 5.服务器处理请求(通过路由读取资源) 6.服务器返回一个HTTP响应(报头中把Content-type设

用WPF写一个登录界面,我想在输入完密码后按回车就能够验证登陆,而不需要用鼠标单击登陆按钮

原文:用WPF写一个登录界面,我想在输入完密码后按回车就能够验证登陆,而不需要用鼠标单击登陆按钮 在wpf中,将按钮的IsDefault设置为true ???? 原文地址:https://www.cnblogs.com/lonelyxmas/p/9345580.html

从输入 URL 到浏览器接收的过程中发生了什么事情

从输入 URL 到浏览器接收的过程中发生了什么事情? 原文:http://www.codeceo.com/article/url-cpu-broswer.html 从触屏到 CPU  首先是「输入 URL」,大部分人的第一反应会是键盘,不过为了与时俱进,这里将介绍触摸屏设备的交互. 触摸屏一种传感器,目前大多是基于电容(Capacitive)来实现的,以前都是直接覆盖在显示屏上的,不过最近出现了 3 种嵌入到显示屏中的技术,第一种是 iPhone 5 的 In-cell,它能减小了 0.5 毫米

一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么?

一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了: 1.浏览器补全URL地址 在输入完URL之后,浏览器会自动检查该地址是否完整,例如是否有添加https协议,若发现不完整,会自动补全. 2.向DNS查询IP地址 每个域名都对应一个或多个提供相同服务服务器的 IP 地址,只有知道服务器 IP 地址才能建立连接,所以需要通过 DNS 把域名解析成一个 IP 地址. 3.得到IP地址后,建立连接,进行三次握手 即每次建立连接前,客户端和服务端都要先进行三次对话才开始正式传输内容,三次对

从输入 URL 到浏览器接收的过程中发生了什么事情?

从输入 URL 到浏览器接收的过程中发生了什么事情? What really happens when you navigate to a URL 上面两篇文章都解读的很好,值得阅读. 接下来在总结一下这个过程: 1.首先,会查询缓存,如果缓存存在的话则直接响应,否则继续下面过程: 2.当发送一个URL请求时,不管这个URL是Web页面的URL还是Web页面上每个资源的URL,浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器上启动一个DNS查询.这能使浏览器获得请求对应的IP地址.D

爱创课堂每日一题第五十七天-一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么?

分为4个步骤: (1),当发送一个URL请求时,不管这个URL是Web页面的URL还是Web页面上每个资源的URL,浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器上启动一个DNS查询.这能使浏览器获得请求对应的IP地址. (2), 浏览器与远程`Web`服务器通过`TCP`三次握手协商来建立一个`TCP/IP`连接.该握手包括一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在 浏览器和服务器之间传递.该握手首先由客户端尝试建立起通信,而后服务器应答并接受客户端的请求,最后

输入url地址按下回车发生了什么?

1.输入url地址后,首先进行DNS解析,将相应的域名解析为IP地址: 2.客户端根据IP地址去寻找相应的服务器: 3.与服务器进行TCP的三次握手: 所谓三次握手就是客户端在请求与服务器相连接时,彼此共计发送了三次数据包,就好比以下的对话: 首先,需要明确的是,三次握手是客户端先发起请求. (第一次)客户端:hi,服务器,在吗?我想和你建立连接,你能收到我的消息吗?(此时客户端给服务端发送了一个数据包和发送序号,即SYN=1,Seq=X) (第二次)服务器:hi,客户端,我在呢,我收到你的消息