このコースではこれまで、一般的な 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 を更新したり、メインスレッドで実行する必要があるその他の処理を実行したりできます。
知識を試す
ウェブワーカーはどのスレッドで実行されますか。
ウェブワーカーがアクセスできるもの
window
コンテキストで使用できる API の厳密なサブセット(fetch
など)。window
コンテキスト(ただし、間接的)。ウェブワーカーが「window」コンテキストにアクセスするにはどうすればよいですか?
window
オブジェクトのメンバーを参照することによって直接的に行う。window
にアクセスできません。self
)の postMessage
メソッドで円滑なメッセージング パイプラインを使用する。次のトピック: 具体的なウェブワーカーのユースケース
次のモジュールでは、具体的なウェブワーカーのユースケースについて詳しく説明します。このモジュールでウェブワーカーを使用して、指定された URL から JPEG ファイルを取得し、ウェブワーカーでその Exif メタデータを読み取ります。そのデータはメインスレッドに送り返され、ユーザーに表示されます。