Chrome 80 から Web Worker (Dedicated Worker) で ES Modules が使えるようになります。本記事はその宣伝です。

前提知識

  • ES Modules って何?
    • ざっくりいうとスクリプトファイルをモジューラブルに読み込む仕組みです。
    • 他の方が解説した記事がいっぱいあるのでそっちを見てください。
  • Web Worker って何?

スクリプトファイルの読み込みについては以前「JavaScript のスクリプトインポートを正しく使い分けようという話」に詳しくまとめたのでそちらも併せて読んでください。

使い方

Dedicated Worker で ES Modules (Module Script) をインポートする方法は 3 つあります。

Worker コンストラクタ

1 つ目は Worker コンストラクタの第二引数で type オプションを指定する方法です。type に ‘module’ を指定すると worker のトップレベルスクリプト(要するに最初に実行されるスクリプト)が Module Script として実行されます。

<script>
const worker = new Worker('module-worker.js', { type: 'module' });
</script>

このとき worker を作るスクリプトが Module Script である必要はありません。上の例だと <script> タグに type='module' を指定しなくても大丈夫です。

Static import

2 つ目は worker 内で static import する方法です。

// In module-worker.js
import * as module from './hello-module.js';
module.SayHello();

Static import は Module Script 内でしか使えないため、1 つ目の方法で worker のトップレベルスクリプトを Module Script として起動しておく必要があります。以下の例だとトップレベルスクリプトが Classic Script になるため static import が失敗し、worker の起動自体がエラーになります。

<script>
// Worker will be loaded as classic script.
const worker = new Worker('module-worker.js');
worker.onerror = e => {
  // This error event handler will be fired.
};
</script>

Dynamic import

3 つ目は worker 内で dynamic import する方法です。

// In module-worker.js
import('./hello-module.js')
  .then(module => module.SayHello());

Dynamic import は Classic Script として起動した worker 内でも使えます。

<script>
const worker = new Worker('module-worker.js');
worker.onerror = e => {
  // This error event handler won't be fired.
};
</script>

よくある質問

Shared Worker や Service Worker でも使えますか?

本記事執筆時点ではまだ使えません。仕様は定義されていますがまだ実装されていません。実装状況は crbug/824646crbug/824647 をそれぞれチェックしてください。この機能が早く欲しい方はチケットにスターを付けてもらえると作業の優先度を決める参考になります。

他のブラウザでも使えますか?

本記事執筆時点では Chromium ベースのブラウザ (Edge, Opera etc) でのみ使うことができます。Firefox や Safari はまだ実装していません。そのうち実装されると思うので、それぞれのチケット(Firefox チケット / Safari チケット)をチェックしてください。

Module Script 内で importScripts() は使えますか?

使えません。importScripts() は Classic Worker Script でのみ使えます。詳しくは「JavaScript のスクリプトインポートを正しく使い分けようという話」を見てください。

modulepreload は使えますか?

使えません。そもそも Web Worker は preload にもまだ対応していません (crbug/946510)。代わりに prefetch してください。

(他に質問があれば気軽に聞いてください)

リンク