fangchaolong
文章57
标签24
分类10
网页性能优化升级

网页性能优化升级

从输入一个url到浏览器展现页面都经历了哪些

  1. 浏览器先查看浏览器缓存 -> 系统缓存 -> 路由器缓存 如果缓存中有,会直接在屏幕中显示页面内容。若没有,则跳到第三步操作。
  2. 在发送http请求前,需要域名解析(DNS解析),获取解析对应的url。
  3. 浏览器与服务器进行tcp三次握手
  4. 握手成功之后, 浏览器向服务器发送http请求,请求数据包
  5. 服务器处理浏览器的请求,将数据返回给浏览器
  6. 浏览器收到http响应
  7. 浏览器读取数据,并解析html结构。
  8. 生成Dom树、解析css样式、js交互
  9. 客户端和服务器交互

具体可分为:网络、资源、渲染、执行层
优化点可以从这四点下手

网络优化

(1)DNS 处理:增加 dns-prefetch

浏览器对网站第一次的域名 DNS 解析查找流程依次为:浏览器缓存 >> 系统缓存 >> 路由器缓存 >> ISP DNS 缓存 >> 递归搜索。

移动端环境下,DNS 请求带宽非常小,但延迟很高。针对该问题,我们采取预读取DNS方案,该方案能显著降低延迟,平均加载时长可减少1秒左右。

为帮助浏览器对某些域名进行预解析,我们对上线活动 html 文档中新增 dns-prefetch标签。加入该标签后,浏览器解析步骤如下:

第一步:用 meta 信息来告知浏览器,当前页面要做 DNS 预解析:

<meta http-equiv="x-dns-prefetch-control" content="on" />

第二步:在页面 header 中使用 link 标签来强制对 DNS 预解析:

<link rel="dns-prefetch" href="//topicstatic.vivo.com.cn" />

(2) CDN 分发优化

CDN 的全称是 Content Delivery Network,即内容分发网络。CDN 是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。

下图展示终端用户访问页面时,CDN获取过程:

active

缓存对于CDN服务至关重要,合适的缓存策略能够降低源站的请求压力,从而提升页面加载速度,因此我们需要优化静态资源存储方式和缓存策略。

CDN资源缓存配置如下:

active

静态资源上传至CDN,带来如下提升:

  1. 通过 CDN 向用户分发传输相关库的静态资源文件,可以降低我们自身服务器的请求压力。
  2. 大多数 CDN 在全球都有服务器,所以 CDN上的服务器在地理位置上可能比你自己的服务器更接近你的用户。用户直接访问边缘缓存,极大地提升页面资源的响应速度。
  3. 不缓存HTML入口文件,只缓存js、css的策略,避免资源不更新的同时,加快了专题资源的获取速度。

不缓存HTML入口文件的目的是防止客户端缓存策略,导致主入口资源不更新,导致线上升级失败。

(3)HTTP/2

HTTP/2 的定义为:

(超文本传输协议第 2 版,最初命名为HTTP 2.0),简称为h2(基于 TLS/1.2 或以上版本的加密连接)或h2c(非加密连接)[1],是HTTP协议的的第二个主要版本,使用于万维网

将 HTTP 消息分解为独立的帧,交错发送,然后在另一端重新组装是 HTTP 2 最重要的一项增强。事实上,这个机制会在整个网络技术栈中引发一系列连锁反应,从而带来巨大的性能提升:

HTTP2.0开启方式如下:

server {  
 listen        443 **ssl** **http2**;  
  server_name   yourdomain;
  ……  
  ssl          on**;
  …… 
}

开启 HTTP 2监听:

listen 443 ssl http2;

多路复用代替原有的序列以及阻塞机制,使得多个资源可以在一个连接中并行下载,不受浏览器同一域名资源请求限制,提升整站的资源加载速度。

2、资源优化##

(1)图片懒加载

图片懒加载是一种很好的优化网页或应用的方式,它能够在用户滚动页面时自动获取更多的数据,新获取的图片不会影响到页面呈现,同时视口外的图片有可能永远不需要被加载,能够极大的节约用户流量以及服务器资源。

