(十三) 性能优化CRP

一. 什么是CRP

前端性能优化核心处理思想: CRP

CRP: Critical Rendering Path, 关键路径渲染, 就是了解浏览器渲染的每个环节, 然后针对每个环节进行优化

因此可以通过分析我们输入url并敲回车以后发生的具体细节来进行优化

二. 分析url访问过程来看性能优化

1. URL解析

2. 缓存检查

缓存机制是最简单的性能优化

浏览器会根据响应头先执行强缓存, 如果强缓存不生效 (不存在 / 过期) 再检查协商缓存

像html页面是无法使用强缓存进行缓存的, 因为服务器更新了某些资源后, 无法更新缓存下来的html页面, 但是可以使用协商缓存来缓存html页面, 至于为什么, 看完下面对于两者的解释答案自然了然于心

强缓存 Expires / Cache-Control 是服务端设置的, 浏览器会根据这两个响应头进行相应的强缓存处理

浏览器对于强缓存的处理: 是根据第一次请求资源时服务端返回的响应头来确定的

  • Expires: 缓存过期时间, 用来指定资源到期的时间 (HTTP 1.0)
  • Cache-Control: 例如: cache-control: max-age=2592000, 表示第一次请求到资源后的30天内, 再次发送请求, 会读取缓存中的信息 (HTTP 1.1)

Cache-Control的优先级高于Expire, 即: 如果服务端同时设置了这两个相应头, 会按照Cache-Control进行强缓存

Cache-Control可以设置的值:

  • public 表示响应可以被客户端和代理服务器缓存
  • private 表示响应只可以被客户端缓存
  • max-age=30 缓存30秒后过期,需要重新请求
  • s-maxage=30 覆盖max-age,作用一样,只在代理服务器中生效
  • no-store 不缓存任何响应
  • no-cache 资源被缓存,但是立即失效,下次会发起请求验证资源是否过期
  • max-stale=30 30秒内,即使缓存过期,也使用该缓存
  • min-fresh=30 希望在30秒内获取最新的响应

协商缓存 Last-Modified / ETag

协商缓存就是当强制缓存失效后, 浏览器携带协商缓存的缓存标识向服务器发起请求, 由服务器根据缓存标识决定时候使用缓存

  • ETag的内容是服务端最后更新资源所生成的标识

  • Last-Modified的内容是服务端最后更新资源的时间, 该时间精确到 秒

协商缓存每次都需要向服务器发送携带标识的请求, 来让服务器判断文件是否更新, 再决定是返回新资源还是直接读取缓存

Last-Modified 相比与 ETag有一个问题: Last_Modified的精确时间到秒, 如果客户端在使用协商缓存完成渲染的1秒内再次向服务器发送请求, 而服务器又恰巧在这1秒内更新的某个资源, 此时会判断最后更新时间是相同的, 并不会返回最新的资源

数据缓存 后端设置的, 用的比较多的是:

  • localStorage: 本地持久存储
  • sessionStorage: 回话存储
  • vuex等路由保持

3. DNS解析

通过DNS服务器将域名解析成服务器的ip地址 (这个过程还有其他判断)

假如没有缓存或缓存失效, 则会进行DNS解析, 一次DNS解析大概在20ms-120ms

DNS方面的优化: DNS预解析

  • 在页面头部加入,这样浏览器对整个页面进行预解析

    <meta http-equiv="x-dns-prefetch-control" content="on" />
    
  • 通过 link 标签手动添加要解析的域名,比如:

  • <link rel="dns-prefetch" href="//img10.360buyimg.com" />
    

4. TCP三次握手

三次握手建立连接进行可靠传输

5. 传输数据

主要的优化就在这个环节

  • 减少HTTP请求次数和大小
    • 资源文件合并处理压缩 (可以利用像webpack等工具)
    • 服务端开启GZIP压缩HTTP响应包 (一般可压缩60%)
    • 对大批量数据进行分批次请求 (例如: 下拉刷新或分页等等)
    • 等等
  • 图片资源的优化
    • 字体图标 或 SVG
    • 精灵图
    • 图片的base64
    • 图片懒加载
    • 等等

6. TCP四次挥手

HTTP1.1以及以后版本, 默认添加了 Connection: keep-alive这条规则, 即在第一次握手结束后, 通信通道不会立即关闭, 而是会保持一段时间, 以避免多次建立连接

7. 浏览器解析资源

浏览器通过解析HTML,生成DOM树,解析CSS,生成CSS规则树,然后通过DOM树和CSS规则树生成渲染树。渲染树与DOM树不同,渲染树中并没有head、display为none等不必显示的节点。

在解析CSS的同时,可以继续加载解析HTML,但在解析执行JS脚本时,会停止解析后续HTML,这就会出现阻塞问题

8. 页面渲染

优化方案

  • 标签语义化和避免深层次嵌套
  • css选择器渲染是从右到左
  • 尽早尽快的把css下载到客户端
    • 将style link等引入放在顶部
  • 避免阻塞的js加载
    • 将js引入放在底部
    • 使用异步请求, 如async等

DOM层面的核心优化

1. 减少重排和重绘

重排一定会触发重绘, 反之则不一定

  • 重排: 元素的大小或位置发生了变化 (当页面布局和几何信息发生变化的时候), 触发了重新布局, 导致渲染树重新计算布局, 如 添加或删除可见的DOM元素、元素尺寸发生变化、内容发生变化、窗口尺寸发生变化...
  • 重绘: 元素样式的改变 (宽高、大小、位置等不变), 如: color、background-color、border...

具体做法:

  • 放弃直接对DOM的操作, 使用像vue、react等框架
  • 读写分离
  • 动画运用到脱离文档流的元素上
  • 开启css3硬件加速、修改样式基于transform等
  • ...

2. 使用事件委托

3. 使用防抖和节流函数

4. requestAnimationFrame 和 cancelAnimationFrame

requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率。在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量
orequestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话动画会自动暂停,有效节省了CPU开销

三. 性能优化总结

1. 使用缓存

2. DNS预解析

3. 减少HTTP请求次数和大小

4. 图片资源的优化

5. CDN加速

6. 服务端开启GZIP压缩HTTP响应包

7. css样式放在顶部, js脚本放在底部

8. 优化JS代码

posted @ 2021-07-28 00:06  只猫  阅读(183)  评论(0编辑  收藏  举报