Web前端性能优化学习总结

概述

在同样的网络环境下,两个同样能满足你的需求的网站,一个“Duang”的一下就加载出来了,一个纠结了半天才出来,你会选择哪个?研究表明:用户最满意的打开网页时间是2-5秒,如果等待超过10秒,99%的用户会关闭这个网页。也许这样讲,各位还不会有太多感触,接下来我列举一组数据:Google网站访问速度每慢400ms就导致用户搜索请 求下降0.59%;Amazon每增加100ms网站延迟将导致收入下降1%;雅虎如果有400ms延迟会导致流量下降5-9%。网站的加载速度严重影响了用户体验,也决定了这个网站的生死存亡。

可能有人会说:网站的性能是后端工程师的事情,与前端并无多大关系。我只能说,too young too simple。事实上,只有10%~20%的最终用户响应时间是用在从Web服务器获取HTML文档并传送到浏览器的,那剩余的时间去哪儿了?来瞄一下性能黄金法则:

只有10%20%的最终用户响应时间花在了下载HTML文档上。其余的80%90%时间花在了下载页面中的所有组件上,并且随着前端应用的壮大,大部分逻辑是交给浏览器执行的,所以网页的性能问题尤为突出。下面总结几点提高网页性能的方法。

资源合并与压缩

  1. html压缩
  • 使用在线网站进行压缩
  • 使用nodejs、gulp提供的工具进行压缩
  • 后端模板引擎渲染压缩
  1. css压缩
  • 无效、重复代码进行删除
  • css语义合并
  1. js压缩
  • 无效字符的删除
  • 剔除注释以及日志调试代码
  • 代码语义化的缩减和优化
  • 代码保护(代码压缩混淆,降低可读性,有利于保护代码不被看懂或复制)
  1. 压缩工具
  • 在线手动压缩
  • gulp开发环境提供各类资源的压缩工具类
  • webpack开发环境提供对应loader、plugin等进行处理和压缩

图片相关的优化

png8/png24/png32之间的区别

  • png8 -- 256色(2^8) 支持透明--适用于颜色种类较少的png图片
  • png24 -- (2^24) 不支持透明
  • png32 -- (2^24) 支持透明--适用于颜色种类丰富的png图片

不同图片常用的业务场景

  • jpg有损压缩,压缩率高,不支行透明
  • png支持透明,浏览器兼容好
  • webp压缩程序更好,在ios webviewe有兼容性问题
  • svg矢量图,代码内嵌,相对较小,图片样式相对简单的场景

进行图片压缩

  • 针对真实图片情况,舍弃一些相对无关的色彩信息

css雪碧图

  • 优点:减少Http请求
  • 缺点:当雪碧图过大时,加载过慢,在雪碧图上的所有图片就会都没有加载出来

image inline

  • 把图片转成base64格式,然后内嵌在html中
  • 优点:减少http请求
  • 缺点:代码体量过大

使用矢量图

  • 使用svg进行矢量图绘制
  • 使用iconfont解决icon问题
  • 与jpg相比,更小,加载更快
  • 缺点:颜色比较单调,复杂的图片不适合使用矢量图

在安卓下使用webp

  • webp压缩率更高,大小更小,但是并不所有浏览器兼容

图片压缩网址

  • 图片压缩

css和js的装载与执行

html,css,js加载过程

输入网站,发起请求,服务器返回一段html,浏览器html解析器解析,从上到下生成dom树,在这个过程中,解析到相应的link,script等外部资源,然后由浏览器发起请求,加载到相应的资源并解析,生成对应的css树,css树和dom树结合,生成render tree,然后布局,重绘,形成html页面

html渲染过程中的一些特点

  • 顺序执行,并发加载(引入外部资源,并发加载)
  • 是否阻塞(css,js加载是否阻塞后续dom加载)

css阻塞

  • css head中阻塞页面的渲染
  • css阻塞js执行--js执行可能影响dom结构和css样式,执行前要求dom和css已经加载完成,有依赖关系
  • css不阻塞外部脚本的加载

js阻塞

  • 直接引入的js阻塞页面的渲染
  • js不阻塞资源的加载
  • js顺序执行,阻塞后续js逻辑执行

