本文目录

[[toc]]

WEB 应用性能优化分析

一个 web 应用卡慢的原因,基本是以下两点:

  • 计算时间长: CPU 能力弱
  • 网络延迟: I/O 能力弱

所以,归根结底, web 应用性能优化就是在有限 CPU 计算能力,并且有限 I/O 的场景下,进行的计算优化、 I/O 优化等行为

计算优化

计算优化有两条思路:

  • 使用异步计算: 避免主线程假死,并通过可视化手段提示用户计算正在后台运行,比如 operation loading 、后台任务队列、消息回显等方案。
  • 减少计算量: 比如优化算法,降低时间复杂度;比如使用性能更高的 WASM 或者计算能力更强的 FaaS 进行计算

I/O 优化

从 I/O 的角度出发,就需要考虑网络 I/O 能力的优化,这是全链路的性能优化,大部分前端开发者的优化思路都集中在这部分。

一般入手点有以下几处:

  • 后端接口性能: 主要依赖于服务端监控上报,一般只有在 BFF 等场景下,前端需要关注,比如:
    • GraphQL 单接口的并发性能问题,这块优化需要考虑对 NodeJS 进行高可用部署,通过 Nginx 或者其他网关服务进行负载均衡,减少单 NodeJS 应用的负载。
    • NodeJS 单 CPU 工作时处理 CPU 密集型任务影响其他请求的响应,比如图表生成、大数据读写等,优化思路同上。
    • 网关处理大请求时的 I/O 性能问题,包括文件上传下载,以及部分需要传递大量参数的场景,这块主要优化点在于 Nginx 网关。
    • 考虑服务器的稳定与可用,避免由于单点崩溃导致整个集群雪崩。
  • 网络传输速度: 整体需要从网络传输链路考虑,包括 TCP/TLS 握手、 HTTP 协议版本的特点、 gzip/br 压缩、协商缓存、大文件 Range 传输等等
    • 协议层优化:
      • 优先使用 HTTP/3 , HTTP+TLS 握手仅 1 RTT ,并且传输无队头阻塞问题,支持 header 压缩、多路复用、移动端变更基站复用连接等等现代化能力
      • 其次考虑 HTTP/2 多路复用,在并发请求时不需要重复握手,并且支持 header 压缩、多路复用
      • 最后考虑 Nginx 开启会话缓存,一定时间内再次链接不握手
    • 传输过程优化:
      • 开启传输压缩: 优先使用 br ,其次是 gzip ,可以使用 Nginx ,会在请求时与客户端进行资源类型协商。
      • 如果使用 HTTP/1.1 或者更低版本的 HTTP 协议,需要考虑接口合并,减少同一时间的接口数,减少握手开销。
      • 减少资源体积: 通过非关键资源延迟加载、优先加载 MVP 资源、骨架屏等方案,提升用户体验
  • 缓存优化: 通过多级缓存减少服务端负载,也提升客户端加载速度,例如 CDN 、 Nginx 缓存等等,需要注意集中回源问题
    • 设立多级缓存,针对传输过程中的各个节点,都设置不同时间间隔的缓存
    • 热点资源回源时需要加锁,避免集中回源,将源站打挂
    • 优先使用过期缓存,在后续利用 idle 时间更新缓存( SWR )
  • 提前加载: 按照埋点数据或者用户画像,针对用户可能访问的资源在空闲时进行 preload / prefetch / modulepreload
    • preload 优先级较高,适合加载即将可能访问的资源
    • prefetch 优先级低,但是可以在页面关闭后保留线程继续加载
    • modulepreload 与 preload 相同,但是 RTT 会更少,一次性加载所有依赖 chunk 回来

图片优化

图片格式介绍

  • jpg: 有损压缩的视频格式,不支持透明度
    • 适用场景: 色彩丰富、彩图、 banner 图、结构不规则图形
    • 不适用场景: 线条图形、文字、图标
  • png: 无损压缩的位图图形,支持索引、灰度、 RGB 、透明度
    • 适用场景: 纯色、透明、线条图形、边缘清晰且大量颜色相同、需要半透明并且颜色较少
    • 不适用场景: 彩色图片不适用,体积会很大
  • gif: 只能支持完全透明或者完全不透明;颜色只有 8 位,一共 256 种。
    • 适用场景: 动画、图标
    • 不适用场景: 彩色图片
  • webp: 现代图片格式,支持无损压缩、有损压缩,体积较小,支持动画,支持透明度, 8 位颜色
    • 适用场景: 图形、半透明、动画
    • 不适用场景: 色彩丰富的图片不适用
  • svg: 矢量图片,支持动画、透明度、颜色
    • 适用场景: 支持放大缩小的场景,可以保证展示效果
    • 不适用场景: 不规则线条场景不适用,会导致图片体积膨胀;存在图片嵌套场景慎用,体积很大。

优化加载速度

常见的优化手段如下:

  • 图片压缩:
  • 自适应图片大小: 可以通过 query 参数从服务端获取不同尺寸大小的图片,通过分辨率裁剪可以加速小屏设备下的图片加载速度,也能避免大屏下图片模糊问题
  • 渐进式加载图片: 在初期使用 统一占位符 、 低质量图片矢量图占位 等占位,在后续逐步加载高质量图片替换
  • 小图片优化:
    • 通过 Data URI 内联,减少请求数
    • 通过雪碧图合并图片

HTML 性能优化

  • 减少 HTML 代码长度:
    • 减少 DOM 深度
    • 减少 DOM 节点数
    • 删除协议头( //:a.com 会根据现在网站的协议自动补全协议 )
    • 删除多余空格、缩进、注释
    • 同域名 url 使用相对路径
  • 考虑资源请求阻塞
    • 首屏需要的 CSS 与 JS 优先加载,其他内容通过 preload/prefetch 预加载
    • CSS 尽量放到 head 中, JS 通过 defer 延迟加载,参考 资源加载优先级
  • 通过 SSR 优先渲染首屏,减少回流

CSS 性能优化

  • CSS 渲染性能
    • 减少选择器层级数
    • 减少 CSS 表达式
    • 避免使用通配符、正则属性匹配等
    • 减少 @import
  • CSS 动画优化
    • 尽量使用 transform 属性进行位移,而不是直接修改几何属性,避免大面积回流
    • 对于不可避免需要对几何属性进行动画的情况,可以使用 will-change 通知浏览器

JS 性能优化

  • JS 执行性能优化:
    • 获取元素时使用 id 选择器精确获取
    • 避免 evalwith
    • 对用户交互事件进行节流
    • 列表事件进行事件委托
  • JS 动画优化:
    • 优先使用 CSS 动画或者 canvas 动画
    • 使用 requestAnimationFrame 进行即使更新 UI
  • DOM 节点缓存:
    • 通过虚拟列表模拟长列表,避免同时渲染大量 DOM

webpack 性能优化

浏览器加载机制

网络请求优化

  • 减少 Cookie 存储的内容
  • 更换 https 证书为 ECC 证书
  • TLS 升级为 1.3 (支持 0-RTT 握手)
  • 升级网络协议为 HTTP/2 、 HTTP3
  • 使用 CDN 存放静态资源