从输入URL到页面展现完成浏览器作了些什么

为何输入URL就能够显示想要的页面?
输入URL后浏览器作了些什么?
前端能够针对这些作哪些优化?javascript

浏览器的主要功能是将用户选择的web资源呈现出来,它须要从服务器请求资源,并将其显示在浏览器窗口中,资源的格式一般是HTML,也包括PDF、image及其余格式。
那么从输入URL到浏览器显示完成,大体是分为2个阶段。首先解析url,完成后经过http获取页面资源,最后将得到的资源渲染展现出来。css

clipboard.png
HTML页面加载和解析流程
1.用户输入网址(假设是个html页面,而且是第一次访问),浏览器向服务器发出请求,服务器返回html文件;
2.浏览器开始载入html代码,发现<head>标签内有一个<link>标签引用外部CSS文件;
3.浏览器又发出CSS文件的请求,服务器返回这个CSS文件;
4.浏览器继续载入html中<body>部分的代码,而且CSS文件已经拿到手了,能够开始渲染页面了;
5.浏览器在代码中发现一个<img>标签引用了一张图片,向服务器发出请求。此时浏览器不会等到图片下载完,而是继续渲染后面的代码;
6.服务器返回图片文件,因为图片占用了必定面积,影响了后面段落的排布,所以浏览器须要回过头从新渲染这部分代码;
7.浏览器发现了一个包含一行Javascript代码的<script>标签,赶快运行它;
8.Javascript脚本执行了这条语句,它命令浏览器隐藏掉代码中的某个<div> (style.display=”none”)。忽然少了这么一个元素,浏览器不得不从新渲染这部分代码;
9.终于等到了</html>的到来,浏览器泪流满面……
10.等等,还没完,用户点了一下界面中的“换肤”按钮,Javascript让浏览器换了一下<link>标签的CSS路径;
11.浏览器召集了在座的各位<div><span><ul><li>们,“大伙儿收拾收拾行李,咱得从新来过……”,浏览器向服务器请求了新的CSS文件,从新渲染页面html

1. 解析url、获取页面资源前端

  • DNS解析获取ip地址
  • TCP请求(3次握手)
  • http请求得到返回数据html

2. 解析、渲染页面html5

  • html解析/dom树构建
  • 同获取html方式获取css/js/图片的资源
  • 解析构建css规则树
  • 构建渲染树
  • 布局layout
  • 渲染页面

DNS域名解析java

浏览器在发起http请求前,会先解析这个域名,找到ip地址。这个过程就是dns解析。解析过程以下:
1)浏览器先查询hosts文件是否有与这个域名对应的ip地址,若是有则直接向这个ip地址发起http请求。查询不到就进行下一步。web

2)浏览器向本地DNS服务器发出解析域名的DNS解析报文,本地DNS服务器收到请求后,先查询缓存,判断是否有对应的记录,若是有就返回这条记录,查询不到就进行下一步。数据库

3)本地DNS服务器没有在缓存中查询到对应的记录,本地DNS服务器因而就向DNS根服务器发起查询请求。DNS根服务器收到请求经过查询获得顶级域名对应的顶级域服务器的ip地址,而后向本地DNS服务器发送一条应答报文。浏览器

4)本地DNS服务器收到应答报文后,获得顶级域服务器的地址,而后向该地址发送请求解析域名的DNS请求报文。缓存

5)顶级域名服务器在收到请求后先查询缓存是否有对应的记录,若是有就返回对应的记录,若是没有找到就查询域名对应的二级域服务器地址,而后将域名对应的二级域服务器地址返回给本地DNS服务器。

6)本地DNS服务器收到应答报文后,获得二级域服务器的地址,而后向该地址发送请求解析域名的DNS请求报文。

7)二级域服务器在收到请求后先查询缓存是否有对应的记录,若是有就返回对应的记录,若是没有找到就查询域名对应的三级域服务器地址,而后将域名对应的三级域服务器地址返回给本地DNS服务器。

8)本地DNS服务器收到应答报文后,获得三级域服务器的地址,而后向该地址发送请求解析域名的DNS请求报文。

9)三级域服务器在收到请求后在DNS区域数据库中查询对应的记录,返回对应的记录

10)本地名称服务器在收到三级域服务器后,向用户返回一条DNS应答报文,并将这条记录保存在缓存中

11)浏览器就获得了域名对应的ip地址,而后就能够发起http请求了

3次握手4次挥手

