ワーカーの概要

ウェブワーカーと Service Worker がサイトのパフォーマンスを改善する仕組みと、ウェブワーカーと Service Worker のどちらを使用するかについて説明します。

Andrew Guan
Andrew Guan

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

社員がウェブサイトを改善する方法

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

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

ウェブでは、JavaScript は単一スレッドのコンセプトを中心に設計されているため、アプリのようなマルチスレッド モデルを実装するために必要な機能(共有メモリなど)が欠落しています。

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

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

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

ウェブワーカーと Service Worker

類似点

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

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

相違点

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

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

ユースケース

両方のタイプのワーカーの違いは、どちらを使用するかを判断するうえで役立ちます。

ウェブワーカーのユースケースは、UI のブロックを回避するために、セカンダリ スレッドに処理(負荷の高い計算など)をオフロードすることに関連しています。

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

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

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

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

ポッドキャスト PWA のスクリーンショット。
UI が更新され、ダウンロードの進行状況が表示されます(左)。サービス ワーカーにより、すべてのタブが閉じられてもオペレーションを実行し続けることができます(右)。

ツールとライブラリ

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

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

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

Workbox

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

次のステップ

このシリーズの残りの部分では、ウィンドウとサービス ワーカーの通信パターンについて説明します。

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

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