ウェブ ワーカーと Service Worker を使用してサイトのパフォーマンスを向上させる方法と、Web Worker と Service Worker の使い分けについて説明します。
この概要では、ウェブ ワーカーと Service Worker がウェブサイトのパフォーマンスを向上させる方法と、Web Worker と Service Worker の使い分けについて説明します。ウィンドウと Service Worker の通信の特定のパターンについては、このシリーズの残りの部分をご覧ください。
ワーカーがウェブサイトを改善する方法
ブラウザは単一のスレッド(メインスレッド)を使用して、ウェブページ内のすべての JavaScript を実行するだけでなく、ページのレンダリングやガベージ コレクションの実行などのタスクも実行します。JavaScript コードを過度に実行するとメインスレッドがブロックされ、ブラウザによるこれらのタスクの実行が遅れ、ユーザー エクスペリエンスが低下する可能性があります。
iOS/Android アプリの開発では、アプリのメインスレッドがユーザー イベントに自由にアクセスできるようにする一般的なパターンは、追加のスレッドに操作をオフロードすることです。実際、最新バージョンの Android では、メインスレッドのブロックが長すぎるとアプリのクラッシュにつながります。
ウェブ上では、JavaScript はシングル スレッドのコンセプトに基づいて設計されており、共有メモリなどのアプリのようなマルチスレッド モデルを実装するために必要な機能がありません。
こうした制限はあるものの、ウェブでも同様のパターンを実現するには、ワーカーを使用してバックグラウンド スレッドでスクリプトを実行します。これにより、ワーカーはメインスレッドに干渉することなく、タスクを実行できます。ワーカーは JavaScript スコープ全体であり、共有メモリを伴わずに別のスレッドで実行されます。
この投稿では、2 種類のワーカー(ウェブ ワーカーと Service Worker)と、それらの類似点と相違点、本番ウェブサイトでこれらのワーカーを使用する一般的なパターンについて説明します。
ウェブワーカーとサービス ワーカー
類似点
ウェブワーカーとサービス ワーカーは、ウェブサイトで利用できる 2 種類のワーカーです。この 2 つの共通点は次のとおりです。
- どちらもセカンダリ スレッドで実行されるため、メインスレッドとユーザー インターフェースをブロックせずに JavaScript コードを実行できます。
- ユーザーは
Window
オブジェクトとDocument
オブジェクトにアクセスできないため、DOM を直接操作できず、ブラウザ API へのアクセスが制限されています。
相違点
ウェブ ワーカーに委任できるほとんどのことは、Service Worker でも実行できると考える方もいるかもしれませんが、両者には重要な違いがあります。
- ウェブワーカーとは異なり、Service Worker ではネットワーク リクエストを(
fetch
イベントで)インターセプトし、(push
イベントを介して)バックグラウンドで Push API イベントをリッスンできます。 - 1 つのページから複数のウェブワーカーを生成できますが、1 つの Service Worker が、その登録に使用されたスコープのアクティブなタブをすべて制御します。
- ウェブワーカーの存続期間は、それが属するタブと密接に結びついていますが、Service Worker のライフサイクルは独立しています。このため、ウェブ ワーカーが動作しているタブを閉じるとウェブ ワーカーは終了しますが、サイトでアクティブなタブが開いていなくても、Service Worker はバックグラウンドでの実行を継続できます。
使用例
両方のタイプのワーカーの違いから、どちらのワーカーを使用するかが決まっています。
ウェブワーカーのユースケースは、UI をブロックしないように、一般的には作業(負荷の高い計算など)をセカンダリ スレッドにオフロードすることに関連しています。
- 例: ビデオゲーム PROXX を作成しているチームが、ユーザー入力とアニメーションを処理するために、メインスレッドをできる限り無料にしたいと考えていました。そのために、ウェブワーカーを使用して、別のスレッドでゲームロジックと状態のメンテナンスを実行しました。
Service Worker のタスクは一般に、ネットワーク プロキシとしての動作、バックグラウンド タスクの処理、キャッシュ保存やオフライン処理などに関連しています。
例: ポッドキャスト PWA で、ユーザーがエピソード全編をダウンロードしてオフラインで聴けるようにできます。そのためには、Service Worker、特に Background Fetch API を使用できます。そうすることで、エピソードのダウンロード中にユーザーがタブを閉じても、タスクが中断されることはありません。
ツールとライブラリ
ウィンドウとワーカーの通信は、異なる下位レベルの API を使用して実装できます。幸いなことに、このプロセスを抽象化して最も一般的なユースケースに対応するライブラリがあります。このセクションでは、ウェブワーカーと Service Worker のウィンドウを処理する Comlink と Workbox の 2 つについて説明します。
Comlink
Comlink は、ウェブ ワーカーを使用するウェブサイトを構築する際に、基盤となる多くの詳細情報を処理する小さな(1.6k)RPC ライブラリです。PROXX や Squoosh などのウェブサイトで使用されています。その動機とコードサンプルの概要については、こちらをご覧ください。
Workbox
Workbox は、Service Worker を使用するウェブサイトを構築するための一般的なライブラリです。キャッシュ保存、オフライン、バックグラウンド同期などに関する一連のベスト プラクティスがパッケージ化されています。workbox-window
モジュールは、Service Worker とページの間でメッセージを交換するための便利な方法を提供します。
次のステップ
このシリーズの残りの部分では、ウィンドウと Service Worker の通信パターンに焦点を当てます。
- 命令型キャッシュ ガイド: ページから Service Worker を呼び出して、リソースを事前にキャッシュに保存します(プリフェッチのシナリオなど)。
- 更新情報のブロードキャスト: Service Worker からページを呼び出して、重要な更新(ウェブサイトの新しいバージョンが利用可能になったなど)を通知します。
- 双方向通信: タスクを Service Worker に委任し(大量のダウンロードなど)、進行状況をページに知らせます。
ウィンドウとウェブ ワーカーの通信パターンについては、ウェブ ワーカーを使用してブラウザのメインスレッドから JavaScript を実行するをご覧ください。