web前端性能优化方案

web前端性能优化:让用户觉得网页加载贼快
根据用户按下回车键后的一系列事件,找出对应的优化方案
chrome的Audits

目的

让用户觉得网页加载贼快

实现原理

当用户输入完网址、按下回车键后

  1. 看本地有没有缓存
  2. DNS查询
  3. 建立tcp连接
  4. 发送请求
  5. 等待服务端处理,然后发送响应
  6. 接收响应
  7. 接收完成后得到HTML,逐行解析HTML
  8. 解析到css则下载css文件【多个css文件可以最多同时下载4个】
  9. 解析到js则下载js文件,js会阻塞HTML渲染

优化方案

css放在head里,js放在body最后

把CSS放在HTML头部是为了让浏览器尽早生成CSSOM,然后往下解析HTML的时候可以一次性生成最终的 RenderTree,渲染一次即可。如果把CSS放在底部,会出现渲染卡顿的现象,影响性能和体验。

由于js会阻塞渲染,因此把js放在底部,可以保证浏览器优先渲染完所有的HTML内容,让用户先看到内容,体验好。另外,JS中可能涉及到DOM的操作,得等到DOM解析完,才能获取DOM元素。

减少域名数量,降低DNS查询

假设baidu.com/index.html的css文件放在a.com/xxx.css,js文件放在b.com/xxx.js
那么DNS就会查询3次(分别查询baidu.com、a.com、b.com的DNS)
将所有文件放在1个域名下,这样就只有1次DNS查询了

DNS预解析

1
2
<meta http-equiv="x-dns-prefetch-control" content="on"> <!-- 强制打开a标签的DNS预解析 -->
<link rel="dns-prefetch" href="//img.alicdn.com">

tcp连接复用

在请求头加上keep-alive

http/2.0多路复用

发送请求时减小cookie

浏览器每次发送请求时都会带上cookie,所以减小cookie体积可以优化web性能

增加域名数量,从而增加资源下载的并发数

浏览器可以最多同时下载4个文件,假设有10个js文件,那么必须等前4个下载完,才能继续下载后面的js文件。
这时,如果将前4个js文件放在a.com,5~8放在b.com,9、10放在c.com,那么这10个js文件就能同时一起下载
!注意:当文件数量少时,减少域名数量,降低DNS查询;当文件数量很多时,增加域名数量,从而增加资源下载的并发数

压缩合并文件,减少HTTP请求

将多个css合并到1个css文件
将多个js合并到1个js文件

雪碧图

多个图片合并到一张图上

小图标用base64

压缩css、js、图片文件

利用浏览器缓存

浏览器缓存分为强缓存和协商缓存

  1. 浏览器在加载资源时,先根据这个资源的一些http header判断它是否命中强缓存,强缓存如果命中,浏览器直接从本地缓存中读取资源,不会发请求到服务器。比如某个css文件,如果浏览器在加载它所在的网页时,这个css文件命中了强缓存,浏览器就直接从缓存中加载这个css,连请求都不会发送到服务器;
  2. 当强缓存没有命中的时候,浏览器一定会发送一个请求到服务器,通过服务器端依据资源的另外一些http header验证这个资源是否命中协商缓存,如果协商缓存命中,服务器会返回304,但是不会下载这个资源,而是告诉客户端可以直接从缓存中加载这个资源,于是浏览器就又会从本地缓存中去加载这个资源;
  3. 强缓存与协商缓存的共同点是:如果命中,都是从本地缓存中加载资源,而不是从服务器加载资源数据;区别是:强缓存不发送请求到服务器,协商缓存会发送请求到服务器。
  4. 当协商缓存也没有命中的时候,浏览器直接从服务器加载资源数据。

强缓存

Expires 和 Cache-Control 都是强缓存。强缓存表示在缓存期间不发送请求,直接使用本地缓存

1
Expires: Wed, 22 Oct 2018 08:41:00 GMT

表示资源会在 Wed, 22 Oct 2018 08:41:00 GMT 后过期,需要再次请求。并且 Expires 属于绝对时间,如果手动修改了本地时间,可能会造成缓存失效。

1
Cache-control: max-age=300

表示资源会在 300 秒后过期,需要再次请求。属于相对时间,不受本地时间的影响。

同时存在时,听 Cache-control 的

协商缓存

如果缓存过期了,我们就可以使用协商缓存来解决问题。
协商缓存会向服务端发送http请求,询问是否继续使用本地缓存,如果要使用本地缓存,则服务端返回304状态码。

Last-Modified 和 If-Modified-Since

Last-Modified 表示文件最后修改日期
第一次访问后端,后端返回文件和Last-Modified(假设2018-01-01);再次访问后端时,请求头的If-Modified-Since会把Last-Modified的值给带上,后端接收到该值后,与服务器上的文件进行比较,如果服务器上的文件最后修改日期是2018-01-01,那就说明文件没有修改过,只返回304,不返回文件;如果服务器上的文件最后修改日期是2018-02-01,说明文件有更新,于是返回新的文件和Last-Modified值
但是如果在本地打开缓存文件,就会造成 Last-Modified 被修改【此时最后修改时间改变,但是文件本身没有做修改,造成重新下载资源】,所以在 HTTP / 1.1 出现了 ETag 。

ETag 和 If-None-Match

假设1分钟前请求了a.css,服务器下发了一个Etag是xxxxx;当浏览器再次请求a.css时,请求头中的 If-None-Match 会将这个 ETag值 发送给服务器,后端比较该资源 ETag 是否相同,两端的Etag值不同的话说明文件有更新,则发送新的资源和Etag。如果服务器发现该资源的Etag没有变动,那么只发送响应304(not modified),而不会下载这个css文件
ETag 优先级比 Last-Modified 高。

!注意:Etag会发送请求,返回304,不下载文件;Cache-Control直接不发送请求

开启Gzip压缩

服务器用gzip压缩HTML、CSS、JS等各种文件后,将压缩包发送给浏览器
浏览器接收到压缩包后,发现响应头是Content-Encoding:gzip,于是浏览器解压压缩包
!注意:浏览器解压压缩包会消耗浏览器cpu,所以体积较小的文件不需要gzip,体积较大的文件适用gzip

使用CDN

  1. CDN可以增加域名数量,从而增加请求的并发数,达到同时下载多个文件的目的
  2. 内容分发网络:将静态资源分发到全球各地,让不同地区的人都能快速访问距离你最近的那个服务器
  3. CDN没有cookie,因为cookie是发送给自己的服务器的

尽量使用css3动画代替js动画

使用transform:translate3d(0,0,0) 开启GPU加速

尽量使用translateX/Y代替left/top的移动

使用事件委托减少监听器

懒加载

1
<img id="img1" src="loading.png" data-lazy="真实图片地址">

首先展示loading图

当执行到尾部的js文件时,再将图片链接换成真实的图片地址

1
2
var img1 = document.getElementById('img1');
img1.src = img1.getAttribute('data-lazy');

预加载

减少DOM操作

  • 缓存DOM查询,在for循环中缓存元素的length
  • 合并DOM插入,利用文档片段【document.createDocumentFragment】

使用SSR后端渲染

直接返回渲染好的html文件,这样就不需要发送ajax请求获取数据了

节流

1
2
3
4
if(timer){
clearTimerout(timer);
}
timer = setTimeout(fn,1000);

chrome调试方法

chrome开发者工具 –> Audits –> Perform an audit –> run audit
运行完后会告诉你哪里需要进行优化

-------------本文结束感谢您的阅读-------------