
【JavaScript入門】Shared Worker
Shared Worker は 複数ページ/タブ間で 1 本だけ起動される共通スレッド です。
同一オリジン内なら、開いているページが何枚あっても 単一インスタンス を共有できるため、
- ウィンドウ間でのリアルタイム同期
- 重量級キャッシュや WebSocket 接続の一本化
などで威力を発揮します。シンタックスは通常 Worker と似ていますが、port
経由 の通信になる点が大きな違いです。

1.Worker の種類とスコープ
種類 | スレッド数 | 共有範囲 | 通信 API |
---|---|---|---|
Dedicated Worker | ページごとに 1 本 | 共有なし | postMessage / onmessage |
Shared Worker | オリジンごとに 1 本 | 同一オリジンの全タブ | port.postMessage / port.onmessage |
Service Worker | オリジンごとに 1 本 | ネットワーク・オフライン制御 | postMessage / onmessage |
2.基本 API
立場 | 生成/接続 | 送信 | 受信 |
---|---|---|---|
ページ | new SharedWorker("worker.js") | worker.port.postMessage(data) | worker.port.onmessage = e => … |
Worker | onconnect = e => { const p = e.ports[0]; … } | port.postMessage(data) | port.onmessage = e => … |
port.start()
はモダンブラウザで自動呼び出しされるため省略可能です。
3.サンプル構成
app3/
├─ web-worker/
│ ├─ shared-worker.html(各ページから接続)
│ └─ shared-worker.js(共通スレッド)
└─ index.js ← Express サーバー("Fetch APIで通信をする"で使用したものと同じ)
4.サンプルプログラム
4.1. shared-worker.js
(共通スレッド)
// カウンタを全ページで共有
let counter = 0;
onconnect = e => {
const port = e.ports[0];
port.onmessage = ev => {
console.log("@worker 受信:", ev.data); // Worker 側ログ
port.postMessage(`返信! ${++counter}`); // ページへ返信
};
};
4.2. shared-worker.html
(各ページから接続)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>🤝 Shared Worker デモ</title>
<style>
body{font-family:"Segoe UI",sans-serif;margin:2rem;background:#f9fbff}
h1{text-align:center;font-size:1.8rem;margin-bottom:1rem}
button{padding:.6rem 1.2rem;border:none;border-radius:6px;
background:#0078d4;color:#fff;font-weight:bold;cursor:pointer}
button:hover{opacity:.85}
#log{white-space:pre-line;border:1px solid #ccc;background:#fff;
border-radius:8px;margin-top:1rem;padding:1rem;min-height:6rem}
</style>
</head>
<body>
<h1>🤝 Shared Worker デモ</h1>
<button id="sendBtn">メッセージ送信</button>
<div id="log">ここに結果が表示されます</div>
<script>
const log = txt => document.getElementById("log").textContent += txt + "\n";
// Shared Worker へ接続
const worker = new SharedWorker("shared-worker.js");
// 受信
worker.port.onmessage = e => log("▶ 受信: " + e.data);
// 送信ボタン
document.getElementById("sendBtn").onclick = () => {
log("● 送信: こんにちは");
worker.port.postMessage("こんにちは");
};
</script>
</body>
</html>
4.3. index.js の作成
以下の index.js を作成して、例えば「C:\Users\<ユーザー名>\Desktop\node-js\app4」に保存します。
ファイル名: index.js
// index.js
const express = require("express");
const app = express();
// ルート
app.get("/", (_, res) => res.send("Hello World"));
// 静的ファイル(/net, /web-worker 配下)
[
{ path: "/net", root: __dirname + "/net" },
{ path: "/web-worker", root: __dirname + "/web-worker" }
].forEach(opt => app.use(opt.path, express.static(opt.root)));
app.listen(3000, () => console.log("Server started: http://localhost:3000/"));
5.動作確認手順
5.1. PowerShell を起動し、index.js を置いたフォルダへ移動します。
移動例:
PS C:\Users\joeac\Desktop\node-js\app4>
5.2. ターミナルで node .
を実行
node .
5.3. ブラウザで複数のタブを開き、各々のURLに「http://localhost:3000/web-worker/shared-worker.html」を入力する

各々のタブで「メッセージ送信」をクリックすると
▶ 受信: 返信! 1 ← タブ1
▶ 受信: 返信! 2 ← タブ2
▶ 受信: 返信! 3 ← タブ2
のように カウンタが連番 で増え、単一 Worker が共有されていることが分かります。
6.ポイント解説
- 接続イベント
onconnect
Shared Worker は “接続” ごとにonconnect
が発火し、event.ports[0]
でページ専用のMessagePort
を取得。 - 終了管理
ページが閉じても他タブが残っていれば Worker は存続。完全に不要になったらページ側でworker.port.close()
を呼ぶと良い。 - ユースケース
・WebSocket や IndexedDB を 1 つに集約
・頻繁なポーリングを複数タブで共有して省リソース
・タブ間チャット・通知のリアルタイム同期
まとめ
Shared Worker を使うと “ブラウザ内のマイクロサービス” のように中央スレッドを置き、複数ページをまたいでステートやコネクションを共有できます。new SharedWorker
→ port.postMessage
/ port.onmessage
という最小 API を押さえ、
リアルタイム連携やリソース節約にぜひ活用してみましょう。