Workers overview

本概述介绍了 Web Worker 和 Service Worker 如何提高网站的性能,以及何时使用 Web Worker 与 Service Worker。

本概述介绍了 Web Worker 和 Service Worker 如何提高网站的性能,以及何时使用 Web Worker 与 Service Worker。查看本系列的其余部分,了解窗口和 Service Worker 通信的特定模式。

Worker 如何改进您的网站

浏览器使用单线程(主线程)来运行网页中的所有 JavaScript,以及执行渲染页面和执行垃圾回收等任务。运行过多的 JavaScript 代码可能会阻塞主线程,从而延迟浏览器执行这些任务,并导致不良的用户体验。

在 iOS/Android 应用程序开发中,确保应用程序的主线程保持空闲以响应用户事件的常用模式是将操作卸载到其他线程。事实上,在最新版本的 Android 中,阻塞主线程时间过长会导致应用崩溃

在 Web 上,JavaScript 的设计围绕单线程的概念,并且缺乏实现应用程序拥有的多线程模型(如共享内存)所需的功能。

尽管存在这些限制,但通过使用 Worker 在后台线程中运行脚本,可以在 Web 中实现类似的模式,从而允许它们执行任务而不会干扰主线程。Worker 是在单独线程上运行的完整 JavaScript 作用域,没有任何共享内存。

在本文中,您将了解两种不同类型的 Worker(Web Worker 和 Service Worker)、它们的异同,以及在生产网站中使用它们的最常见模式。

Diagram showing two links between the Window object and a web worker and service worker.

Web Worker 和 Service Worker

相似之处

Web WorkerService Worker 是网站可用的两种类型的 Worker。它们有一些共同点:

  • 两者都在辅助线程中运行,允许 JavaScript 代码执行而不会阻塞主线程和用户界面。
  • 它们无权访问 WindowDocument 对象,因此它们无法直接与 DOM 交互,并且它们对浏览器 API 的访问权限有限。

不同之处

人们可能会认为,可以委托给 Web Worker 的大多数事情都可以在 Service Worker 中完成,反之亦然,但它们之间存在重要的差异:

  • 与 Web Worker 不同,Service Worker 允许您拦截网络请求(通过 fetch 事件)并在后台监听 Push API 事件(通过 push 事件)。
  • 一个页面可以生成多个 Web Worker,但单个 Service Worker 控制在其注册的作用域下的所有活动标签页。
  • Web Worker 的生命周期与其所属的标签页紧密相关,而 Service Worker 的生命周期则独立于它。因此,关闭运行 Web Worker 的标签页将终止它,而 Service Worker 可以在后台继续运行,即使该站点没有任何活动标签页打开。

用例

两种 Worker 之间的差异表明在哪些情况下可能需要使用其中一种:

Web Worker 的用例更常见地与将工作(如 繁重的计算)卸载到辅助线程有关,以避免阻塞 UI。

Diagram showing a link from the Window object to a web worker.
  • 示例: 构建视频游戏 PROXX 的团队希望尽可能使主线程保持空闲,以便处理用户输入和动画。为了实现这一目标,他们使用了 Web Worker 在单独的线程上运行游戏逻辑和状态维护。
A screenshot of the videogame PROXX.

Service Worker 任务通常更与充当网络代理、处理后台任务以及缓存和离线等事情有关。

A screenshot of the videogame PROXX.

示例:podcast PWA 中,可能希望允许用户下载完整的剧集以便在离线时收听。Service Worker,特别是 Background Fetch API 可以用于此目的。这样,如果用户在剧集下载时关闭标签页,则任务不必中断。

A screenshot of a Podcast PWA.
UI 已更新,以指示下载进度(左)。感谢 Service Worker,当所有标签页都已关闭时,操作可以继续运行(右)。

工具和库

窗口和 Worker 通信可以使用不同的较低级别 API 来实现。幸运的是,有一些库可以抽象化此过程,处理最常见的用例。在本节中,我们将介绍其中两个分别处理窗口到 Web Worker 和 Service Worker 的库:ComlinkWorkbox

A screenshot of the videogame PROXX.

Comlink 是一个小型 (1.6k) RPC 库,在构建使用 Web Worker 的网站时,它处理许多底层细节。它已在 PROXXSquoosh 等网站中使用。其动机和代码示例的摘要可以在此处找到。

Workbox

Workbox 是一个流行的库,用于构建使用 Service Worker 的网站。它围绕缓存、离线、后台同步等内容打包了一组最佳实践。workbox-window 模块提供了一种在 Service Worker 和页面之间交换消息的便捷方式。

后续步骤

本系列的其余部分重点介绍窗口和 Service Worker 通信的模式:

  • 命令式缓存指南:从页面调用 Service Worker 以预先缓存资源(例如,在预取场景中)。
  • 广播更新:从 Service Worker 调用页面以告知重要更新(例如,网站的新版本可用)。
  • 双向通信:将任务委托给 Service Worker(例如,大量下载),并让页面了解进度。

有关窗口和 Web Worker 通信的模式,请查看:使用 Web Worker 在浏览器主线程之外运行 JavaScript