ACK : TCP协议规定,只有ACK=1时有效,也规定链接创建后全部发送的报文的ACK必须为1
SYN(SYNchronization):在链接创建时用来同步序号。当SYN=1而ACK=0时,代表这是一个链接请求报文。对方若赞成创建链接,则应在响应报文中使SYN=1和ACK=1.
所以, SYN置1就表示这是一个链接请求或链接接受报文。
FIN (finis):完,终结的意思, 用来释放一个链接。当 FIN = 1
时,代表此报文段的发送方的数据已经发送完毕,并要求释放链接。

1)第一次握手:创建链接。客户端发送 SYN 包到服务器,Sequence Number 为 x,进入 SYN_SENT 状态,等待服务器确认。
2)第二次握手:服务器收到 SYN 包,对这个报文进行确认,设置 Acknowledgment Number 为 Sequence Number + 1;同时本身也要发送 SYN 包,Sequence Number 为 y;服务器将这些全部信息放入 SYN + ACK 包中发送给客户发,服务器进入 SYN_RCVD 状态。
3)第三次握手:客户端收到 SYN + ACK 包。将 Acknowledgment Number 设为 y + 1,即服务器发来的 Sequence Number + 1,并向服务器发送 ACK 包,发送完成后客户端和服务器都进入 ESTABLISHED 状态。

clipboard.png

http相关
一般HTTP消息包括客户机向服务器的请求消息和服务器向客户机的响应消息。
在浏览器查看一个http请求的请求头部以下:

clipboard.png

http响应头部
从上图能够看到,头部信息包括三部分:
一、通用头部

1)通用头域包含请求和响应消息都支持的头域。
 2)Request URL:请求的URL地址
 3)Request Method: 请求方法,get/post/put/……
 4)Status Code:状态码,200 为请求成功
 5)Remote Address:路由地址

二、请求头部

