技术咨询、项目合作、广告投放、简历咨询、技术文档下载 点击这里 联系博主

# 前端性能优化度量

我们经常能看到大量介绍前端如何进行性能优化的文章。然而很多文章只介绍了如何优化性能,却未能给出一个可计算,可采集的性能量化标准。此文就简单介绍一下前端性能优化的度量方案。

首先来一张整个 web 请求加载的流程图,这些 api 都可以在performance.timing中获取

# 一、性能优化常用度量方法

说明 其中 lcptbtCLS将会在 2020 年发布 API.

# FP 和 FCP 度量方法

FPFCP 分别是页面首次绘制和首次内容绘制。

参考资料: w3c paint (opens new window)

  • 首次绘制包括了任何用户自定义的背景绘制,它是首先将像素绘制到屏幕的时刻。
  • 首次内容绘制是浏览器将第一个 DOM 渲染到屏幕的时间。该指标报告了浏览器首次呈现任何文本、图像、画布或者 SVG 的时间。
  • 这两个指标其实指示了我们通常所说的白屏时间
let perfomanceMetrics = {};
const observer = new PerformanceObserver(list => {
  for (const entry of list.getEntries()) {
    // `entry` is a PerformanceEntry instance.
    // `name` will be either 'first-paint' or 'first-contentful-paint'.
    const metricName = entry.name;
    const time = Math.round(entry.startTime + entry.duration);
    if (metricName === "first-paint") {
      perfomanceMetrics.fp = time;
    }
    if (metricName === "first-contentful-paint") {
      perfomanceMetrics.fcp = time;
    }
  }
});

// Start observing the entry types you care about.
observer.observe({ entryTypes: ["paint"] });

# FMP(首次有意义绘制) 度量方法【重点】

目前,大多数公司都使用 FMP作为指标来衡量首屏性能。但是在未来/2020 年 谷歌将会发布一个新的衡量方式LCP,也就是首屏页面最长加载时间作为首屏的度量。FMP 的时机其实是在整个页面绘制完成,但不一定能进行前端交互。

FMP(First meaningful paint and hero element timing)。因为很难有一个通用标准来指示所有的页面当前时刻的渲染达是否到了有用的程度,所以当前并没有制定标准。对于开发者,我们可以根据自己的页面来确定那一部分是最重要的,然后度量这部分渲染出的时间作为 FMP。

Google Time to First Meaningful Paint: a layout-based approach (opens new window)

chrome 提供的性能分析工具 Lighthouse 可以测量出页面的 FMP,在查阅了一些资料后,发现 Lighthouse 使用的算法是:页面绘制布局变化最大的那次绘制(根据 页面高度/屏幕高度 调节权重)

# TTI(可交互时间) 度量方式

TTI 标准定义文档 (opens new window)

TTI 主要是通过跟踪耗时较长的任务来确定,设置PerformanceObserver观察类型为 longtask 的条目, 然后可以根据耗时较长的条目的 startTime 和 duration,来大致确认页面处于 idle 的时间,从而确定 TTI 指标。 Google 希望将 TTI 指标标准化,并通过 PerformanceObserver 在浏览器中公开,但目前并不支持。 目前只能通过一个 polyfill,检测目前的 TTI,适用于所有支持 Long Tasks API 的浏览器。 该 polyfill 公开 getFirstConsistentlyInteractive() 方法,后者返回使用 TTI 值进行解析的 promise。

度量 TTI 主要使用谷歌的tti-polyfill (opens new window)

第一步:设置 PerformanceObserver,并指定监控类型为 longtask。

<script>
  !(function() {
    if ("PerformanceLongTaskTiming" in window) {
      var g = (window.__tti = { e: [] });
      g.o = new PerformanceObserver(function(l) {
        g.e = g.e.concat(l.getEntries());
      });
      g.o.observe({ entryTypes: ["longtask"] });
    }
  })();
</script>

第二步:引入 tti-polyfill.js(可通过 npm 包获取),获取到 tti 的值

import ttiPolyfill from "/images/gmtc/performance/path/to/tti-polyfill.js";

ttiPolyfill.getFirstConsistentlyInteractive(opts).then(tti => {
  // Use `tti` value in some way.
});

# Long Tasks 度量方式

如果有一个任务需要消耗特别长的时间,那么队列中的其他任务将被阻塞。同时,js 线程和 ui 渲染线程是互斥的,也就是说,如果 js 在执行,那么 ui 渲染就被阻塞了。此时,用户在使用时将会感受到卡顿和闪烁,这是当前 web 页面不好的用户体验的主要来源。

Lonag tasks API (opens new window) 认为一个任务如果超过了 50ms 那么可能是有问题的,它会将这些任务展示给应用开发者。选择 50ms 是因为这样才能满足 RAIL 模型 中用户响应要在 100ms 内的要求。

度量方式 Long Task的度量也是采用了tti-polyfill (opens new window)

const observer = new PerformanceObserver(list => {
  for (const entry of list.getEntries()) {
    // `entry` is a PerformanceEntry instance.
    console.log(entry.entryType);
    console.log(entry.startTime); // DOMHighResTimeStamp
    console.log(entry.duration); // DOMHighResTimeStamp
  }
});

// register observer for long task notifications
observer.observe({ entryTypes: ["longtask"] });

# 二、如何衡量总体性能?

  • 绝对平均法
  • 加权平均 法
  • 秒开率,分位法
  • 去值平均法,分位平均值
  • 散点图、数据分层

# 三、阿里前端性能优化特色方案

# 1、指导思想

  • 减少资源

    • 让资源变小

      • 各种压缩算法
      • API 优化
    • 下载时间变快

      • 利用 CDN 就近请求资源
      • 优化 TTFB
      • 动态加速
    • 打破时间窗口

      • 预加载下一页资源
      • 各种缓存方案
      • 首屏优化
  • 减少执行

    • 减少计算量

      • 代码质量提升
      • 用 SSR 代替 CSR
    • 调整时序

      • api 并行加载
      • 各种避免字眼阻塞渲染
      • 边缘流式计算方案

# 2、 边缘流式计算方案

# 边缘流式计算优化首跳性能

将页面动静分离,静态结构缓存在 CDN,动态内容由 CDN 向服务器获取

和传统的 CSR 有什么区别?

开始还是 CSR,将静态资源放在 CDN 边缘节点。需要 cdn 有边缘计算能力。

技术原理

  • 【1】用户发送请求
  • 【2】【3】【4】 CDN 上的 edge worker 返回页面接口并保持连接状态
  • 【7】【8】从服务器读原页面,在 edge woker 上包装为 js 代码,动态加载到 dom 结构中

# 同屏渲染解决二跳性能问题

技术原理

# 检测工具

参考

【未经作者允许禁止转载】 Last Updated: 2/4/2024, 6:06:40 AM