{T}

性能优化概述

前端性能优化是提升用户体验的关键,良好的性能能提高用户留存率和转化率。但性能优化工作往往琐碎繁杂,需要建立体系化的思维:从指标设定、指标采集、到监控预警和优化手段,形成完整闭环。

一、性能优化体系

性能优化可以系统化为一个完整体系,它包含三大部分:

code
┌───────────────────────────────────────────────────────────┐
│                    前端性能优化体系                          │
├───────────────────┬───────────────────┬───────────────────┤
│  ① 性能优化流程    │  ② 指标采集与上报   │  ③ 监控预警平台     │
│  · 指标设定        │  · 指标采集        │  · 数据处理后台     │
│  · 标准确定        │  · SDK 封装        │  · 可视化前台       │
│  · 收益评估        │  · 上报策略        │  · 监控预警         │
│  · 诊断清单        │  · 脏数据过滤      │                    │
│  · 优化手段        │                   │                    │
│  · 性能立项        │                   │                    │
│  · 性能实践        │                   │                    │
└───────────────────┴───────────────────┴───────────────────┘
  • 性能优化流程:设定指标 → 确定标准 → 收益评估 → 诊断清单 → 优化手段 → 性能立项 → 性能实践。其中「性能立项」很重要,它是赢得产品经理、后端同事支持、让优化顺利落地的前提。
  • 指标采集与上报:把性能指标以代码形式落地,封装成 SDK,制定上报策略,并过滤掉明显异常的「脏数据」。
  • 监控预警平台:分析上报数据、对比性能标准进行监控,超过阈值时通过邮件或短信预警。包含数据处理后台(预处理、清洗、计算)和可视化前台(展示、监控、预警)。

二、核心性能指标

1. 指标选择原则

要确定关键性能指标,必须满足两点:

  • 可衡量:能通过代码度量,无法衡量就无法优化。
  • 关注以用户为中心的关键结果和真实体验:关键结果是用户真正关心的内容(如电商的商品描述、头图、价格、购买按钮);真实体验是用户使用产品的实际感受。

基于此,性能指标聚焦三个方向:加载、交互性、视觉稳定性

2. Web Vitals 核心指标

Google 提出的核心 Web 指标,用于衡量用户体验:

指标全称维度良好值
LCPLargest Contentful Paint加载性能≤ 2.5s
INP/FIDInteraction to Next Paint / First Input Delay交互性能≤ 200ms / 100ms
CLSCumulative Layout Shift视觉稳定性≤ 0.1

**LCP(最大内容绘制)**衡量页面主要内容加载速度:

评级时间
良好≤ 2.5s
需改进2.5s - 4.0s
较差> 4.0s

影响 LCP 的因素:服务端响应慢、JavaScript 和 CSS 阻塞渲染、资源加载慢、图片没有预设尺寸、动态插入内容、字体加载导致布局变化。

**CLS(累积布局偏移)**指页面从一帧切换到另一帧时,视口中不稳定元素的偏移情况。CLS 影响用户体验(如点击时页面元素移动导致误点),可通过预设图片尺寸、为动态内容预留空间、使用 aspect-ratio、优化字体加载(font-display: swap)来改善。

3. 加载性能关键指标

业界目前主要关注白屏时间和首屏时间,它们是直接影响用户体验且衡量标准已达成共识的指标。

白屏时间:从输入内容回车(包括刷新、跳转)后,到页面开始出现第一个字符的时间。过程包括 DNS 查询、TCP 连接、发送首个 HTTP 请求(HTTPS 含 TLS 验证)、返回 HTML、解析 Head。标准是 300ms

首屏时间 = 白屏时间 + 渲染时间。从输入地址并回车,到首屏内容渲染完毕的时间(不需要滚动页面)。

首屏时间可以进一步拆解为:白屏时间、数据接口响应时间、图片加载资源等,便于定位是接口问题还是渲染问题。

白屏/首屏时间过长的原因:DNS 查询慢、TCP 连接慢、服务器处理慢、未做 Gzip 压缩、缺乏本地离线化处理、下载/解析/渲染时长过长等。

4. 秒开率与分位值

首屏时间用平均值表示并不准确——网络环境差异大(2G/3G/4G/WiFi),平均值会被极端值拉高。因此常采用分位值统计

  • P50 / P90 / P99:把所有首屏时间排序后,取第 50 / 90 / 99 位的值。例如 P99 表示 99% 的用户首屏时间低于该值。
  • 秒开率:1 秒内打开页面的用户占比。这个概念最早来自阿里巴巴,后来被业界普遍采用,计算简单、易于理解。
code
秒开率 = 首屏时间 ≤ 1s 的用户数 / 总用户数

5. 页面加载时间线

页面加载涉及的关键时间戳(Navigation Timing):

code
navigationStart ← 导航开始
fetchStart      ← 开始获取文档
domainLookupStart/End ← DNS 查询
connectStart/End      ← TCP 连接
requestStart          ← 请求开始
responseStart         ← 响应开始
responseEnd           ← 响应结束
domLoading            ← DOM 开始解析
domInteractive        ← DOM 解析完成
domContentLoadedEvent ← DOMContentLoaded 触发
domComplete           ← DOM 解析完成
loadEventStart/End    ← load 事件