1) Accept:  告诉WEB服务器本身接受什么介质类型,*/* 表示任何类型,type/* 表示该类型下的全部子类型;
 2)Accept-Charset:  浏览器申明本身接收的字符集
 Accept-Encoding:浏览器申明本身接收的编码方法,一般指定压缩方法,是否支持压缩,支持什么压缩方法  (gzip,deflate)
 3)Accept-Language:  浏览器申明本身接收的语言。语言跟字符集的区别:中文是语言,中文有多种字符集,好比big5,gb2312,gbk等等。
 4)Authorization:  当客户端接收到来自WEB服务器的 WWW-Authenticate 响应时,该头部来回应本身的身份验证信息给WEB服务器。
 5)Connection:表示是否须要持久链接。close(告诉WEB服务器或者代理服务器,在完成本次请求的响应后,断开链接,
 不要等待本次链接的后续请求了)。keep-alive(告诉WEB服务器或者代理服务器,在完成本次请求的响应后,保持链接,等待本次链接的后续请求)。
 6)Referer:发送请求页面URL。浏览器向 WEB 服务器代表本身是从哪一个 网页/URL 得到/点击 当前请求中的网址/URL。
 7)User-Agent: 浏览器代表本身的身份(是哪一种浏览器)。
 8)Host: 发送请求页面所在域。
 9)Cache-Control:浏览器应遵循的缓存机制。
        no-cache(不要缓存的实体,要求如今从WEB服务器去取)
        max-age:(只接受 Age 值小于 max-age 值,而且没有过时的对象) 
        max-stale:(能够接受过去的对象,可是过时时间必须小于 max-stale 值)  
        min-fresh:(接受其新鲜生命期大于其当前 Age 跟 min-fresh 值之和的缓存对象)
 10)Pramga:主要使用 Pramga: no-cache,至关于 Cache-Control: no-cache。
 11)Range:浏览器(好比 Flashget 多线程下载时)告诉 WEB 服务器本身想取对象的哪部分。
 12)Form:一种请求头标,给定控制用户代理的人工用户的电子邮件地址。
 13)Cookie:这是最重要的请求头信息之一

三、响应头部

1)Age:当代理服务器用本身缓存的实体去响应请求时,用该头部代表该实体从产生到如今通过多长时间了。
  2)Accept-Ranges:WEB服务器代表本身是否接受获取其某个实体的一部分(好比文件的一部分)的请求。bytes:表示接受,none:表示不接受。
  3) Cache-Control:服务器应遵循的缓存机制。
          public(能够用 Cached 内容回应任何用户)
          private(只能用缓存内容回应先前请求该内容的那个用户)
          no-cache(能够缓存,可是只有在跟WEB服务器验证了其有效后,才能返回给客户端) 
          max-age:(本响应包含的对象的过时时间)  
          ALL:  no-store(不容许缓存)  
  4) Connection: 是否须要持久链接
          close(链接已经关闭)。
          keepalive(链接保持着,在等待本次链接的后续请求)。
          Keep-Alive:若是浏览器请求保持链接,则该头部代表但愿 WEB 服务器保持链接多长时间(秒)。例如:Keep-Alive:300
  5)Content-Encoding:WEB服务器代表本身使用了什么压缩方法(gzip,deflate)压缩响应中的对象。 例如:Content-Encoding:gzip 
  6)Content-Language:WEB 服务器告诉浏览器本身响应的对象的语言。
  7)Content-Length:WEB 服务器告诉浏览器本身响应的对象的长度。例如:Content-Length: 26012
  8)Content-Range:WEB 服务器代表该响应包含的部分对象为整个对象的哪一个部分。例如:Content-Range: bytes 21010-47021/47022
  9)Content-Type:WEB 服务器告诉浏览器本身响应的对象的类型。例如:Content-Type:application/xml
 10)Expired:WEB服务器代表该实体将在何时过时,对于过时了的对象,只有在跟WEB服务器验证了其有效性后,才能用来响应客户请求。
 11) Last-Modified:WEB 服务器认为对象的最后修改时间,好比文件的最后修改时间,动态页面的最后产生时间等等。
 12) Location:WEB 服务器告诉浏览器,试图访问的对象已经被移到别的位置了,到该头部指定的位置去取。
 13)Proxy-Authenticate: 代理服务器响应浏览器,要求其提供代理身份验证信息。
 14)Server: WEB 服务器代表本身是什么软件及版本等信息。
 15)Refresh:表示浏览器应该在多少时间以后刷新文档,以秒计。

clipboard.png

clipboard.png

clipboard.png

clipboard.png

html解析/dom树构建

clipboard.png

clipboard.png
同获取html方式获取css/js/图片的资源
dom树构建过程当中,遇到link标签、script标签会中止dom树构建,以获取html的方式获取相关资源。
解析构建css规则树
CSS解析的过程相似于HTML解析,也是浏览器使用自带的解析器进行解析,通常解析过程是由上而下,会将CSS文件解析成为StyleSheet对象,且每一个对象都包含CSS规则。CSS规则对象包含了选择和声明对象,以及其余与CSS语法对应的对象。CSS解析完成后会大体生成以下结构的CSS Rule Tree。

clipboard.png

构建渲染树
渲染的主要过程分为——Render Tree(渲染树)生成——Layout(布局)——Paint(绘制)。
DOM树和CSS树结合生成Render Tree(渲染树)——这是由可视化元素按照其显示顺序组成的树形结构,是文档可视化的表示,它的做用是让浏览器可以按照正确的顺序渲染页面元素。Firefox中称之为“框架”,Webkit中的术语则是呈现器或者呈现对象。
  渲染树是和DOM元素相对应的,可是并不是所有一一对应,例如:1,非可视化元素是不会出如今渲染树中,如“head”元素,2,若是元素的display属性值为“none”,也不会出如今渲染树中(可是visibility属性值为“hidden”的元素会出如今渲染树中)
布局layout
渲染树中并不包含位置和大小的信息,计算这些值的过程就是布局或者重排。
布局的过程是一个递归的过程,从根元素开始,递归遍历部分或者全部的渲染树结构,并为每个须要显示元素计算几何信息。通常根元素位置坐标(0,0),大小为浏览器窗口的可见区域。
这里涉及到两个重要的概念reflow和repaint:
 repaint(重绘):元素的某一部分属性发生改变,如字体颜色,背景颜色等改变,尺寸并未改变,这时发生的改变过程就是repaint。
  reflow(回流): 由于浏览器渲染是一个由上而下的过程,当发现某部分的变化影响了布局时,就须要倒回去从新渲染,这个过程就称之为reflow。reflow几乎是无法避免的,如今一些经常使用的效果,好比树状目录的折叠、展开(实质上是元素的显示与隐藏)等,都将引发浏览器的 reflow。鼠标滑过、点击……只要这些行为引发了页面上某些元素的占位面积、定位方式、边距等属性的变化,都会引发它内部、周围甚至整个页面的从新渲染。基本上能引发reflow的主要有几个缘由:

        1,网页初始化。

        2,JS操做DOM树的时候,增长删除元素等。

        3,某些元素的尺寸改变。

        4,CSS属性的改变,

  可是浏览器很聪明,为了不细小的改变就进行repaint或者reflow,浏览器采用一种"dirty"系统,会将这些改变操做积攒一批,而后作一次reflow,这又叫异步reflow或增量异步reflow。可是有些特殊状况不会这么作,好比:resize窗口,改变了页面默认的字体,等,对于这些操做,浏览器会立刻进行reflow。

  可是有的时候,咱们本身编写的脚本会阻止浏览器的这种操做,好比咱们请求下面的值的时候:offsetTop, offsetLeft, offsetWidth, offsetHeight,scrollTop/Left/Width/Height,clientTop/Left/Width/Height,IE中的 getComputedStyle(), 或 currentStyle等,若是咱们的程序运行的时候须要这些值,那么浏览器须要给咱们返回最新的值,而这样就会将当前积攒的操做执行,从而引发频繁的reflow或者repaint。

  一般reflow比repaint会耗费更多的时间,从而也就会影响性能,因此编写代码的时候要尽量避免过多的reflow或者repaint。减小reflow/repaint的方法:

        1,修改样式不要逐条修改,建议定义CSS样式的class,而后直接修改元素的className。

        2,不要将DOM节点的属性值放在循环中当成循环的变量。

        3,为动画的 HTML 元素使用 fixed 或 absoult 的 position,那么修改他们的 CSS 是不会 reflow 的。

        4,把DOM离线后修改。如设置DOM的display:none,而后进行你须要的屡次修改,而后再显示出来,或者clone一个节点到内存中,而后随意修改,修改完成后再与在线的交换。

        5,千万不要使用table布局,一个微小的改变就可能引发整个table的从新布局。
渲染页面

在绘制阶段,系统会遍历渲染树,而且调用呈现器将的“paint”方法,将内容显示在屏幕上。一样,相似于布局过程,也分为全局和增量两种

性能优化
 1,提高HTML加载速度

        -    页面精简,删除没必要要的注释,空格,将内嵌的JS和CSS移至外部文件,使用压缩工具等。

        -    减小文件数量,减小页面上引入的文件数量能够减小请求的次数,能够合并的JS和CSS文件尽可能合并。

        -    减小域名查询,DNS查询和解析域名须要消耗时间,减小对外部JavaScript、CSS、图片等资源的引用,不一样域名的使用越少越好。

        -    使用缓存,重用数据。

        -    优化页面元素的加载顺序。

        -    使用如今CSS和合法的标签。

        -    指定图片的大小,若是浏览能够当即肯定图片大小就不须要从新进行布局操做。

        -   根据浏览器类型选择合适的策略。

        -    使用压缩工具等。

        -    页面精简,删除没必要要的注释,空格,将内嵌的JS和CSS移至外部文件,使用压缩工具等。

        2,编写合理的CSS

        首先说明CSS选择符的匹配顺序,从右到左!从右到左!从右到左!(重要的事情说三遍),因此,相似于“#nav li” 咱们觉得很简单的规则,应该立刻就能够匹配成功,可是,须要从右往左匹配,因此,先会去查找全部的li,而后再去肯定它的父元素是否是#nav。所以,编写合理的CSS也能够提升咱们的页面行能:

        -    DOM的深度尽可能浅,不要嵌套过深。

        -    减小inline javascript  css的数量。

        -    使用合法的CSS属性。

        -    不要为ID选择器指定类名或者标签名。

        -    避免后代选择器,尽可能使用子选择器。

        -    避免使用通配符。

        3,关于javascript标签

        对于javascript标签首先得了解其加载和执行的特色:1,载入后当即执行,2,执行时会阻塞页面后续的内容,针对这些特色,咱们使用javascript标签时应该注意: 

        -    将全部的javascript标签放在页面底部,也就是body标签闭合以前,这样能够保证脚本执行前已完成DOM渲染。

        -    尽量合并脚本,页面中引入的脚本越少,加载响应速度也就越快。

        -    减小inline javascript的使用。

        -    全部的javascript标签会按照其引入顺序依次执行,只有前面的内容解析完成才会解析下一个,因此注意多个javascript标签的引入顺序。

        -    使用defer属性,该属性可使脚本在文档彻底呈现之后再执行。

        -    使用async属性,可使当前脚本没必要等待其余脚本的执行,也没必要阻塞文档的呈现。

参考文章-英文
参考文章-中文

相关文章
相关标签/搜索