ウェブワーカーの概要

このコースの内容の多くは、一般的な HTML のパフォーマンスに関する考慮事項、リソースヒント、最初のページの読み込み時間やユーザー入力に対する応答性を改善するためのさまざまなリソースタイプの最適化、特定のリソースの遅延読み込みなどのコンセプトに焦点を当ててきました。

ただし、JavaScript のパフォーマンスに関する 1 つの側面については、このコースではまだ説明していませんが、入力の応答性を向上させるうえでウェブワーカーが果たす役割について、このモジュールと次のモジュールで取り上げます。

JavaScript はシングルスレッド言語と表現されることが多く、実際には、メインスレッドのことを指します。メインスレッドは、ブラウザに表示されるほとんどの処理をブラウザが行う単一のスレッドです。この作業には、スクリプトの作成、一部のレンダリング作業、HTML と CSS の解析など、ユーザー エクスペリエンスを向上させるユーザー向けの作業に関連するタスクが含まれます。実際、ブラウザは、デベロッパーが通常は直接アクセスできない作業(GPU スレッドなど)には、他のスレッドを使用します。

JavaScript に関しては、処理の実行がメインスレッドに限定されますが、これはデフォルトに限られます。JavaScript で追加のスレッドを登録して使用することは可能です。JavaScript でマルチスレッドを可能にする機能は、Web Workers API と呼ばれます。

ウェブワーカーは、計算負荷の高い作業があっても、ページが応答しなくなるような長いタスクを発生させずにメインスレッドで実行できない場合に便利です。このようなタスクは、ウェブサイトの Interaction to Next Paint(INP)に確実に影響する可能性があるため、メインスレッドから完全に実行できる処理があるタイミングを把握すると役立ちます。これにより、メインスレッドに他のタスク用のスペースが広がり、ユーザー操作が高速化されます。

このモジュールと具体的なユースケースを示す後続のデモでは、ウェブワーカーについて説明します。デモ自体は、ウェブワーカーを使用してメインスレッドから JPEG ファイルから画像メタデータを読み取る処理を実行する方法と、そのメタデータをユーザーが確認できるようにメインスレッドに戻す方法を示しています。

Web Worker の起動方法

ウェブワーカーを登録するには、Worker クラスをインスタンス化します。その際、ウェブワーカー コードの場所を指定します。ブラウザはこれを読み込んで新しいスレッドを作成します。結果として得られるスレッドは、多くの場合、ワーカー スレッドと呼ばれます。

const myWebWorker = new Worker('/js/my-web-worker.js');

ワーカーの JavaScript ファイル(この場合は my-web-worker.js)にコードを記述すると、別のワーカー スレッドで実行されます。

ウェブワーカーの制限事項

メインスレッドで実行される JavaScript とは異なり、ウェブワーカーは window コンテキストに直接アクセスできず、提供する API へのアクセスが制限されます。ウェブワーカーには次の制約があります。

  • ウェブワーカーは DOM に直接アクセスできません。
  • ウェブワーカーは、メッセージング パイプラインを介して window コンテキストと通信できます。つまり、ウェブワーカーは DOM に間接的にアクセスできます。
  • Web Worker のスコープが window ではなく self になっている。
  • ウェブ ワーカー スコープは、JavaScript のプリミティブと構造に加え、fetch などのその他多数の API にもアクセスします。

ウェブワーカーが window と通信する方法

ウェブワーカーは、メッセージング パイプラインを介してメインスレッドの window コンテキストと通信できます。このパイプラインを使用すると、メインスレッドとウェブワーカーとの間でデータをやり取りできます。ウェブワーカーからメインスレッドにデータを送信するには、ウェブ ワーカーのコンテキスト(self)で message イベントを設定します。

// my-web-worker.js
self.addEventListener("message", () => {
  // Sends a message of "Hellow, window!" from the web worker:
  self.postMessage("Hello, window!");
});

次に、メインスレッドの window コンテキストのスクリプトで、さらに別の message イベントを使用してウェブ ワーカー スレッドからメッセージを受信できます。

// scripts.js

// Creates the web worker:
const myWebWorker = new Worker('/js/my-web-worker.js');

// Adds an event listener on the web worker instance that listens for messages:
myWebWorker.addEventListener("message", ({ data }) => {
  // Echoes "Hello, window!" to the console from the worker.
  console.log(data);
});

ウェブワーカーのメッセージング パイプラインは、ウェブワーカーのコンテキストからの脱出手段です。これを使用すると、ウェブワーカーから window にデータを送信し、それを使用して DOM を更新したり、メインスレッドで実行する必要のある他の作業を実行したりできます。

理解度テスト

ウェブワーカーはどのスレッドで実行されますか?

メインスレッド。
もう一度お試しください。
独自のスレッド(ウェブ ワーカー スレッドとも呼ばれます)
正解です。
GPU スレッド。
もう一度お試しください。

ウェブ ワーカーがアクセスできるもの

JavaScript のプリミティブ(配列やオブジェクトなど)。
正解です。
window コンテキストで使用できる API の厳格なサブセット(fetch など)。
正解です。
window コンテキスト。ただし、間接的です。
正解です。

ウェブワーカーはどのようにして「window」コンテキストにアクセスできますか。

window オブジェクトのメンバーを参照することにより直接。
もう一度お試しください。
ウェブワーカーはどのような方法でも window にアクセスできません。
もう一度お試しください。
ウェブ ワーカー コンテキスト(self)の postMessage メソッドによって実現されるメッセージング パイプラインを使用する。
正解です。

次のトピック: ウェブワーカーの具体的なユースケース

次のモジュールでは、ウェブワーカーの具体的なユースケースを取り上げて、詳しく説明します。このモジュールでウェブワーカーを使用して、指定された URL から JPEG ファイルを取得し、ウェブワーカーでその Exif メタデータを読み取ります。そのデータは、その後、ユーザーに表示するメインスレッドに送り返されます。