在 Service Worker 中衡量性能

除了担心自己的开发者技能会生疏之外,Jake Archibald 还强烈建议您通过智能使用服务工件来显著提升网站或应用的性能。如需了解详情,请观看视频。

如果您想按照 Jake 的建议“大幅缩短网页加载时间”,就必须了解服务工作器对网页请求有何影响。

Resource TimingUser Timing API 是许多网站 RUM(Real User Monitoring,即实际用户监控)基础架构的关键组成部分,因为它们可让您全面了解所有用户对您网站性能的看法(另一个用例是检测内容注入)。简而言之,除非您使用了 Service Worker 或 Web Worker,否则您可以通过该工具了解从您的网站发出的每个网络请求的几乎所有方面。

以下是一个快速示例,展示了如何使用此函数获取发送到非当前网域的所有请求的列表。

var getThirdPartyRequests = function() {
    var thirdPartyRequests = [];
    var requests = window.performance.getEntriesByType("resource");
    
    var currentHost = window.location.host

    for(var requestIdx = 0; requestIdx < requests.length; requestIdx++) {
    var request = requests[requestIdx];
    var url = new URL(request.name);
    var host = url.host;

    if(host != currentHost) {
        thirdPartyRequests.push(request);
    }
    }
    
    return thirdPartyRequests;
};

Resource Timing API 和 User Timing API 是在工程师们还未想到 Service Worker 之前创建和实现的,因此上述代码无法了解 Service Worker 对其有何影响。

Chrome 45(2015 年 7 月发布 Beta 版)最近进行了一系列更改,这些更改引入了一种机制,可让所有形式的 worker(Web worker 和 service worker)访问 Resource Timing API 和 User Timing API,从而让您能够随时了解所有用户的网络性能。

从服务工件访问性能指标

最大的变化是将 performance 对象添加到了 Worker 上下文(Web 和 ServiceWorker),现在,您可以了解在 Worker 上下文中发出的所有请求的性能时间,还可以设置自己的标记来衡量 JS 执行情况。如果您只能查看当前窗口的上下文中发生的情况,则会错过以下重要时间信息:

  • 在服务工作器的 oninstall 事件内发出的 fetch() 请求
  • 现在,您可以跟踪在 onpush 事件中缓存数据时发出的 fetch() 请求,以了解用户看到的性能。
  • 最后,由 onfetch 处理程序发出并被拦截的 fetch() 请求。

最后一点很重要。您可以将 Service Worker 视为位于 Web 界面和网络之间的代理。window 上的 performance 对象只能看到其调用的请求部分的耗时和信息,它不知道位于客户端和网络之间的服务工件,因此无法了解服务工件的具体影响。

如何使用此功能?

支持“离线优先”的典型服务工作线程会有一个安装步骤,用于下载并保存所有资源以供日后使用

例如,您可以使用此 API 记录和记录安装步骤的时间数据,以便根据真实的实际用户使用情况,做出一些关于如何提升安装效果的衡量决策。

self.addEventListener("install", function() {
    var urls = [
    '/',
    '/images/chrome-touch-icon-192x192.png',
    '/images/ic_add_24px.svg',
    '/images/side-nav-bg@2x.jpg',
    '/images/superfail.svg',
    '/scripts/voicememo-core.js',
    '/styles/voicememo-core.css',
    '/third_party/Recorderjs/recorder.js',
    '/third_party/Recorderjs/recorderWorker.js',
    '/third_party/Recorderjs/wavepcm.js',
    '/third_party/moment.min.js',
    '/favicon.ico',
    '/manifest.json'
    ];

    urls = urls.map(function(url) {
    return new Request(url, {credentials: 'include'});
    });

    event.waitUntil(
    caches
        .open(CACHE_NAME + '-v' + CACHE_VERSION)
        .then(function(cache) {
        // Fetch all the URL's and store in the cache
        return cache.addAll(urls);
        })
        .then(function () {
        // Analyze all the requests
        var requests = self.performance.getEntriesByType("resource");
        
        // Loop across all the requests and save the timing data.
        return;
        })
    );
});

目前,许多网站都使用 RUM 来了解大多数用户对其网站的体验。Google Analytics 等工具已在使用 Navigation Timing API 报告网站速度数据,但需要更新才能包含 Worker 上下文中的性能分析。

Navigation Timing API 是否会面向服务工件推出

目前,我们没有计划将 Navigation Timing API 添加到 Service Worker 上下文,因为 Service Worker 中没有传统导航。有趣的是,对于服务工作线程而言,服务工作线程控制的一组网页中的每一次导航都看起来像是资源提取。仅这一点就足以让 Service Worker 成为集中 Web 应用中大部分性能逻辑的极具吸引力的方式。

我可以查看具体有何变化吗?

我对讨论和规范感兴趣