1. 输入阶段
当我们在浏览器的地址栏输入字符的时候 浏览器开始检索历史记录,显示匹配的地址 如果没有匹配的地址,浏览器就会判断输入的内容是url还是要搜索的内容
如果是要搜索的内容,那么点击回车,他会跳转到默认的搜索引擎,并拼接url进行跳转 如果是url,他会在跳转之前添加上协议(如果缺少协议的话)
2. 请求阶段
浏览器通过进程间的通信(IPC),把URL请求发送到网络进程,网络进程发起真正的请求,在往下的步骤就是和计算机网络有关系了,参照下图
大体描述如下
浏览器构建HTTP Request请求 网络传输 服务器构建HTTP Response 响应 网络传输 浏览器渲染页面
在发起请求前,网络进程根据请求的URL查询是否缓存了资源,如果缓存了当前的资源,那么会将资源直接进行返回,如果没有,那么就会进行DNS解析
应用层
DNS解析
关于什么是DNS 点击 ,简单来说就是找到资源真正地址的服务,他就像一个电话簿,对于我们来说,我们记忆的是人名(www.baidu.com),而DNS记忆的是电话号码(IP地址)
生成请求报文
应用层生成针对目标WEB服务器的请求报文,HTTP的请求报文包括起始行、首部(请求头(Request Header))和主体(请求正文)部分,如下
GET/sample.jspHTTP/1.1
Accept:image/gif.image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)
Accept-Encoding:gzip,deflate
username=jinqiao&password=1234
HTTPS
一般服务器收到TCP报文的时候会解包提出HTTP报文,而HTTP报文是明文,这个时候就不安全了
为了解决上面的问题就需要在进入TCP报文之前,对HTTP报文加一次密就可以了,就就是HTTPS
HTTPS就是HTTP + SSL,在网络结构中位于HTTP和TCP协议之间
过程
HTTPS在传输数据之前需要客户端与服务端进行一个握手(TLS/SSL) 在握手过程中将确立双方加密传输数据的密码信息 TLS/SSL使用了非对称加密,对称加密以及hash等 点击
HTTPS相比于HTTP,虽然提供了安全保证,但是会带来一些时间上的损耗,比如握手和加密的过程,所以是否需要https应该根据具体情况在安全和性能方面做出权衡
传输层
传输层一般会建立TCP连接,且传输层的协议分为UDP和TCP两种
UDP是无连接的协议,TCP是可靠的有链接的协议,他主要表现在
接收方会收到数据进行确认 发送方会重传接收方为确认的数据 接收方会将接收到的数据按正确的顺序进行排序,并删除重复的数据 提供了控制拥挤的机制 点击 HTTP使用的是TCP协议,为了方便通信,将HTTP请求报文按序号分为多个报文段(segment),并对每个报文段进行封装。
使用本地一个大于1024以上的随机TCP源端口(这里假设是1030)建立到目的服务器TCP80号端口(HTTPS协议对应的端口号是443)的连接,TCP源端口和目的端口被加入到报文段中,学名叫协议数据单元(Protocol Data Unit,PUD)。因TCP是一个可靠的传输控制协议,传输层还会加入序列号、确认号、窗口大小、校验等参数,共添加20字节的头部信息,如下
他的大致过程如下
其中路由设备,它包含网络层、数据链路层和物理层
三次握手与四次挥手
三次握手建立连接,四次挥手断开连接
点击
网络层
网络层使用IP协议来选择路线
处理来自传输层的数据段segment
,将数据段segment
装入数据包packet
,填充包头,主要就是添加源和目的IP地址,然后发送数据。在数据传输的过程中,IP协议负责选择传送的路线,称为路由功能
数据链路层
为了保证数据的可靠传输,把数据包packet封装成帧(Frame),并按顺序传送各帧。由于物理线路的不可靠,发出的数据帧有可能在线路上出错或丢失,于是为每个数据分块计算出CRC(循环冗余检验),并把CRC添加到帧中,这样接收方就可以通过重新计算CRC来判断数据接收的正确性。一旦出错就重传 将数据包packet封装成帧(Frame),包括帧头和帧尾。帧尾是添加被称做CRC的循环冗余校验部分。帧头主要是添加数据链路层的地址,即数据链路层的源地址和目的地址,即网络相邻结点间的源MAC地址和目的MAC地址
物理层
数据链路层的帧(Frame)转换成二进制形式的比特(Bit)流,从网卡发送出去,再把比特转换成电子、光学或微波信号在网络中传输
网络传输
从客户机到服务器需要通过许多网络设备, 一般地,包括集线器、交换器、路由器等
集线器
集线器是物理层设备,比特流到达集线器后,集线器简单地对比特流进行放大,从除接收端口以外的所有端口转发出去
交换机
交换机是数据链路层设备,比特流到达交换机,交换机除了对比特流进行放大外,还根据源MAC地址进行学习,根据目的MAC地址进行转发。交换机根据数据帧中的目的MAC地址査询MAC地址表,把比特流从对应的端口发送出去
路由器
路由器是网络层设备,路由器收到比特流,转换成帧上传到数据链路层,路由器比较数据帧的目的MAC地址,如果有与路由器接收端口相同的MAC地址,则路由器的数据链路层把数据帧进行解封装,然后上传到路由器的网络层,路由器找到数据包的目的IP地址,并查询路由表,将数据从入端口转发到出端口。接着在网络层重新封装成数据包packet,下沉到数据链路层重新封装成帧frame,下沉到物理层,转换成二进制比特流,发送出去
3. 服务器
服务器接收到这个比特流,把比特流转换成帧格式,上传到数据链路层,服务器发现数据帧中的目的MAC地址与本网卡的MAC地址相同,服务器拆除数据链路层的封装后,把数据包上传到网络层。服务器的网络层比较数据包中的目的IP地址,发现与本机的IP地址相同,服务器拆除网络层的封装后,把数据分段上传到传输层。传输层对数据分段进行确认、排序、重组,确保数据传输的可靠性。数据最后被传到服务器的应用层 如果是静态网站,一般会经nginx做反向代理,根据请求的域名做location到服务器的某个静态文件上,比如:/root/www/index.html; 如果是动态网站,会由controller处理(MVC),返回一个页面。 然后进行反向传输
服务器返回一个http响应
这一部分对应于变成语言中的socket
4. 浏览器渲染
预渲染阶段
渲染进程准备
在chrome中一个标签对应一个渲染进程 但是如果从一个页面打开了另一个新的页面,新的页面与当前页面属于同一个站点的话,那么新页面会复用父页面的渲染进程,这个默认策略叫做:process-per-site-instance
提交文档
浏览器进程将网路进程接收到的html数据提交给渲染进程,具体如下
网络进程将资源下载完毕之后,告诉浏览器进程 浏览器进程向渲染进程发送"提交文档"的消息 渲染进程和网络进程建立传输数据的管道 文档数据传输完毕之后,渲染进程告诉浏览器进程 "确认提交"的消息 浏览器进程更新UI界面中的状态:比如安全状态、地址栏中的url,前进后退的状态
渲染阶段
一般的渲染顺序如下
构建dom 树 构建css 树 构建渲染树 节点布局 页面渲染
图片来自
构建DOM树
将html文档转换为浏览器认识的dom树,并保存到内存中
一般来说转换的顺序:字节数据 => 字符串 => Token => Node => DOM
浏览器从磁盘或者网络读取HTML原始字节,并根据文件制定的编码(例如UTF-8)将他们转化成字符串
样式计算
渲染引擎将css转化为浏览器可以理解的的样式表,如下
他会计算每个DOM节点的每个元素的具体样式,计算过程中遵循CSS继承和层叠规则
布局阶段
他会遍历可见的DOM元素,添加到布局树中(LayoutTree) 然后进行布局的计算 进行分层
针对z-index
、3D转换、页面滚动等,渲染引擎还要生成图层树(LayerTree) 拥有层叠上下文属性的元素会被提升为单独的一层,比如定位属性,透明属性、css路径等,详情点击 需要剪裁的地方也会被创建为新的图层。文字超过div会被剪裁,如果出现滚动条,也会被提升为单独的图层 栅格化操作
当图层的绘制列表准备好之后,浏览器就会把主进程列表提交给合成线程 一个页面可能很大,显示器并不能完全显示网页的所有内容,而当前显示器所有显示的可见区域就叫做视口(ViewPort) 合成线程会将图层划分为图块(title),图块大小通常是256*256
或者512*512
大小 合成线程会优先将视口附近的图来生成位图,而栅格化的含义就是将图块转为位图
重绘与重排
重绘与重排是页面渲染过程中非常重要的两个概念。页面生成以后,脚本操作、样式表变更,以及用户操作都可能触发重绘重排 回流(reflow)是firefox里的术语,在chrome中则成为重排(relayout)
回流
他是指敞口尺寸被改变、发生滚动动作,或者元素位置的相关属性被更新时会触发布局过程 在布局过程中要计算所有元素的位置信息。由于HTML使用的是流式布局,如果一个页面中一个元素的尺寸发生了变化,其后续的元素位置都要跟着发生变化,也就是重新进行流式布局的过程,所以被称为回流 在上面的3个树,(DOM树、Render树、Render Layer树)回流发生在render树上,我们常说的脱离文档流也就是指脱离渲染树(Render Tree) 悬殊的重绘只会发生在渲染层上(render layer),所以,如果要改变元素的视觉属性,最好让该元素称为一个独立的渲染层(render layer)
减少回流次数
不要一条一条的修改dom样式,而是修改className或者style.cssText 在内存中多次操作节点,完成后在添加到文档中去 对于一个元素进行复杂的操作时,可以先隐藏他,操作完成后再显示 在需要经常获取哪些引起浏览器回流的属性时,要先缓存到变量中去 不要使用table布局,因为一个小改动可能造成table的重新布局。而table渲染通常需要3被同等元素的时间
此外,将需要多次重绘的元素独立为render layer渲染层,如设置absolute,可以减少重绘范围;对于一些进行动画的元素,可以进行硬件渲染,从而避免重绘和回流
https://blog.csdn.net/ky1in93/article/details/122380722
https://www.jianshu.com/p/8446d0ce9782
https://blog.csdn.net/qinian8/article/details/99081105