Service Worker 注册

确定 Service Worker 注册时间的最佳做法。

服务 工作器 有效加快对用户的重复访问的速度, 确保 Service Worker 在初始安装时不会降低 用户的首次访问体验

一般来说,延迟 Service Worker 注册 直到初始页面加载完毕之后, 尤其是使用网络连接速度较慢的移动设备的用户

通用注册样板

如果您曾阅读有关 Service Worker 的内容,那么您可能遇到过 样板文件的内容大致如下:

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js');
}

这有时可能会附带几个 console.log() 语句,或者 代码 检测之前 Service Worker 注册的更新,作为一种 告知用户要刷新页面但这些都只是细微的差别 只需编写标准的几行代码即可。

那么,navigator.serviceWorker.register 是否有任何细微差别?有没有 最佳做法是什么?不足为奇(考虑到本文并没有结束 ),这两个问题的答案都是“是的!”

用户的首次访问

让我们以用户首次访问 Web 应用为例。还没有 Service Worker 而且浏览器无法提前知道 最终安装的工作器。

作为开发者,您的首要任务应该是确保浏览器能够快速、 获取展示互动式广告所需的最低限度的关键资源集 页面。拖慢检索这些响应速度的任何资源都是 实现快速的互动体验

现在想象一下,在下载 浏览器决定启动后台线程或 进程(为简单起见,我们假定这是一个线程)。假设 使用的不是大型台式机,而是那些性能不佳的计算机 将全世界大多数人视为主要设备的手机。开启 这个额外的线程会加剧浏览器对 CPU 时间和内存的争用 花在呈现交互式网页上的费用。

空闲的后台线程不太可能有重大意义。但 如果该线程不处于空闲状态,而是决定也将启动 从网络下载资源?任何有关 CPU 或内存的问题 网络争用(即网络争用)应该占后, 适用于许多移动设备带宽非常宝贵,所以请不要 同时下载辅助资源,从而轻松管理关键资源

所有这些都是为了指明在启动新的 Service Worker 线程 而在后台缓存资源 则有助于您实现 用户在首次访问您的网页时所需的最短互动体验 网站。

改进样板

解决方案是通过选择何时调用 Service Worker 来控制 Service Worker 的启动。 navigator.serviceWorker.register()。简单的经验法则是 报名截止日期为 load event 会在 window 上触发,如下所示:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}

但启动 Service Worker 注册的合适时间也取决于 您可以获悉 Web 应用在加载后立即执行的操作。例如,Google I/O 大会 2016 版 Web 应用具有一个简短动画 然后再切换到主屏幕我们的团队 发现 在动画期间关闭 Service Worker 注册可能会导致卡顿 在低端移动设备上展示的广告我们不会给用户带来糟糕的体验 晚点 Service Worker 注册,直到动画播放完毕,此时浏览器处于最活跃状态 可能会有几秒空闲的时间

同样,如果您的 Web 应用使用的框架可在 请查找框架特有的事件,以便在 工作。

后续访问

到目前为止,我们一直关注首次访问体验, 重复访问您的网站时会出现延迟 Service Worker 注册吗? 虽然这可能会让一些人感到惊讶,但这应该不会有任何影响。

注册 Service Worker 后,它会经过 installactivate 生命周期 事件。 激活 Service Worker 后,它可以处理任意 Service Worker 的 fetch 事件 对网页应用的后续访问Service Worker 在之前 。 。如果现有 Service Worker 在 之前尚未运行, 那么就没有机会完成以下事件的fetch事件: 导航请求。

因此,如果有活动的 Service Worker,则您何时调用 navigator.serviceWorker.register(),或者事实上无论您是否调用它。 除非您更改 Service Worker 脚本的网址, navigator.serviceWorker.register()实际上是 在后续访问期间执行 no-op。时间 并不相关

尽早注册的原因

是否存在任何需要尽早注册 Service Worker 是否合理?我想到一个问题是,Service Worker clients.claim() 在首次访问期间控制页面,而 Service Worker 积极执行运行时 缓存 调用其 fetch 处理程序。在这种情况下 尽快激活 Service Worker 使用稍后可能用到的资源填充其运行时缓存。如果 您的 Web 应用就属于这个类别,那么您应退一步 确保 Service Worker 的 install 处理程序不会请求 与主页面的请求争用带宽的资源。

进行测试

模拟首次访问的一个好方法是在 Chrome 浏览器中打开您的网络应用 无痕模式 窗口, 并在 Chrome 的 开发者工具。以网页形式 您很可能会重新加载数十个 Web 应用的本地实例, 每天数十次。但是,在已有一定数量的 Service Worker 和完全填充的缓存,您将无法获得相同的体验 这也就很容易忽略潜在问题

下方这个示例说明了注册时间在 品牌。这两个屏幕截图是在访问示例时截取的 app 无痕模式会使用网络节流功能来模拟网速较慢的情况。

提前注册的网络流量。

上面的屏幕截图反映了修改示例时的网络流量 以执行 Service Worker 注册。您可以看到 预缓存请求(带有齿轮 图标 (源自 Service Worker 的 install 处理程序) 中间穿插显示对显示页面所需的其他资源的请求。

延迟注册的网络流量。

在上面的屏幕截图中,直到 Service Worker 注册 页面已经加载。您可以看到,预缓存请求在 确保已从网络获取资源, 带宽。此外,由于我们预缓存的部分项目已经 浏览器的 HTTP 缓存,即“大小”中具有 (from disk cache) 的项 列,我们可以填充 Service Worker 的缓存,而无需转到 。

如果您通过实际低端设备运行此类测试, 真实的移动网络您可以利用 Chrome 浏览器的远程调试功能, 功能 通过 USB 将 Android 手机连接到台式机,并确保 这些测试实际上反映了许多应用的真实体验 用户。

总结

总而言之,请确保用户能获得最佳的首次访问体验 应优先考虑将 Service Worker 注册延迟到 网页在初始访问期间加载了,这样就可以帮助确保这一点。您仍将获得 拥有使用 Service Worker 进行重复访问的所有好处。

确保延迟 Service Worker 初始 注册使用以下代码:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}