懒加载的一般形式表现为:

  1. 打开首页,滑动页面
  2. 懒加载图片展示默认图
  3. 默认图替换为真实图片

(2)图片压缩

在移动端环境下,图片加载一直是需要重点优化的关键项,所以才延伸出懒加载这种交互方案来提高用户体验。

当该方案优化到了落地后,我们下一步考虑如何在保证图片质量的前提下,尽量压缩图片体积,提升图片加载效率。

WebP 是 Google 推出的一种同时提供了有损压缩与无损压缩(可逆压缩)的图片文件格式。相比于其他相同大小不同格式的压缩图像,WebP 格式的图片拥有更小的体积以及更高的质量,所以它的优势十分明显。

WebP 是 Google 推出的一种同时提供了有损压缩与无损压缩(可逆压缩)的图片文件格式。相比于其他相同大小不同格式的压缩图像,WebP 格式的图片拥有更小的体积以及更高的质量,所以它的优势十分明显。

在使用 WebP 进行有损压缩后,我们大概可以将原本的图片大小压缩至原来的十分之一左右,而图片质量却没有大的损失。这确实是一个惊人的效率。

我们可以看下一组数据来看下 webp 有损压缩效果:

Webp 有损压缩(75%质量比)

await execFileSync(cwebp, ['-q', '75', filePath, '-o', webpPath]);

将原图片和转换后的webp图片都上传到cdn上,做一个备份的能力,实际业务场景可以根据需求去选择是否使用 Webp 图片。

下图展示 Webp 压缩前后效果,右侧展示压缩后图片,图片大小从215k减小至17k。

(3)跨域避免 option 请求

*关于为什么会发起options请求,可以看博客的options的文章

前后端分离方案,服务器域名和专题域名不一致,会受到浏览器同源策略影响。

我们发现数据主接口会发起两次,其中第一个请求为预检请求。

一般来说使用 application/json 的 post 请求是必然会带入 OPTION 请求,何为 OPTION 预检:

用于获取目的资源所支持的通信选项。客户端可以对特定的 URL 使用 OPTIONS 方法,也可以对整站(通过将 URL 设置为“*”)使用该方法。

CORS中,可以使用 OPTIONS 方法发起一个预检请求,以检测实际请求是否可以被服务器所接受。预检请求报文中的Access-Control-Request-Method首部字段告知服务器实际请求所使用的 HTTP 方法;Access-Control-Request-Headers首部字段告知服务器实际请求所携带的自定义首部字段。服务器基于从预检请求获得的信息来判断,是否接受接下来的实际请求。

有趣的是专题详情为 GET 接口,为何 GET 请求也会发起 option 预检?

这个原因得从简单请求和复杂请求说起,跨域请求分为简单和复杂两种:

简单请求:

请求方式为如下之一:

HEAD

GET

POST

HTTP 请求头只能包含如下信息:

Accept

Accept-Language 

Content-Language 

Last-Event-ID 

Content-Type,但仅能是下列之一 

application/x-www-form-urlencoded 

multipart/form-data 

text/plain

任何一个不满足上述要求的请求,即被认为是复杂请求。一个复杂请求不仅有包含通信内容的请求,同时也包含预检信息。

专题配置接口请求头中带有自定义 header,浏览器会认定为非简单请求,需要向服务器发出检查,判断该域名是否允许跨域。

经过分析发现,自定义 header 其实在此业务场景中非必传自带,发出预检请求至少会有 100ms 的耗时,无形中延长页面绘制时间。

最终解决方案:去除自定义header,修改为简单请求,避免该请求发出预检。

3、渲染执行优化##

在网络层以及资源压缩优化落地后,接下来探索浏览器渲染执行优化点,涉及到浏览器,一定会联想到网页解析过程,下图清晰的展示静态资源如何通过浏览器最终显示:

当dom元素变化会导致浏览器重新执行渲染树生成、绘制,我们称之为重排重绘。

