当咱们在浏览器中输入一个URL后,发生了什么?

写在开头:这篇文章被我纳入博客性能优化类别,是由于我认为若是咱们要优化网站性能、提高用户体验,首要目标就是要知道用户在本地请求并加载你的网页的过程当中,到底发生了什么,在此基础上咱们才能更好的优化网页。

原文发表在个人我的博客: kmknkk.xincss

图源:知乎张秋怡
图源:知乎-张秋怡html

浏览器解析并查询缓存

DNS查询

  • DNS查询顺序以下,若其中一步成功则直接跳到创建连接部分:canvas

    • 浏览器自身DNS
    • 操做系统DNS
    • 本地hosts文件
    • 向域名服务器发送请求

创建连接

  • TCP三次握手(three-way handshaking)浏览器

    • 发送方:SYN(synchronize)
    • 接收方:SYN/ACK(acknowledgement),确认信息传达
    • 发送方:ACK - 确认接收方在线可收消息,握手结束
    • Accept

TCP三次握手

TCP三次握手的的好处在于:发送方能够确认接收方仍然在线,不会由于白发送而浪费资源。缓存

发送HTTP请求

  • 报文首部(GET /index.html HTTP/1.1)性能优化

    • 方法
    • URL
    • HTTP版本
  • 空行(CR+LF)
  • 报文主体

注意:
1.HTTP是无链接无状态的,即HTTP在传输完成后就会断开(HTTP1.1之前),而且不会记录访问者的状态。服务器

从HTTP/1.1开始才默认支持持久化链接,即通讯一次之后链接不中断,HTTP/1.0须要手动设置:keep-alive。dom

正常来讲,HTTP请求、响应方式为每请求一次就响应一次:布局

请求1 -> 响应1 -> 请求2 -> 响应2 -> 请求3 -> 响应3

若采用持久链接请求管线化方式:性能

请求1 -> 请求2 -> 请求3 -> 响应1 -> 响应2 -> 响应3

使用管线化的条件:

  • 服务端须要支持管线化
  • 只有GET和HEAD能够进行管线化,POST请求有所限制
  • 管线化不会影响响应到来的顺序

2.关于CR(Carriage Return,回车)和LF(Line Feed,换行)

Dos和Windows采用CR/LF表示下一行
UNIX/Linux采用LF表示下一行
MAC OS系统则采用CR表示下一行

服务器发送响应

  • 报文首部(HTTP/1.1 200 OK)

    • HTTP版本
    • 响应状态码
    • 状态码信息
  • 空行(CR+LF)
  • 报文主体

客户端收到页面,浏览器渲染页面

执行如下过程:
浏览器渲染页面

解析HTML

  • 根据DOCTYPE来肯定文档类型(最多见的就是HTML5,注意若是是HTML4的话有严格和宽松模式之分)
  • 构建DOM树(根据HTML构建相似于二叉树的结构树)
  • 下载资源

    • CSS - 构建CSSOM树
    • js - 等下下载并执行后解析

浏览器渲染

在聊浏览器渲染以前,咱们先明确一个概念: 事实上,咱们看到的页面并非直观所见的一层图页,而是由许多DOM元素渲染层(Layers)组成的,以下图。

浏览器层级合成

页面的渲染过程

因此一个的页面的渲染过程由以下几步构成:

  • 构建渲染树(Render Tree): 根据DOM和CSSOM树渲染,不可见元素不被会渲染

由DOM树和CSSOM树构建Render Tree的过程

  • 布局(layout): CPU根据渲染树布局计算元素的具体位置和大小,转换成绝对像素,而且根据样式,分割成多个独立的渲染层(Layers),将每一层对应到位图中
  • 绘制(Paint): GPU根据每一个渲染层(Layers)的位图绘制每一个点,即像素填充,而且将因此渲染层缓存,若是下次页面变更可是渲染层没变就不会触发重绘。
  • 层级合成(Compositing): 顾名思义,即处理多层渲染层之间的关系,将其合成为一个完整的页面。

重绘和重排

重绘(repaint):

  • 元素视觉表现属性被改变即触发重绘,如改变visibility,color等,不会影响到dom结构

reflow(重排):

  • 与repaint区别就是:全部影响dom的元素布局的事件都会触发重排。同时也会触发repaint。
  • 这种开销是很是昂贵的,致使性能降低是必然的,页面元素越多效果越明显。

reflow常见状况:

  • 增删改DOM节点
  • 移动DOM的位置或是动画显示(因此尽可能用canvas来作动画)
  • 修改width、display等CSS样式
  • resize窗口或是滚动的时候
  • 修改网页默认字体(不建议)
  • display:none会触发reflow和repaint,而visibility:hidden只会产生repaint

显而易见,要提升页面性能,首要目标就是减小重绘重排,具体方法包括当不限于如下几种:

  • 压缩DOM深度,以避免内层元素改变而致使多个外层都改变。
  • 对于没用的元素,尽可能设置为display:none,减轻绘制压力。
  • 在对DOM进行大量元素操做时,咱们可使用利用DocumentFragment对象进行操做,最后再一次性装载进DOM结构中。
  • 指定img的大小:因为img是内联元素,因此在加载后会改变宽高,严重的会致使整个页面重排,因此最好在渲染前就设置好其宽高,或者让其脱离文档流。

DOM渲染层(Layers)与GPU硬件加速

知道了浏览器页面的渲染合成过程后,咱们不可贵出一个结论:

若是咱们把会发生大量重绘重排的元素提取出来,单独触发一个渲染层(Layer),就不会把其余元素一块儿带着重绘,这会大大提升页面性能。

那么如何触发渲染层,让GPU来加速绘制呢?最简单的方法有如下三种:

will-change: transform;
will-change: opacity;
transform: translateZ(0);

PS:使用Layers来触发GPU加速(硬件加速)也会带来负面影响,如电量损失过快、占用内存和GPU等。因此在使用中要注意不能滥用,在常触发重绘和重排的元素上使用便可。

相关文章
相关标签/搜索