浏览器页面渲染原理深入!!
浏览器页面渲染原理深入!!
从用户输入URL到页面渲染显示经历两大部分:网络通信 和 页面渲染
1、网络通信:
总流程:
1.1输入URL回车
1.2开始进行DNS域名解析:优先从缓存中查找,再从子级域名至顶级域名依次请求相应的DNS服务器,直到拿到相应的IP地址–使用UDP运输协议
注:**DNS数据库是域名和IP地址相互映射的一个分布式数据库,DNS协议用来将域名转换为IP地址,它运行在UDP协议之上。
为什么选择UDP而非TCP?
原因如下:UDP无需连接,时效性更好,进行一次查询只需要两个DNS包。而TCP需要先用3个包建立连接,再用2个DNS包进行查询,最后用4个包断开连接,连接成本远大于查询本身,容易让DNS服务器不堪重负。**
1.3开始建立TCP三次报文握手连接
SYN请求报文段------不能携带数据,消耗一个序号
ACK确认报文段------可以携带数据
客户端初始序号seq=x
服务器确认号ACK=x+1 初始号seq=y
通过三次报文建立连接
注:为什么需要进行三次握手,而不是两次握手?
1.4开始发送HTTP请求报文--应用层–使用TCP运输协议
注:**HTTP协议本身是无连接的,无状态的,但是使用了面向连接的运输层TCP协议,保证了数据的可靠传输
+
数据传输过程:HTTP应用层----->TCP运输层------>IP网络层------->MAC数据链路层------->比特流-物理层
1.5服务器返回HTTP响应
1.6浏览器开始处理HTTP响应
-
浏览器检查HTTP响应Header的状态码,采取相应的处理措施
常见的状态码
状态码 响应类别 原因短语 1XX 信息性状态码(Informational) 服务器正在处理请求 2XX 成功状态码(Success) 请求已正常处理完毕 3XX 重定向状态码(Redirection) 需要进行额外操作以完成请求 4XX 客户端错误状态码(Client Error) 客户端原因导致服务器无法处理请求 5XX 服务器错误状态码(Server Error) 服务器原因导致处理请求出错 2xx:
- 200 OK表示请求成功处理,并返回 内容
- 204 NO Content表示成功处理,但无内容返回
- 206 Partial Content表示范围请求成功
3xx:
- 301 Moved Permanently 永久重定向,表示请求的资源已经永久的搬到了其他位置
就是说资源已经被分配了新的URI - 302 Found 临时重定向,表示请求的资源临时搬到了其他位置
请求的资源暂时被配到到了新的URI - 303 See Other 表示请求资源存在另一个URI,应使用GET定向获取请求资源
303功能与302一样,区别只是303明确客户端应该使用GET访问 - 304 Not Modified 表示客户端发送附带条件的请求(GET方法请求报文中的IF…)时,条件不满足
返回304时,不包含任何响应主体
4xx:
- 400 Bad Request 表示请求报文存在语法错误或参数错误,服务器不理解
服务器不应该重复提交这个请求 - 401 Unauthorized 表示发送的请求需要有HTTP认证信息或者是认证失败了
- 403 Forbidden表示对请求资源的访问被服务器拒绝了,你可能没有访问权限
- 404 Not Found 表示服务器找不到你请求的资源,服务器没有这个资源路径
5xx:
- 500 Internal Server Error 服务器出故障了
- 503 Service Unavailable 服务器繁忙
- 浏览器开始加载、解析、渲染页面
1.6关闭TCP连接
通过四次挥手
注:为什么通过四次挥手?
服务器必须先同意断开连接,但此时如果还有数据发送,就不能立即发送断开连接请求!!所以需要四次握手
参考博文连接:https://www.jianshu.com/p/71cf7f69eca8
https://blog.****.net/kang___xi/article/details/80407735
https://blog.****.net/Scythe666/article/details/51926042
https://blog.****.net/q1056843325/article/details/53147180
2.浏览器页面加载、解析、渲染
总流程:
1.拿到HTTP响应的HTML数据----->浏览器开始加载HTML文件------>边加载边解析生成DOM树===>一个线程
2.遇到非js文件的link----->开启另一个线程开始加载,并解析CSSDOM树
3.遇到js文件----->浏览器将挂起当前线程---->开始加载并解析js文件----->解析完毕之后---->继续开始加载解析DOM树
4.遇到CSS文件---->直接开始同步加载解析,并生成CSSDOM树
5.最后生成Render树,开始进行页面绘制渲染
6.页面渲染过程:repaint重绘:屏幕每个区域内容改变,几何尺寸没变
reflow重排:组件几何尺寸改变,需要从下往上递归全部重新绘制
类比:C语言程序的编译过程,C程序无法直接识别,必须编译成obj文件,连接为exe可执行文件,才能被执行
同样的,HTML及CSS和JS文件,计算机也无法直接识别,必须先将文件解析成DOM和CSS render树,此文件才能被浏览器渲染执行
**js脚本的放置规则:**浏览器对HTML文件中的标签挨个进行解析,同时将其加入至DOM节点中
-
静态js脚本,在解析是必须执行的脚本==----------->==由于此js脚本需要直接加入DOM节点操作,一般置于head前,或者放于被控制的标签前后
-
需要DOM解析完成并成功渲染,即文档加载完成时执行的js脚本==--------->==由于此脚本在文档加载完成前,不会进行解析,故可以放于head或body内均可
-
动态加载脚本,如大量使用虚拟DOM进行动态渲染的Vue.js脚本==----------->===此脚本必须置于</body>前,为什么呢?
//HTML
<div>{{msg}}</div>
//Vue.js
<script>
new Vue({
el:"div",
data:{
msg:"Hello Vue.js!!"
}
})
</script>
/*看一下结果:Vue.js放置在div前,渲染结果为 {{msg}}
Vue.js放置在div后,渲染结果为 Hello Vue.js!!
原因如下:
置于div前,浏览器先解析Vue.js脚本,由于Vue使用el绑定在了一个div渲染,但此前没有div,所以绑定失败,浏览器跳过js脚本,直接渲染之后的HTML内容
置于div后,浏览器先把div渲染成{{msg}},之后开始解析Vue.js脚本,Vue脚本生成一个VNode虚拟节点,调用diff函数生成真实节点,渲染到页面中,所以使用Vue.js页面一共渲染了两次!!!!
*/
- 定义、声明、框架类的脚本==-------->这类脚本一般浏览器只会加载一下,并不会解析,只有你使用脚本调用函数的时候,才会去解析这个文件,并找到相应的执行代码,所以,可以放于head或body中均可,但是必须置于你的调用执行脚本==之前,否则会报错!!!
优化方案:
-
js优化:
- 由于js脚本加载都会中断页面渲染,虽然有些脚本并不会立即解析执行,但终归影响渲染速度,==可以使用script的defer及async属性进行js脚本加载优化:必须立即执行使用async,加载完成再执行使用defer
参考博文:[script标签中defer和async属性的区别](http://www.cnblogs.com/neusc/archive/2016/08/12/5764162.html)
- 减少DOM操作,代价高昂,由于修改和访问DOM元素会造成页面的Repaint和Reflow,循环对DOM操作更是罪恶的行为。所以请合理的使用JavaScript变量储存内容,考虑大量DOM元素中循环的性能开销,在循环结束时一次性写入。
- 使用json格式数据交换格式
-
减少资源的HTTP请求次数
- 使用webpack对请求资源进行打包
- 使用精灵图加载图片
- 使用CDN内容分发网络技术
-
对CSS进行优化,由于CSS为逆向解析机制
- 避免使用通配规则*{};
- 少用后代选择器 ;
- 多用class id唯一限定的选择器;
- 开始使用静态页面布局,将每个区域尺寸大小全部锁定好,从而形成独立的渲染区域,减少reflow重排深度!!
-
精简CSS、HTML、JS文件的内容大小,使用webpack对其进行打包!!移除注释;移除额外的空格;细微优化;标识符替换。
参考博文:从浏览器渲染原理谈页面优化