什么是重排?当 render tree 中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为重排(回流)。每个页面至少需要一次回流,就是在页面第一次加载的时候。

(1)避免重排
浏览器结构示意图:

可以看到浏览器有负责解析、渲染请求内容的渲染引擎,哪些动作会导致浏览器重排:

(1)增加或删除 DOM 节点;
(2)display:none(重排并重绘); visibility:hidden(重绘);
(3)移动页面中的元素;
(4)改变元素尺寸(宽、高、内外边距、边框等);
(5)用户改变窗口大小,滚动页面等;
(6)页面初始渲染;
(7)改变元素内容(文本或图片等)。

offsetTop, offsetLeft,...
scrollTop, scrollLeft, ...
clientTop, clientLeft, ...
getComputedStyle() (currentStyle in IE)

这些属性都需要实时回馈给用户的几何属性或者是布局属性,浏览器不得不立即执行渲染队列中的“待处理变化”,并随之触发重排返回正确的值。

document.body.style.minWidth = '12OOpx'
document.body.style.overflow = 'hidden'
//获取某div的偏移量
document.querySelector('xxx').offsetTop

我们优化活动代码执行逻辑,将上述直接操作 dom 的操作修改为 class 样式操作,减少加载过程中重复的dom操作。

(2)善用 Vue 生命周期
善用 Vue 组件生命周期,在合适的 hook 去初始化数据,操作dom,能够大幅提升加载体验。

在mounted 阶段,浏览器已经完成 dom 与 css 规则树的 render,并完成 render tree布局,这时候再去发送数据请求,会拉长请求时间和渲染周期,所以建议在beforeCreate中执行,以此达到预渲染和请求的并行进行。

我们将活动初始化数据的动作放在 beforeCreate 阶段,并将对 dom 的操作和监听挂载在 mounted 中。

{
  beforeCreate(){
    fetch({
      url: topicUrl,
      params: {
        //...
      }
    }).then(res=>{
      //数据处理
      //...
    })
  },
  mounted() {
    // global listener
    window.addEventListener('xxx');
    // get dom element by refs
    this.$refs.xxx
    // get dom element use native api
    document.querySelector
  }
}

对浏览器来说,整个渲染流程尚未开始或者说准备开始,对 vue 来说,实例尚未被初始化,data observer 和 event/watcher 也还未被调用,这个时候请求页面初始化数据时机是比较成熟的。

(3)减少白屏时间
相比 Native 页面,H5 页面体验问题主要是:打开一个 H5 页面需要做一系列处理,会有一段白屏时间,体验糟糕。

白屏时间是指浏览器从响应用户输入网址地址,到浏览器开始显示内容的时间。

本次专题优化,我们采用如下方式去减少白屏时间:

  1. 骨架屏,html直接渲染过渡效果
  2. 改造第三方 JS 引入顺序
  3. 使用 SplitChunksPlugin 拆分公共代码;
  4. 使用动态 import,切分页面代码,减小首屏 JS 体积

其中改造骨架的方式是一种成本低,效果非常卓越的方式,更进阶的方式有服务端直出等。由于悟空活动专题有快,灵的特点,配置改变需实时生效,所以前期我们权衡方案利弊,采用骨架,直接渲染过渡效果的方案。

页面加载html后直接显示加载效果,在底版本andriod手机中,webwiew初始化过程会有一个高度切换过程,加载后出现Native的titleBar,导致过渡效果会产生位置移动场景。

为了解决该问题,我们使用css3动画来实现过渡效果延迟出现,避免与webview初始化冲突。

animation: loading 1s linear 300ms infinite;
···
@keyframes loading{
  from {
    opacity: 1;
  }
  to {
    opacity: 1;
  }
}

这一现象能侧面反映出,loading出现基本于webview初始化同期进行,速度很快。为了解决loaidng瞬移的问题,我们采用纯css3实现loading延迟出现,不与webview初始化冲突。

无以生计,卖文苟延

微信
支付宝