加载中...
  • 前端性能揭秘阅读笔记 loading

    截屏

    1
    2
    Devtools提供了过程截屏的能力, 用户可以直观地看到页面的选过程
    切换至network面板, 点击setting按钮后勾选Capture screenshots, 这样在刷新页面的同时浏览器会自动吧关键帧的截屏保留下来

    vite build

    1
    2
    3
    4
    托管dist文件

    cd dist
    npx static-server -z

    performance API

    perfomance.now()

    1
    2
    3
    performance.now()
    精度精确到微秒
    获取的是把页面打开时间点作为基点的相对时间, 不依赖操作系统的时间

    度量首屏

    1
    2
    3
    4
    FP(first paint) 第一次绘制时间
    FCP(first contentful paint) 第一次绘制出DOM元素的时间
    FMP(first meaningful paint) 第一次有意义的绘制(主观) , 替代方案LCP
    TTI(time to interaction) 可交互时间

    度量流畅度的指标

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    FPS 每秒传输帧数, 达到60fps就会让用户感觉到非常流畅
    使用requestAnimationFrame
    FPS降低的根本原因是UI线程被阻塞, 而这种阻塞是由一些长时间未能完成的长任务导致的, 如长时间的js任务执行或代价高昂的浏览器重绘
    使用Long Task API 可以定位这些阻塞UI线程的长任务

    const oberver = new PerformanceObserver((list) => {
    const perfEntries = list.getEntries()
    for (let i = 0; i < perfEntries.length; i++) {
    // 处理长任务, 一般大于50ms会被统计
    }
    })
    oberver.observe({ entryTypes: ['longtask'], buffered: true })

    最佳实践 Core Web Vitals

    1
    2
    3
    4
    LCP: 首屏视图中最大的元素的渲染时间
    浏览器会持续探测页面中占用最大的元素, 这个元素可能会在加载过程中发生变化(如出现了占用体积更大的元素), 直到页面完全加载后, 才会把最终占用面积最大的元素的渲染时间定为LCP探测的元素
    LCP是按照元素的渲染完成时间测算的, 如果一个大的图片只是在面积上占用了最大的空间, 但是还没有加载好, 那么浏览器仍然会把当前的LCP元素指向另外一个较小但是已经渲染好的元素
    LCP的特点: 更贴近用户体验的首屏, 可以自动测算, 可以解释

    TTFB

    1
    指客户端从发起请求到接收到服务器响应的第一个字节的时间, 能够在前端比较客观的反应后端的耗时

    图片使用 base64 的优缺点

    1
    2
    3
    4
    5
    6
    7
    可以减少一个图片请求的开支

    缺点
    base64会导致图片的体积增大1/3左右
    HTML中内联的图片在多次请求之间无法复用缓存
    客户端解析base64是需要时间的

    WebPageTest

    1
    2
    3
    4
    5
    WebPageTest是常用的线上性能分析工具, 能对线上的页面进行性能分析, 生成的报告也非常丰富, 除了自身的分析报告, 还包括DevTools timeline, lighthouse报告, 视频对比等.

    https://www.webpagetest.org/

    Start Render: 开始渲染时间, 既非白屏时间

    RTT

    1
    2
    3
    4
    5
    Round-Trip Time 往返延迟
    指的是从发送端发送数据开始, 到发送端收到来自接收端的确认的时间, 即一来一回的时间, 一般来说, 这个时间由物理距离, 网络传输路径等决定

    在Ping的时候看到的time=xxms, 大致是1个RTT

    TCP 的连接

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    客户端向服务器发送SYN, 传输seq=X
    服务端向客户端发送ACK X+1, 表示收到, 客户端可以将X+1作为seq发送消息, 同时发送SYN, seq=Y, 把自己设置为established状态(可接受数据)
    客户端向服务器发送ACK Y+1, 表示收到, 服务器端可以将Y+1作为seq发送消息, 把自己设置为established

    客户端发送完ACK后就认为连接已经建立完毕(而不是等待服务器端收到这个ACK), 并开始传输应用层数据, 服务器收到这个ACK后才会开始把收到的数据交付给应用层

    http1/1/1 TCP建立连接的时间就是一个RTT
    htts 还需要加上SSL的时间

    优化: preconnect

    对称加密

    1
    2
    3
    4
    用同一个秘钥进行加密和解密

    优点是简单
    不安全, 服务器想要保证传输的数据安全, 就得先把密钥传输过来, 而发送密钥的过程本身是不安全的

    非对称加密

    1
    2
    3
    有一组密钥 分为公钥和私钥 私钥只能一人保管, 公钥可以公布给任何人

    非对称加密算法的加密和解密是用不同的密钥完成的, 也就是说, 私钥加密后的内容可以被公钥的持有者解密, 而公钥加密后的内容只有私钥的持有者能解密

    SSL/TSL 握手

    1
    2
    3
    4
    客户端校验服务器端的证书
    协商生成对称加密使用的密钥

    需要两个RTT

    HTTP/2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    就http/2而已, 其提高性能的主要手段有, 连接复用, 头部压缩和Server Push

    连接复用
    http/1.1 支持Keep-Alive
    Keep-Alive用来表示申请服务器端在响应后仍然保持连接. 服务器端可以控制保持连接的时间, 一般为15s, 其实这里复用的并不是http连接, 而是迭戈http请求复用tcp连接

    队头阻塞
    由于http请求-响应是一一对应的, 使用同一个连接发送多个http请求会产生队头阻塞问题, 即第二个请求需要等待第一个请求返回后才能发起

    http/2对此提出了更根本的解决方案, 即让http在单个TCP连接内可以发送多个请求, 并且可以乱序返回

    Server Push

    1
    2
    3
    4
    5
    6
    7
    8
    9
    服务端需要在响应html时返回一个PUSH_PROMISE帧, 同时把需要推送的内容的html一起返回给客户端, 当客户端试图加载css时, 可以根据PUSH_PROMISE帧的ID读取到对应的流

    Swever Push 无法有效的和本地缓存复用
    无法从第三方推送
    Server Push 无法从第三方服务器进行推送, 为了尽快发送内容而放弃了CDN在静态资源托管性能上的优势, 往往是得不偿失的

    折中方案
    用户通过Cookie去猜测

    http/3

    1
    2
    3
    4
    无论是http/1还是http/2, 都是基于TCP协议的, 这意味着有一些由TCP协议带来的问题很难得到解决

    http2的队头阻塞问题
    TCP是可靠传输协议, 虽然两个请求在http层面是乱序的, 但是如果前面的请求出现了丢包, 那么TCP协议必须等待重传的宝按照次序读取出来, 这就是http2的队头阻塞问题

    压缩和缓存

    1
    2
    3
    br压缩比gzip压缩的效果更显著, 但是也会增加服务器端处理耗时

    accept-encoding, content-encoding

    内存泄漏和性能

    1
    2
    3
    当页面中出现了比较严重的内存泄漏时, 会产出一下两个结果
    内存总是不够, 导致垃圾回收频繁被触发
    内存中存在大量对象, 导致垃圾回收算法本身执行得更加缓慢
    上一篇:
    现代js库开发
    下一篇:
    脚手架搭建
    本文目录
    本文目录