关键指标计算方式

指标计算方式说明
FPfirstPaint - navigationStart首次绘制时间
FCPfirstContentfulPaint - navigationStart首次内容绘制
TTFBresponseStart - navigationStart首字节时间
DOMContentLoadeddomContentLoadedEventEnd - navigationStartDOM 加载完成
LoadloadEventEnd - navigationStart页面完全加载

三、性能指标采集

指标是抓手,确定了指标和标准,才能有针对性地开展优化。指标采集有手动采集自动化采集两种方式。

手动采集(埋点)

通过埋点方式,在页面开始位置打 FMP.Start()、首屏结束位置打 FMP.End(),用差值获取首屏时间。

优点:兼容性强、去中心化(各业务负责自己的打点)、灵活。 缺点:与业务代码严重耦合、覆盖率不足、依赖人(打错或忘记打点导致结果不精确)。

自动化采集

引入一段通用代码做自动化采集,接入时只需必要的配置。

优点:独立性强、接入自动化、统计结果标准化。 缺点:个性化需求无法满足。

采集方式对比

维度手动采集自动化采集
接入成本高(业务代码耦合)低(引入通用代码)
灵活性
统计标准不统一(依赖人)统一
覆盖范围受业务排期影响全面

SPA 页面无法直接使用 DOMContentLoaded 采集首屏(DOMContentLoaded 触发时页面仍是空白),需使用 MutationObserver 采集,具体算法见性能监测工具

四、性能监控

性能监控包括采集、上报和平台展示三个环节。

1. Performance API

javascript
// 获取页面加载性能数据
function getPageTiming() {
  const timing = performance.timing;

  return {
    dns: timing.domainLookupEnd - timing.domainLookupStart,      // DNS 查询时间
    tcp: timing.connectEnd - timing.connectStart,                // TCP 连接时间
    request: timing.responseEnd - timing.requestStart,           // 请求响应时间
    ttfb: timing.responseStart - timing.requestStart,            // 首字节时间
    domParse: timing.domComplete - timing.domLoading,            // DOM 解析时间
  };
}

2. Performance Observer

javascript
// 监控长任务(>50ms)
const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log('长任务:', entry.duration, 'ms');
  }
});
observer.observe({ type: 'longtask', buffered: true });

3. Navigator Connection API

javascript
// 检测网络状态(网络环境是性能优化的盲区)
function checkNetworkStatus() {
  const connection = navigator.connection;
  if (connection) {
    return {
      effectiveType: connection.effectiveType,  // 4g, 3g, 2g, slow-2g
      downlink: connection.downlink,            // 下行速度 (Mbps)
      rtt: connection.rtt,                      // 往返时间 (ms)
      saveData: connection.saveData             // 省流模式
    };
  }
  return null;
}

4. 数据上报

javascript
// 使用 sendBeacon 上报(页面卸载时也能可靠发送)
function reportPerformance(data) {
  navigator.sendBeacon('/api/performance', JSON.stringify(data));
}

上报优化建议:优先使用 sendBeacon、合并多条指标为一次请求、对高流量页面采样上报(如 10%)、数据压缩、异步上报(requestIdleCallback)。

五、优化策略与方法论

优化流程闭环

code
┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│   性能监控    │────→│   问题定位    │────→│   优化实施    │
└──────────────┘     └──────────────┘     └──────────────┘
       ↑                                          │
       └──────────────────────────────────────────┘
                      效果验证

优化策略分类

分类策略影响指标
资源优化压缩、合并、懒加载LCP, FCP
网络优化CDN、缓存、HTTP/2TTFB, LCP
渲染优化减少重排、虚拟列表INP, TBT
代码优化代码分割、Tree ShakingFCP, TTI
内存优化避免泄漏、及时释放TTI

优化方法论

1. 先量化再优化:确立基线指标,明确优化目标(如 LCP 从 3.2s 降到 2.5s)。

2. 抓主要矛盾:遵循 80/20 法则,先解决影响最大的瓶颈,避免过度优化次要问题。

3. 优化要可度量:每次优化后重新测量验证效果。

4. 注意优化的副作用:优化是一把双刃剑,需权衡利弊。

优化手段收益潜在副作用
缓存策略减少请求、提升速度数据一致性问题
懒加载减少首屏资源延迟感知、交互等待
代码分割减小包体积增加请求次数
CDN 加速降低延迟缓存更新复杂度

不同场景优化策略

场景核心目标关键指标优化重点
首屏加载快速呈现LCP, FCP资源优化、SSR
交互响应流畅操作INP, TBTJS 执行优化
长列表渲染滚动流畅FPS虚拟列表、DOM 优化

六、参考资料

性能优化是一个持续的过程,需要建立监控、分析、优化的闭环机制。记住:没有测量就没有优化,没有目标就没有方向