依赖关系

  • 页面渲染依赖于css加载
  • js的执行顺序的依赖关系
  • js逻辑对于dom节点的依赖关系

js引入方式

  • 直接引入--会阻塞页面加载
  • defer--不会阻塞dom渲染,dom渲染完成后,按照从上到下,同步执行
  • async--不会阻塞dom渲染,dom渲染完成后,异步加载执行,不存在依赖关系

懒加载与预加载

原理

  • 什么是懒加载:图片进入可视区域之后请求图片资源,如果网站图片很多,但是用户只看了几张就退出,后面的图片也没有必要加载,这时就是用到懒加载了,而且过多资源加载,会影响后面js的加载
    比如大部分网站常用的监听scoll整件,当图片进入可视区域后,图片开始加载
  • 什么是预加载:图片等静态资源使用前,提前加载,资源使用到时能从缓存中加载,提升用户体验

预加载的三种方法

1.直接在页面内通过img标签引入,默认隐藏
2.在js里文件new image对象,需要的时候直接引用
3.使用XMLHttpRequest对象加载图片,这个方法返回状态和回调函数,监听函数,更好控制整个过程,但是不同域名下的资源有跨域问题
4.使用preloadJS库

缓存优化

CDN缓存

CDN可以理解分布世界各地的节点,当用户浏览网站的时候,CDN会选择一个离用户最近的CDN边缘节点来响应用户的请求,这样在广州访问王者荣耀用户的请求就不会千里迢迢跑到北京的服务器(假设王者荣耀源站部署在北京)
CDN的优势很明显:
1.CDN解决了跨地域访问的问题,访问延时大大降低;
2.大部分请求在CDN边缘节点完成,CDN起了分流作用,减轻了源站的负载

//设置CDN边缘节点数据缓存时间
Cache-Control:max-age

当客户端向CDN节点请求数据时,CDN节点会判断缓存数据是否过期,若缓存数据并没有过期,则直接将缓存数据返回给客户端;否则,CDN节点会向源站发出请求,从源站获取最新数据,更新本地缓存,并将最新的数据返回给客户端。CDN服务商一般会提供基于文件后缀、目录多个维度来指定CDN缓存时间,为用户提供更精细化的缓存管理

DNS缓存

DNS(Domain Name System):解析域名找到IP地址服务器
DNS查找流程:首先查看浏览器缓存是否存在,不存在则访问本机DNS缓存;再不存在则访问远程DNS服务器,通常浏览器查找域名对应的IP地址需要花费20-120ms,在DNS查找完成之前,浏览器不能从host下载任何东西

  • DNS性能优化最佳实践
    当客户端的DNS缓存为空时,DNS查找的数量与配置的主机数量相等,所以减少配置主机可以减少DNS查找的数量。
    但是问题来了,有时候需要多设置主机数量,来增加DNS的负载均衡,因此减少DNS的查找和增加主机数量形成矛盾关系,建议配置2-4个主机是最佳的。更多负载均衡可以用nginx实现。

浏览器缓存

1.Cache-Control:max-age
假如站点引入一个脚本文件,希望20年不变,这时浏览器把这个脚本缓存起来,不用每一次都请求服务器。这样节省宽带并且提升性能;

//设置Response的HTTP头中Cache-Control
Cache-Control:max-age=31536000

因为标准规定最多只能设置一年。这里设置了一年的缓存,以秒为单位。
但是,有一天发现脚本的文件要改了怎么办?很简单,改变请求的文件名就好了。这时浏览器会向服务器请求这个文件。
2.Expires
指一个绝对过期日期,如果过期了,客户端向服务器获取最新资源;这个过期时间是参照客户端的时间,修改客户端的时间等同于更改缓存命中结果,推荐与Cache-Control一块使用

//设置Response的HTTP头中Expires
Response Headers
Expires:Sat,24 Jan 2018 20:30:47 GMT
...

3.Last-Modified 和 If-Modified-Since

