1)应用层进行DNS解析
通过域名解析成IP地址。在解析过程中,按照浏览器缓存
、系统缓存
、路由器缓存
、ISP(运营商)DNS缓存
、根域名服务器
、顶级域名服务器
、主域名服务器
的顺序,逐步读取缓存,直到拿到IP地址。
DNS协议是一个查询/回复的协议,查询和回复的数据格式相同。当一个应用需要把域名解析为一个IP地址时,就调用解析程序,称为DNS的一个客户,把待查询的域名以UDP数据报的方式发给本地域名服务器。本地域名服务器查询缓存,如果存在则把对应的IP地址放在回答报文中返回。应用程序获得目的主机的IP地址后即可进行通信。
递归与迭代的区别
如果本地DNS服务器本地区域文件与缓存解析都失效,则根据本地DNS服务器的设置(是否设置转发器)进行查询,如果未用转发模式,本地DNS就把请求发至 “根DNS服务器”,“根DNS服务器”收到请求后会判断这个域名(.com)是谁来授权管理,并会返回一个负责该顶级域名服务器的一个IP。本地DNS服务器收到IP信息后,将会联系负责.com域的这台服务器。这台负责.com域的服务器收到请求后,如果自己无法解析,它就会找一个管理.com域的下一级DNS服务器地址(qq.com)给本地DNS服务器。当本地DNS服务器收到这个地址后,就会找qq.com域服务器,重复上面的动作,进行查询,直至找到www.qq.com主机。
如果用的是转发模式,此DNS服务器就会把请求转发至上一级DNS服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根DNS或把转请求转至上上级,以此循环。不管是本地DNS服务器用是是转发,还是根提示,最后都是把结果返回给本地DNS服务器,由此DNS服务器再返回给客户机。
递归是用户只向本地DNS服务器发出请求,然后等待肯定或否定答案。而迭代是本地服务器向根DNS服务器发出请求,而根DNS服务器只是给出下一级DNS服务器的地址,然后本地DNS服务器再向下一级DNS发送查询请求直至得到最终答案。
这里可以使用预解析,提前解析可能用到的域名,使解析结果缓存到系统缓存中,缩短DNS解析时间,提高网站访问速度。
2)应用层生成HTTP请求报文
HTTP请求报文包括起始行、首部和主体部分。
如果访问的google.com,则起始行可能如下
GET https://www.google.com/ HTTP/1.1
首部包括域名host、keep-alive、User-Agent、Accept-Encoding、Accept-Language、Cookie等信息
首部和主体内容之间有一个回车换行(CRLF),主体内容即要传输的内容。如果是get请求,则主体内容为空
3)传输层建立TCP连接
TCP协议是面向连接的,所以它在开始传输数据之前需要先建立连接。要建立或初始化一个连接,两端主机必须同步双方的初始序号。同步是通过交换连接建立数据分段和初始序号来完成的,在连接建立数据分段中包含一个SYN(同步)的控制位。同步需要双方都发送自己的初始序号,并且发送确认的ACK。此过程就是三次握手
TCP三次握手我之前有写过随笔,就不再介绍。
构建TCP请求会增加大量的网络时延,常用的优化方式如下所示
(1)资源打包,合并请求
(2)多使用缓存,减少网络传输
(3)使用keep-alive建立持久连接
(4)使用多个域名,增加浏览器的资源并发加载数,或者使用HTTP2的管道化连接的多路复用技术
4)网络层使用IP协议来选择路线
处理来自传输层的数据段segment,将数据段segment装入数据包packet,填充包头,主要就是添加源和目的IP地址,然后发送数据。在数据传输的过程中,IP协议负责选择传送的路线,称为路由功能
5)数据链路层实现网络相邻结点可靠的数据通信
为了保证数据的可靠传输,把数据包packet封装成帧(Frame),并按顺序传送各帧。由于物理线路的不可靠,发出的数据帧有可能在线路上出错或丢失,于是为每个数据分块计算出CRC(循环冗余检验),并把CRC添加到帧中,这样接收方就可以通过重新计算CRC来判断数据接收的正确性。一旦出错就重传。
6)物理层传输数据
数据链路层的帧(Frame)转换成二进制形式的比特(Bit)流,从网卡发送出去,再把比特转换成电子、光学或微波信号在网络中传输
7)服务器传输一个HTTP响应报文
8)浏览器解析
1、如果HTTP响应报文是301或302重定向,则浏览器会相应头中的location再次发送请求
2、浏览器处理HTTP响应报文中的主体内容,首先使用loader模块加载相应的资源
3、使用parse模块解析HTML、CSS、Javascript资源
9)浏览器渲染
指一系列在首屏渲染中必须发生的事件
获取html > 获取资源 > 解析 > 显示页面
某些资源(css/js)加载会阻塞页面渲染;这些非必须资源花费大量时间加载,应考虑移出关键路径。
首屏渲染需要关注三件事:优化资源数量/优化子节数/优化路径长度
- 图片懒加载:一开始只加载首页的图片
- js文件:只加载首屏的js
- 减少css文件,或者合并外部css文件,或者内嵌css
(构建渲染树)
- 从DOM树的根节点开始遍历每个可视节点。
- 对每个这样的节点,找到CSSOM树中对应的规则,并应用他们。
- 根据每个可见节点及其对应样式,生成渲染树。
3. 回流:根据渲染树,得到节点的位置和大小;
4. 重绘:根据渲染树以及回流,得到节点的绝对像素;
5. 将像素发送给GPU,展示在页面上。
重绘:通过构造渲染树和回流阶段后,将每个节点转换成屏幕上的实际像素;
回流:计算渲染树节点在设备视图内的确切位置和大小,那么当页面布局和几何信息发生变化时就需要回流。比如:
- 添加或删除可见的DOM元素
- 元素的位置发生变化
- 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
- 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。
- 页面一开始渲染的时候(这肯定避免不了)
- 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
回流必定会发生重绘,重绘不一定会引发回流。
1)现代的浏览器都是很聪明的,由于每次重排都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化重排过程。浏览器会将修改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列。但是!当你获取布局信息的操作的时候,会强制队列刷新,比如
- offsetTop、offsetLeft、offsetWidth、offsetHeight
- scrollTop、scrollLeft、scrollWidth、scrollHeight
- clientTop、clientLeft、clientWidth、clientHeight
- getComputedStyle()
- getBoundingClientRect
所以最好避免以上属性,如要使用,最好将值缓存起来。
2)批量修改DOM,先使元素脱离文档流
隐藏元素,应用修改,重新显示
使用文档片段在外构建子树,再拷贝回当前DOM
将原始元素拷贝到一个脱离文档的节点中,修改节点后,再替换原始的元素
3)对于复杂动画效果,使用绝对定位让其脱离文档流
4)使用css3硬件加速,可以让transform、opacity、filters这些动画不会引起回流重绘 。
如果你为太多元素使用css3硬件加速,会导致内存占用较大,会有性能问题。
原文链接:https://www.cnblogs.com/lora404/p/12488032.html
原创文章,作者:优速盾-小U,如若转载,请注明出处:https://www.cdnb.net/bbs/archives/16451