ウェブワーカーの概要

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

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

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

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

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

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

ウェブワーカーの起動方法

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

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

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

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

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

  • ウェブワーカーは DOM に直接アクセスできません。
  • ウェブワーカーは、メッセージング パイプラインを介して window コンテキストと通信できます。つまり、ウェブワーカーは DOM に間接的にアクセスできます。
  • ウェブワーカーのスコープが window ではなく self である。
  • ウェブワーカー スコープは、JavaScript のプリミティブと構造に加えて、fetch などの API や他の非常に多くの 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 メタデータを読み取ります。そのデータはメインスレッドに送り返され、ユーザーに表示されます。