1.客户端第一次向服务器发送请求获取JS文件
2.服务器接收请求后将JS文件返回给客户端,响应头里JS文件最后的修改时间Last-modified:Sat,24 Jan 2018 20:30:47 GMT
3.客户端第二次发起请求获取JS文件,在这里会把第2步返回的修改时间放在请求头里If-Modified-Since:Sat,24 Jan 2018 20:30:47 GMT发送给服务器
4.服务器进行校验,检查修改文件的时间;如果文件没有修改过,通知客户端是最新版本;反之,则返回最新的JS文件给客户端

//第一次发起请求,响应头返回的修改文件时间
Response Headers
Last-Modified:Sat,24 Jan 2018 20:30:47 GMT
//第二次发起请求,请求头发送给服务器的修改文件时间
Request Headers
If-Modified-Since:Sat,24 Jan 2018 20:30:47 GMT

4.ETag 和 If-None-Match
场景:客户端发起请求获取JS文件,JS文件的内容加一个空格然后删除空格进行保存操作;这时候服务器会校验JS文件最后的修改的时间,发现匹配不上,服务器会重新将文件返回给客户端。可是,这样合理么?JS文件内容并没有被修改?
ETag的出现了,完美处理上述情况

1.客户端第一次向服务器发送请求获取JS文件
2.服务器接收请求后将JS文件返回给客户端,响应头里ETag :W/"262b9-Lo40+3qjAODueOOX6ceeIg"
3.客户端第二次发起请求获取JS文件,请求头里 If-None-Match:W/"262b9-Lo40+3qjAODueOOX6ceeIg"发送给服务器
4.服务器进行校验,检查文件内容是否变化了(ETag的值:是依据文件内容的哈希值生成);如果文件内容没有改变过,通知客户端是最新版本;反之,则返回最新的JS文件给客户端

//第一次发起请求,响应头返回ETag
Response Headers
ETag:W/"262b9-Lo40+3qjAODueOOX6ceeIg"
//第二次发起请求,请求头发送ETag的值给服务器
Request Headers
If-None-Match:W/"262b9-Lo40+3qjAODueOOX6ceeIg"

浏览器存储

多种浏览器存储方式并存,如何选择?

cookie

因为HTTP请求无状态,所以需要cookie去维护客户端状态

  • cookie的生成方式
    http response header 中的set-cookie,当客户端接收到http response header 中的set-cookie信息时,会自动在客户端生成相应的cookie,客户端再次发起请求时,这些cookie信息将被携带在request header中带给服务端,服务端可以从这些信息中判断用户的相关信息--用于浏览器端和服务端的交互
    cookie属性httponly(服务端设置), 如果您在cookie中设置了HttpOnly属性,那么通过js脚本将无法读取到cookie信息,这样能有效的防止XSS攻击
  • js中可以通过document.cookie可以读写cookie--客户端自身存储信息

cookie存储的限制

  • 作为浏览器存储,大小4kb左右
  • 需在设置过期时间 expire
  • 浏览器存储尽量用localstorage

localstorage

  • HTML5设计出来专门用于浏览器存储
  • 大小为5M左右
  • 仅在客户端使用,不和服务端进行通信
  • 接口封闭较好,有专门的api进行设置删除操作
  • 浏览器本地缓存方案

sessionstorage

  • 会话级别的浏览器存储(浏览器关闭,sessionstorage删除)
  • 大小为5M左右
  • 仅在客户端使用,不和服务端进行通信
  • 接口封闭较好,有专门的api进行设置删除操作
  • 对于表单信息的维护

IndexedDB

-IndexedDB 就是浏览器提供的本地数据库,它可以被网页脚本创建和操作。IndexedDB 允许储存大量数据,提供查找接口,还能建立索引。这些都是 LocalStorage 所不具备的。就数据库类型而言,IndexedDB 不属于关系型数据库(不支持 SQL 查询语句),更接近 NoSQL 数据库。

  • service workers 产生的意义
  • 大规模,多线程运行js

PWA

Progressive Web App(渐进性网页应用,简称PWA)是全新的网页技术,让网站的离线体验变得更好,网络连接断断续续时体验也会更好, 它会模拟一些原生功能。在移动端利用标准化框架,让网页应用呈现和原生应用相似的体验。

你可能感兴趣的:(Web前端性能优化学习总结)