在 Service Worker 中衡量性能

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

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

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

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

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 是在服务工件还未在工程师的眼中闪耀之前创建和实现的,因此上述代码无法了解服务工件对其有何影响。

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() 请求。

最后一点很重要。您可以将服务工件视为位于 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 应用中大部分性能逻辑的极具吸引力的方式。

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

我对讨论和规范感兴趣