5

改善页面性能 - 渲染与 JavaScript

 3 years ago
source link: https://zhuanlan.zhihu.com/p/59987039
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

改善页面性能 - 渲染与 JavaScript

为了提供给前端开发者监控页面性能的能力,W3C 定义了一系列相关 API,在这里统称为 Performance API。目前使用较多的应该是 PerformanceTiming,但是除了该 API,新的 W3C 草案及 WICG 提案定义了一系列 PerformanceEntry API,不仅取代了原 PerformanceTiming 的能力,并增加了更多维度的信息,本文主要针对这些 API 进行介绍。

前面的文章中我们简要介绍了 Performance 的能力,详细介绍了用于监控卡顿,响应延迟,资源加载性能的相关 API,并用实例展示了如何使用。本篇我们会介绍 Performance 的最后两个能力,首屏渲染相关的 Paint Timing API 以及 JavaScript 相关的 User Timing API。希望 Performance 系列能更好的帮助开发者去优化页面性能。

Paint Timing

Paint Timing 草案定义了 PerformancePaintTiming 接口,用来给前端开发者返回 first paint 和 first contentful paint 信息。

  • first paint

官方对 first paint 的定义为:

The time when the browser first rendered after navigation. This excludes the default background paint, but includes non-default background paint.

简而言之就是浏览器绘制的第一帧非背景内容。

  • first contentful paint

官方对 first contentful paint 的定义为:

The time when the browser first rendered any text, image (including background images), non-white canvas or SVG.

浏览器绘制的第一帧文本、图片等内容的时间,对于衡量用户实际浏览体验来说,比 first paint 更有实际意义。

interface PerformancePaintTiming : PerformanceEntry {};

PerformancePaintTiming 直接继承于 PerformanceEntry,并没有扩展新的字段,它的定义比较简单,主要关注 4 个字段:

  • name:有 2 种返回值,first-paint 和 first-contentful-paint
  • entryType:返回常量 "paint"
  • startTime:返回 first-paint 或者 first-contentful-paint 的时间,类型是 DOMHighResTimeStamp
  • duration:返回 0
var observer = new PerformanceObserver(function(list) {
  var perfEntries = list.getEntries();
  for(var i =0; i < perfEntries.length; i++) {
    // Process entries
    // report back for analytics and monitoring
	// ...
  }
});
// register observer for long task notifications
observer.observe({entryTypes:["paint"]});

我们在图 1 可以看到,除了 first paint,first contentful paint 外,还有个时间点是 first meaningful paint。官方对 first meaningful paint 的定义为:

The time when the browser first rendered the page’s primary content

浏览器绘制第一屏有意义的内容。这个时间点的计算非常复杂,大概原理是通过计算多次排版节点变化波峰,并结合 WebFont - 如果页面使用 WebFont - 的加载时间,计算得到 first meaningful paint。

目前,这个时间可以通过 tracing 工具或是 lighthouse 工具获取,暂时没有对应的 Performance API 接口。

User Timing

PerformanceMark 和 PerformanceMeasure 提供了一套 API 给用户,自定义地跟踪 JavaScript 脚本的性能。
Performance 扩展了 4 个相关的接口:

partial interface Performance {
  void mark(DOMString markName);
  void clearMarks(optional  DOMString markName);
  void measure(DOMString measureName, optional DOMString startMark, optional DOMString endMark);
  void clearMeasures(optional DOMString measureName);
};
  • 通过 Performance.mark 可以标记一个时间点,该时间点会记录到 PerformanceMark,通过在代码段前后调用 mark,则可以跟踪计算该代码段的执行时间
  • Performance.clearMarks 可以清除 mark 设置的标记,当指定参数时,可以清除指定标记;当无参数时,会清除所有 mark 标记
  • Performance.measure 保存了 2 个 mark 之间的时间间隔,当没有指定 start 和 end mark 标记时,会保存页面开始加载到当前的时间间隔;如果只指定 start mark,则保存最近一次 start mark 到当前的时间间隔;如果 start 和 end mark 全部指定,则保存最近一次 2 个 mark 之间的时间间隔
  • Performance.clearMeasures 跟 clearMarks 类似,但是用来清理 measure 的记录,不指定参数时,同样是清除所有

PerformanceMark 和 PerformanceMeasure 的接口定义跟 PerformanceEntry 一致,并无新的扩展属性,主要是几个时间点记录,并无特殊:

interface PerformanceMark : PerformanceEntry {};
interface PerformanceMeasure : PerformanceEntry {};
<!doctype html>
<html>
<head><title>User Timing example</title></head>
<body onload="init()">
  <script>
  function init() {
    performance.mark("startTask1");
	doTask1(); // Some developer code
	performance.mark("endTask1");
	
	performance.mark("startTask2");
	doTask2(); // Some developer code
	performance.mark("endTask2");
	
	measurePerf();
  }
  function measurePerf() {
    var perfEntries = performance.getEntriesByType("mark");
	for (var i = 0; i < perfEntries.length; i++) {
	  if (window.console) 
	    console.log("Name: "        + perfEntries[i].name      + 
                    " Entry Type: " + perfEntries[i].entryType +
                    " Start Time: " + perfEntries[i].startTime + 
                    " Duration: "   + perfEntries[i].duration  + "\n");
    }
  }
  </script>
</body></html>

Performance 系列将 W3C 中定义的相关 API 介绍完毕,个人的感觉是这些 API 比较适合有经验的,知识体系完备的开发者者使用。工具有了,如何使用,如何通过工具收集有意义的数据,收集到数据后如何进行优化,这些问题都需要开发者思考。

U4 内核团队正在完善自己的性能检测工具。该工具致力于 Web 业务的性能分析,并提供相应的性能优化策略。这些优化策略来自内核团队与集团内业务方大量成功案例的积累与沉淀。敬请关注。




About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK