モジュール ワーカーによるウェブのスレッド化

ウェブ ワーカーに JavaScript モジュールを使用することで、負荷の大きい処理をバックグラウンド スレッドに簡単に移動できるようになりました。

JavaScript はシングルスレッドなので、一度に 1 つのオペレーションしか実行できません。これは、 ウェブの多くのケースで適切に機能しますが、必要なときに問題になりかねません。 データの処理、解析、計算、分析などの手間のかかるタスクをさらに増加 ウェブで配布されることが多いため、マルチスレッドの あります。

ウェブ プラットフォームでは、スレッド化と並列処理の主なプリミティブは Web Workers API。 ワーカーはオペレーティング システムを基盤とする軽量な抽象化 Message Pass API を公開するスレッド 使用します。この方法は、コストがかかる計算や 処理を実行できるため、メインスレッドをスムーズに実行しながら 負荷の高い処理を実行するのに最適です

次に、ワーカーの典型的な使用例を示します。ここでは、ワーカー スクリプトがメインメッセージからのメッセージをリッスンします。 独自のメッセージを返信することで応答します。

page.js:

const worker = new Worker('worker.js');
worker.addEventListener('message', e => {
  console.log(e.data);
});
worker.postMessage('hello');

worker.js:

addEventListener('message', e => {
  if (e.data === 'hello') {
    postMessage('world');
  }
});

Web Worker API は、ほとんどのブラウザで 10 年以上前から提供されています。その一方で、 従業員が優れたブラウザサポートを受け、適切に最適化されていることを意味する。 使用できます。ワーカーの設計時にモジュール システムが存在しなかったため、この API は ワーカーへのコードの読み込みとスクリプトの作成については、同期スクリプトとほぼ同じです。 2009 年に一般的になった読み込み手法です

履歴: 従来のワーカー

Worker コンストラクタは、引数として script の URL です。 ドキュメント URL からの相対パスです。すぐに新しいワーカー インスタンスへの参照が返されます。 メッセージ インターフェースと、terminate() メソッドを公開します。このメソッドは、 ワーカーを破棄します。

const worker = new Worker('worker.js');

importScripts() 関数は、追加のコードを読み込むためにウェブ ワーカー内で使用できますが、 各スクリプトを取得して評価するために、ワーカーの実行を一時停止します。また、スクリプトや 従来の <script> タグのようにグローバル スコープで指定。つまり、1 つのスクリプト内の変数を 上書きされる場合もあります。

worker.js:

importScripts('greet.js');
// ^ could block for seconds
addEventListener('message', e => {
  postMessage(sayHello());
});

greet.js:

// global to the whole worker
function sayHello() {
  return 'world';
}

このため、これまでウェブ ワーカーは、ウェブ アプリケーションのアーキテクチャに多大な影響を 説明します。開発者は、優れたツールと回避策を作成して、 最新の開発手法をあきらめることなくウェブ ワーカーを使用できます。たとえば、バンドルの webpack は、importScripts() を使用する生成されたコードに小さなモジュール ローダの実装を埋め込みます。 ただし、変数の競合を回避してシミュレートするために、モジュールを関数内にラップします。 インポートとエクスポートに利用できます。

モジュール ワーカーを入力

JavaScript による人間工学とパフォーマンス上のメリットを備えた、ウェブ ワーカー向けの新しいモード モジュールは、モジュール ワーカーと呼ばれる Chrome 80 で出荷されます。「 Worker コンストラクタが新しい {type:"module"} オプションを受け入れるようになりました。これにより、スクリプトの読み込みと <script type="module"> に一致する必要があります。

const worker = new Worker('worker.js', {
  type: 'module'
});

モジュール ワーカーは標準の JavaScript モジュールであるため、インポート ステートメントとエクスポート ステートメントを使用できます。として すべての JavaScript モジュールでは、依存関係は特定のコンテキスト(メインスレッド、 ワーカーなどのワーカーなど)からインポートされ、以降のすべてのインポートでは、すでに実行されたモジュール インスタンスを参照します。読み込み JavaScript モジュールの実行もブラウザによって最適化されます。モジュールの依存関係は、モジュール モジュールの実行前に読み込まれるため、モジュール ツリー全体を ありますモジュールの読み込みでは、解析されたコードもキャッシュに保存されます。つまり、メインモジュールで使用されるモジュールは ワーカー内のオブジェクトは 1 回だけ解析する必要があります。

JavaScript モジュールに移行すると、Dynamic import: コードの実行をブロックせずに遅延読み込みを行います。 指定することもできます。動的インポートは、importScripts() を使用して依存関係を読み込むよりもはるかに明確です。 これは、インポートされたモジュールのエクスポートがグローバル変数に依存せずに返されるためです。

worker.js:

import { sayHello } from './greet.js';
addEventListener('message', e => {
  postMessage(sayHello());
});

greet.js:

import greetings from './data.js';
export function sayHello() {
  return greetings.hello;
}

優れたパフォーマンスを確保するため、モジュール内では古い importScripts() メソッドを使用できません。 できます。JavaScript モジュールを使用するようにワーカーを切り替えると、すべてのコードが厳格な モード。その他 大きな変更点は、JavaScript モジュールの最上位スコープにある this の値が undefined。従来のワーカーでは、値はワーカーのグローバル スコープです。幸いなことに、 常に self グローバルであり、グローバル スコープへの参照を提供します。利用可能な言語: DOM のあらゆるタイプのワーカーに対応できます

modulepreload を使用してワーカーをプリロードする

モジュール ワーカーによって大幅にパフォーマンスが向上するのは、 依存関係を定義します。モジュール ワーカーを使用すると、スクリプトは標準形式で読み込まれて実行されます。 JavaScript モジュール。つまり、modulepreload を使用してプリロードすることも、事前に解析することもできます。

<!-- preloads worker.js and its dependencies: -->
<link rel="modulepreload" href="worker.js">

<script>
  addEventListener('load', () => {
    // our worker code is likely already parsed and ready to execute!
    const worker = new Worker('worker.js', { type: 'module' });
  });
</script>

プリロードされたモジュールは、メインスレッドとモジュール ワーカーの両方でも使用できます。これは インポートされるモジュール、または事前に把握できない場合に モジュールがメインスレッドとワーカーのどちらで使用されるかを指定します。

以前は、ウェブ ワーカー スクリプトのプリロードに使用できるオプションは限られており、 必要不可欠です従来のワーカーには独自の「ワーカー」がリソースタイプは使用できるものの、 <link rel="preload" as="worker"> を実装したブラウザ。そのため、主要な手法は、 ウェブワーカーのプリロードに利用できる <link rel="prefetch"> の使用法は、 HTTP キャッシュに格納します正しいキャッシュ ヘッダーと組み合わせて使用すると、 ワーカーのインスタンス化でワーカー スクリプトのダウンロードを待つ必要がなくなりますただし、 modulepreloadこの手法では、依存関係のプリロードや準備の解析がサポートされていませんでした。

共有ワーカーについて

共有ワーカーでは、 が更新され、Chrome 83 時点で JavaScript モジュールがサポートされるようになりました。専任スタッフのように {type:"module"} オプションを指定して共有ワーカーを作成すると、ワーカー スクリプトが モジュールを使用します。

const worker = new SharedWorker('/worker.js', {
  type: 'module'
});

JavaScript モジュールをサポートする前は、SharedWorker() コンストラクタは URL とオプションの name 引数。従来の共有ワーカーを使用する場合、これは引き続き機能します。 モジュール共有ワーカーを作成するには、新しい options 引数を使用する必要があります。利用可能な オプション これは専用ワーカーの場合と同じです。たとえば、name オプションが 前の name 引数。

Service Worker についてはどうでしょうか。

Service Worker の仕様は、 サポートするように更新されました。 JavaScript モジュールをエントリ ポイントとして、モジュール ワーカーと同じ {type:"module"} オプションを使用。 ただし、この変更はまだブラウザには実装されていません。そうすれば、 次のコードを使用して JavaScript モジュールで Service Worker をインスタンス化します。

navigator.serviceWorker.register('/sw.js', {
  type: 'module'
});

仕様の更新を経て、ブラウザでは新しい動作の実装が始まります。 JavaScript の統合に伴い、余分な複雑さが加わるため、これには時間がかかります。 Service Worker に push します。Service Worker の登録では、インポートされたスクリプトの比較が必要 キャッシュされたバージョンと 更新をトリガーするかどうかの判断。これは JavaScript モジュールで実装する必要があります。 使用した場合また、Service Worker は、ルーティングされた キャッシュが特定の状況で アップデートを確認しています。

その他のリソースと関連情報