本文目录
[[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: 矢量图片,支持动画、透明度、颜色- 适用场景: 支持放大缩小的场景,可以保证展示效果
- 不适用场景: 不规则线条场景不适用,会导致图片体积膨胀;存在图片嵌套场景慎用,体积很大。
优化加载速度
常见的优化手段如下:
- 图片压缩:
jpg:jpegtranpng:node-pngquant-nativegif:gifsicle
- 自适应图片大小: 可以通过 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 选择器精确获取
- 避免
eval、with - 对用户交互事件进行节流
- 列表事件进行事件委托
- JS 动画优化:
- 优先使用 CSS 动画或者 canvas 动画
- 使用
requestAnimationFrame进行即使更新 UI
- DOM 节点缓存:
- 通过虚拟列表模拟长列表,避免同时渲染大量 DOM
webpack 性能优化
浏览器加载机制
网络请求优化
- 减少 Cookie 存储的内容
- 更换 https 证书为 ECC 证书
- TLS 升级为 1.3 (支持 0-RTT 握手)
- 升级网络协议为 HTTP/2 、 HTTP3
- 使用 CDN 存放静态资源