从输入URL到浏览器显示页面过程中都发生了什么?
URL的输入到浏览器解析的一系列事件
- 浏览器根据请求的url交给DNS域名解析
- 发起TCP连接
- 发送HTTP请求
- 服务器处理请求并返回HTTP报文
- 浏览器解析渲染页面
- 连接结束。
简单说说,浏览器根据请求的url交给dns域名解析,查找真正的ip地址,向服务器发起请求;服务器交给后台处理后,返回数据,浏览器会接收到文件数据,比如,html,js,css,图像等;然后浏览器会对加载到的资源进行语法解析,建立相应的内部数据结构;载入解析到得资源文件,渲染页面,完成显示页面效果。
不够清楚明白吗?
那就再次详细一下,从浏览器接收url,开始进行网络请求线程,发出一个完整的HTTP请求,从服务器端接收请求到对应的后台接收到请求,然后是后台和前台的http交互;其中的缓存问题(http的缓存),浏览器接收到http数据包后的解析流程,css的可视化格式模型,js引擎解析过程等;其他呈现页面效果
这里就需要你对浏览器内核的理解:其中主要的渲染引擎和JS引擎,这里了解一下你对浏览器内核的理解。
渲染引擎,是负责取得网页的内容,整理信息,以及计算网页的显示方式,然后输出到显示器上。
JS引擎是用于解析和执行javascript来实现网页的动态效果。
浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。其实最开始渲染引擎和JS引擎是没有区分明确的,不过后来JS引擎越来越独立,so,内核就倾向于渲染引擎。
对于资源请求/获取,资源响应/页面渲染,会给网络带宽和设备资源带来压力,这个时候就会考虑到web的性能优化。
通过DNS解析域名的实际IP地址
发送至 DNS 服务器并获得域名对应的 WEB 服务器的 ip 地址。
DNS 解析首先会从你的浏览器的缓存中去寻找是否有这个网址对应的 IP 地址,如果没有就向OS系统的 DNS 缓存中寻找,如果没有就是路由器的 DNS 缓存, 如果没有就是 ISP 的DNS 缓存中寻找。 所以,缓存的寻找过程就是: 浏览器 -> 系统 -> 路由器 -> ISP。 如果在某一个缓存中找到的话,就直接跳到下一步。 如果都没有找到的话,就会向 ISP 或者公共的域名解析服务发起 DNS 查找请求。这个查找的过程还是一个递归查询的过程。
检查浏览器是否有缓存
通过Cache-Control和Expires来检查是否命中强缓存,命中则直接取本地磁盘的html(状态码为200 from disk(or memory) cache,内存or磁盘);
如果没有命中强缓存,则会向服务器发起请求(先进行下一步的TCP连接),服务器通过Etag和Last-Modify来与服务器确认返回的响应是否被更改(协商缓存),若无更改则返回状态码(304 Not Modified),浏览器取本地缓存;
若强缓存和协商缓存都没有命中则返回请求结果。
与 WEB 服务器建立 TCP 连接
TCP 协议通过三次握手建立连接。
客户端通过 SYN 报文段发送连接请求,确定服务端是否开启端口准备连接。状态设置为 SYN_SEND;
服务器如果有开着的端口并且决定接受连接,就会返回一个 SYN+ACK 报文段给客户端,状态设置为 SYN_RECV;
客户端收到服务器的 SYN+ACK 报文段,向服务器发送 ACK 报文段表示确认。此时客户端和服务器都设置为 ESTABLISHED 状态。连接建立,可以开始数据传输了。
翻译成大白话就是:
客户端:你能接收到我的消息吗?
服务端:可以的,那你能接收到我的回复吗?
客户端:可以,那我们开始聊正事吧。
为什么是3次?:避免历史连接,确认客户端发来的请求是这次通信的人。
为什么不是4次?:3次够了第四次浪费
浏览器发送HTTP请求
首先科补一个小知识,HTTP的端口为80/8080,而HTTPS的端口为443
发送HTTP请求的过程就是构建HTTP请求报文并通过TCP协议中发送到服务器指定端口 请求报文由请求行,请求抱头,请求正文组成。
请求行
请求行的格式为Method Request-URL HTTP-Version CRLF eg: GET index.html HTTP/1.1 常用的方法有: GET,POST, PUT, DELETE, OPTIONS, HEAD。
常见的请求方法区别
这里主要展示GET和POST的区别
1 |
|
1 |
|
服务器处理请求并返回HTTP报文
它会对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。这一部分工作一般是由Web服务器去进行,分成三份,状态码 ,响应报头和响应报文(你从服务器请求的HTML,CSS,JS文件就放在这里面)
浏览器解析渲染页面
解析HTML形成DOM树
解析CSS形成CSSOM 树
合并DOM树和CSSOM树形成(Render Tree)渲染树
浏览器开始渲染并绘制页面 这个过程涉及两个比较重要的概念回流和重绘,DOM结点都是以盒模型形式存在,需要浏览器去计算位置和宽度等,这个过程就是回流。等到页面的宽高,大小,颜色等属性确定下来后,浏览器开始绘制内容,这个过程叫做重绘。浏览器刚打开页面一定要经过这两个过程的,但是这个过程非常非常非常消耗性能,所以我们应该尽量减少页面的回流和重绘
CSS阻塞情况以及优化
1、style标签中的样式:由HTML解析器进行解析,不会阻塞浏览器渲染(可能会产生“闪屏现象”),不会阻塞DOM解析
2、link引入的CSS样式:由CSS解析器进行解析,会阻塞浏览器渲染,会阻塞后面的js语句执行,不阻塞DOM的解析
3、优化:使用CDN节点进行外部资源加速,对CSS进行压缩,优化CSS代码(不要使用太多层选择器)
JS阻塞问题
1、js会阻塞后续DOM的解析,原因是:浏览器不知道后续脚本的内容,如果先去解析了下面的DOM,而随后的js删除了后面所有的DOM,那么浏览器就做了无用功,浏览器无法预估脚本里面具体做了什么操作,例如像document.write这种操作,索性全部停住,等脚本执行完了,浏览器再继续向下解析DOM
2、js会阻塞页面渲染,原因是:js中也可以给DOM设置样式,浏览器等该脚本执行完毕,渲染出一个最终结果,避免做无用功。
3、js会阻塞后续js的执行,原因是维护依赖关系,例如:必须先引入jQuery再引入bootstrap
资源加载阻塞
无论css阻塞,还是js阻塞,都不会阻塞浏览器加载外部资源(图片、视频、样式、脚本等)
原因:浏览器始终处于一种:“先把请求发出去”的工作模式,只要是涉及到网络请求的内容,无论是:图片、样式、脚本,都会先发送请求去获取资源,至于资源到本地之后什么时候用,由浏览器自己协调。这种做法效率很高。
为什么CSS解析顺序从右到左
如果是从左到右的话:
1、第一次从爷节点 -> 子节点 -> 孙节点1
2、第一次从爷节点 -> 子节点 -> 孙节点2
3、第一次从爷节点 -> 子节点 -> 孙节点3
如果三次都匹配不到的话,那至少也得走三次:爷节点 -> 子节点 -> 孙节点,这就做了很多无用功啊
如果是从右到左的话:
1、第一次从孙节点1,找不到,停止
2、第一次从孙节点2,找不到,停止
3、第一次从孙节点3,找不到,停止
这样的话,尽早发现找不到,尽早停止,可以少了很多无用功。
什么是重绘回流
1、重绘:重绘是一个元素外观的改变所触发的浏览器行为,例如改变outline、背景色等属性。浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。重绘不会带来重新布局,所以并不一定伴随重排。
2、回流:渲染对象在创建完成并添加到渲染树时,并不包含位置和大小信息。计算这些值的过程称为布局或重排,或回流
3、”重绘”不一定需要”重排”,比如改变某个网页元素的颜色,就只会触发”重绘”,不会触发”重排”,因为布局没有改变。
4、”重排”大多数情况下会导致”重绘”,比如改变一个网页元素的位置,就会同时触发”重排”和”重绘”,因为布局改变了。
浏览器缓存分类
强缓存
不会向服务器发送请求,直接从本地缓存中获取数据
请求资源的的状态码为: 200 ok(from memory cache)
优先级:cache-control > expires
协商缓存
向服务器发送请求,服务器会根据请求头的资源判断是否命中协商缓存
如果命中,则返回304状态码通知浏览器从缓存中读取资源
优先级:Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304
参考文章
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!