美文网首页
从输入网址到页面呈现,中间都发生了什么?

从输入网址到页面呈现,中间都发生了什么?

作者: HolidayPeng | 来源:发表于2018-07-03 10:01 被阅读39次

    本文阅读时间10分钟,需要你先了解以下两点背景知识:
    一、浏览器的主要组件及功能;
    二、发起一个HTTP请求的全过程。
    如果这些你都OK,可以直接跳过去看后面的内容。不了解的请耐心往下看:

    一、浏览器的主要组件及功能:
      1. 用户界面 - 包括地址栏、后退/前进按钮、书签目录等;
      2. 浏览器引擎 - 用来查询及操作渲染引擎的接口;
      3. 渲染引擎 - 解析html及css,并将解析后的结果显示出来(Firefox使用Geoko,Safari和Chrome都使用webkit);
      4. 网络 - 用来完成网络调用,例如http请求;
      5. UI后端 - 用来绘制类似组合选择框及对话框等基本组件;
      6. JS解释器 - 用来解释执行JS代码;
      7. 数据存储 - 属于持久层,浏览器需要在硬盘中保存类似cookie的各种数据,HTML5定义了web database技术,这是一种轻量级完整的客户端存储技术。
      需要注意的是,不同于大部分浏览器,Chrome为每个Tab分配了各自的渲染引擎实例,每个Tab就是一个独立的进程。

    二、发起一个HTTP请求的全过程:
      1、用户输入url并敲击回车(如果用户输入的是ip地址则直接进入第3步);
      2、进行DNS解析(Domain Name System,域名系统,作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。),即通过主机名,最终得到该主机名对应的IP地址:
      (1) 浏览器会首先搜索浏览器自身的DNS缓存(缓存时间比较短,大概只有2分钟左右,且只能容纳1000条缓存);
      (2) 如果浏览器自身缓存找不到则会查看系统的DNS缓存,如果找到且没有过期则停止搜索解析到此结束;
      (3) 如果本机没有找到DNS缓存,则浏览器会发起一个DNS的系统调用,向本地配置的首选DNS服务器发起域名解析请求(通过的是UDP协议向DNS的53端口发起请求,这个请求是递归的请求,也就是运营商的DNS服务器必须得提供给我们该域名的IP地址),运营商的DNS服务器首先查找自身的缓存,找到对应的条目,且没有过期,则解析成功;
      (4) 如果没有找到对应的条目,则有运营商的DNS代我们的浏览器发起迭代DNS解析请求,它首先是会找根域的DNS的IP地址(这个DNS服务器都内置13台根域的DNS的IP地址),找到根域的DNS地址,就会向其发起请求(请问www.xxxx.com这个域名的IP地址是多少啊?)
      (5) 根域发现这是一个顶级域com域的一个域名,于是就告诉运营商的DNS我不知道这个域名的IP地址,但是我知道com域的IP地址,你去找它去,于是运营商的DNS就得到了com域的IP地址,又向com域的IP地址发起了请求(请问www.xxxx.com这个域名的IP地址是多少?)
      (6) com域这台服务器告诉运营商的DNS我不知道www.xxxx.com这个域名的IP地址,但是我知道xxxx.com这个域的DNS地址,你去找它去,于是运营商的DNS又向xxxx.com这个域名的DNS地址(这个一般就是由域名注册商提供的,像万网,新网等)发起请求(请问www.xxxx.com这个域名的IP地址是多少?),这个时候xxxx.com域的DNS服务器一查,拿到了www.xxxx.com这个域名对应的IP地址,并返回给系统内核,内核又把结果返回给浏览器,终于浏览器拿到了www.xxxx.com对应的IP地址,这次dns解析圆满成功。
       3、拿到域名对应的IP地址之后,User-Agent(一般是指浏览器)会以一个随机端口(1024< 端口 < 65535)向服务器的WEB程序80端口发起TCP的连接请求。这个连接请求(原始的http请求经过TCP/IP4层模型的层层封包)到达服务器端后(这中间通过各种路由设备,局域网内除外),进入到网卡,然后是进入到内核的TCP/IP协议栈(用于识别该连接请求,解封包,一层一层的剥开),还有可能要经过Netfilter防火墙(属于内核的模块)的过滤,最终到达WEB程序,最终建立了TCP/IP的连接。
      4、建立TCP连接后发起http请求
      5、服务器端响应http请求,浏览器得到html代码。

    三、浏览器渲染页面全过程:
      1. 浏览器会将HTML标签解析成一个DOM树,DOM 树的构建过程是一个深度遍历过程:当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点;
      2. 当发现<head>标签内有一个<link>标签引用外部CSS文件,浏览器又发出CSS文件的请求,服务器返回这个CSS文件;
      3. 将CSS解析成 CSS Rule Tree ;
      4. 根据DOM树和CSS Rule Tree来构造 Rendering Tree。注意:Rendering Tree 渲染树并不等同于 DOM 树,因为一些像Header或display: none的东西是不会被加入渲染树中的,而visibility: hidden 则会,所以如果某个节点最开始是不显示的,设为display: none是更优的。另外display: none 会触发 reflow,而 visibility: hidden 只会触发 repaint,因为没有发现位置变化;
      5. 有了Render Tree,浏览器已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系。下一步操作称之为layout,即计算出每个节点在屏幕中的位置;
      6. painting: 渲染引擎会遍历渲染树,由用户界面后端层将每个节点绘制出来
    照算出来的规则合并图层然后通过显卡显示到屏幕上;
      7. 当浏览器发现某个部分发生了点变化影响了布局,需要倒回去重新渲染,称为reflow。比如浏览器在代码中发现一个<img>标签引用了一张图片,就会向服务器发出请求;服务器返回图片文件,由于图片占用了一定面积,影响了后面段落的排布,因此浏览器需要回过头来重新渲染这部分代码。reflow 会从 <html> 这个 root frame 开始递归往下,依次计算所有的结点几何尺寸和位置;
      8.repaint(重绘):改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画,但是元素的几何尺寸没有变;
      9. 浏览器发现了一个包含一行Javascript代码的<script>标签,赶快运行它

    四、javascript代码运行的同步与异步:
      javascript引擎中负责解释和执行javascript代码的线程只有一个,称为主线程。主线程上只执行同步任务,异步任务会有工作线程来执行。
      工作线程包括处理 ajax 的线程、dom事件线程、定时器线程、读写文件的线程等。
      主线程执行时生成的调用栈。当需要进行异步操作时(定时器、ajax请求、dom事件注册等), 主线程会发一个异步任务的请求, 相应的工作线程接受请求;工作线程的任务完成之后, 会把回调函数推入到一个任务队列。当调用栈为空时, 主线程会从任务队列里取一个回调函数并放入当前的调用栈当中执行, 主线程会一直重复这个动作直到消息队列为空。 这个过程就叫做事件循环 (event-loop)。

    [参考资料]:
    https://blog.csdn.net/liaozhongping/article/details/51028705
    https://blog.csdn.net/riddle1981/article/details/78681191
    https://segmentfault.com/a/1190000009975744

    相关文章

      网友评论

          本文标题:从输入网址到页面呈现,中间都发生了什么?

          本文链接:https://www.haomeiwen.com/subject/sbsluftx.html