ワーカーの概要

ウェブ ワーカーとサービス ワーカーでサイトのパフォーマンスを改善する方法と、ウェブ ワーカーとサービス ワーカーの使い分け。

Andrew Guan
Andrew Guan
Demián Renzulli
Demián Renzulli

この概要では、ウェブ ワーカーとサービス ワーカーがウェブサイトのパフォーマンスをどのように改善するか、また、ウェブ ワーカーとサービス ワーカーのどちらをいつ使用するかについて説明します。ウィンドウとサービス ワーカーの通信の特定のパターンについては、このシリーズの残りの部分をご覧ください。

ワーカーがウェブサイトを改善する方法

ブラウザは、単一のスレッド(メインスレッド)を使用して、ウェブページのすべての JavaScript を実行するだけでなく、ページのレンダリングやガベージ コレクションなどのタスクも実行します。過剰な JavaScript コードを実行すると、メインスレッドがブロックされ、ブラウザがこれらのタスクを実行するのに遅延が生じ、ユーザー エクスペリエンスの低下につながる可能性があります。

iOS/Android アプリケーション開発では、アプリのメインスレッドがユーザー イベントに自由に応答できるようにするために、オペレーションを追加のスレッドにオフロードするという一般的なパターンがあります。実際、最新バージョンの Android では、メインスレッドを長時間ブロックするとアプリがクラッシュします

ウェブでは、JavaScript はシングル スレッドのコンセプトに基づいて設計されており、アプリが持つようなマルチスレッド モデルを実装するために必要な機能(共有メモリなど)がありません。

このような制限があるにもかかわらず、ウェブではワーカーを使用してバックグラウンド スレッドでスクリプトを実行することで、同様のパターンを実現できます。これにより、メインスレッドに干渉することなくタスクを実行できます。ワーカーは、共有メモリのない別のスレッドで実行される JavaScript スコープ全体です。

この記事では、2 種類のワーカー(ウェブ ワーカーとサービス ワーカー)について、その類似点と相違点、本番環境のウェブサイトでワーカーを使用する最も一般的なパターンについて説明します。

Window オブジェクトとウェブ ワーカー、サービス ワーカーの間の 2 つのリンクを示す図。

ウェブワーカーとサービス ワーカー

類似点

ウェブ ワーカーサービス ワーカーは、ウェブサイトで利用できる 2 種類のワーカーです。共通点は次のとおりです。

  • どちらもセカンダリ スレッドで実行されるため、JavaScript コードはメインスレッドとユーザー インターフェースをブロックすることなく実行できます。
  • Window オブジェクトと Document オブジェクトにアクセスできないため、DOM を直接操作することはできず、ブラウザ API へのアクセスも制限されます。

相違点

ウェブ ワーカーに委任できるほとんどのことはサービス ワーカーでも実行でき、その逆も可能だと考えるかもしれませんが、両者には重要な違いがあります。

  • ウェブ ワーカーとは異なり、サービス ワーカーでは、ネットワーク リクエストをインターセプト(fetch イベント経由)したり、Push API イベントをバックグラウンドでリッスン(push イベント経由)したりできます。
  • 1 つのページで複数のウェブ ワーカーを生成できますが、1 つのサービス ワーカーが、登録されたスコープ内のすべてのアクティブなタブを制御します。
  • ウェブ ワーカーの存続期間は、それが属するタブに密接に関連付けられていますが、サービス ワーカーのライフサイクルはそれとは独立しています。そのため、ウェブ ワーカーが実行されているタブを閉じるとウェブ ワーカーは終了しますが、サービス ワーカーはサイトにアクティブなタブが開いていない場合でも、バックグラウンドで実行を継続できます。

ユースケース

両方のタイプのワーカーの違いから、どちらを使用する状況が考えられます。

ウェブ ワーカーのユースケースは、UI のブロックを回避するために、重い計算などの作業をセカンダリ スレッドにオフロードすることに関連していることが一般的です。

Window オブジェクトからウェブ ワーカーへのリンクを示す図。
  • 例: ビデオゲーム PROXX を作成したチームは、ユーザー入力とアニメーションを処理するために、メインスレッドをできるだけ空けておきたいと考えていました。これを実現するために、ウェブ ワーカーを使用して、ゲームのロジックと状態のメンテナンスを別のスレッドで実行しました。
ビデオゲーム「PROXX」のスクリーンショット。

サービス ワーカー タスクは、一般的にネットワーク プロキシとしての動作、バックグラウンド タスクの処理、キャッシュ保存やオフラインなどの処理に関連しています。

ビデオゲーム「PROXX」のスクリーンショット。

例: ポッドキャスト PWA では、ユーザーがエピソード全体をダウンロードしてオフラインで聴けるようにしたい場合があります。サービス ワーカー、特に Background Fetch API を使用して、その目的を達成できます。これにより、エピソードのダウンロード中にユーザーがタブを閉じても、タスクを中断する必要がなくなります。

ポッドキャスト PWA のスクリーンショット。
UI が更新され、ダウンロードの進行状況が表示されます(左)。サービス ワーカーのおかげで、すべてのタブが閉じられた後もオペレーションを継続できます(右)。

ツールとライブラリ

ウィンドウとワーカーの通信は、さまざまな下位レベルの API を使用して実装できます。幸いなことに、このプロセスを抽象化し、最も一般的なユースケースを処理するライブラリがあります。このセクションでは、ウィンドウからウェブ ワーカーとサービス ワーカーをそれぞれ処理する 2 つのライブラリ、ComlinkWorkbox について説明します。

ビデオゲーム「PROXX」のスクリーンショット。

Comlink は、Web Worker を使用するウェブサイトを構築する際に、多くの基盤となる詳細を処理する小さな(1.6k)RPC ライブラリです。PROXXSquoosh などのウェブサイトで使用されています。その動機とコードサンプルの概要については、こちらをご覧ください。

Workbox

Workbox は、サービス ワーカーを使用するウェブサイトを構築するための一般的なライブラリです。キャッシュ保存、オフライン、バックグラウンド同期などに関する一連のベスト プラクティスをパッケージ化します。workbox-window モジュールは、サービス ワーカーとページの間でメッセージを交換する便利な方法を提供します。

次のステップ

このシリーズの残りの部分では、ウィンドウとサービス ワーカーの通信パターンに焦点を当てます。

  • 命令型キャッシュ保存ガイド: ページから Service Worker を呼び出して、リソースを事前にキャッシュに保存します(プリフェッチ シナリオなど)。
  • ブロードキャスト更新: サービス ワーカーからページを呼び出し、重要な更新(ウェブサイトの新しいバージョンが利用可能になったなど)について通知します。
  • 双方向通信: サービス ワーカーにタスク(重いダウンロードなど)を委任し、ページの進捗状況を常に把握します。

ウィンドウとウェブ ワーカーの通信パターンについては、ウェブ ワーカーを使用してブラウザのメインスレッドから JavaScript を実行するをご覧ください。