iT邦幫忙

2025 iThome 鐵人賽

DAY 27
3
Modern Web

從 Canvas 到各式各樣的 Web API 之旅系列 第 27

Day 27 - SharedWorker 讓多分頁共享同一個執行緒

  • 分享至 

  • xImage
  •  

過去三天我們介紹了 Service WorkerDedicated Worker

  • Service Worker 能在背景攔截請求、做離線快取,是網站的「系統級後勤」。
  • Dedicated Worker 則幫單一頁面處理重運算,讓畫面保持流暢。

今天要登場的,是 Web Worker 家族的第三位成員——SharedWorker
它的特色是:多個分頁可以共享同一個執行緒,非常適合用來同步狀態或共用連線資源。 🚀


Web Workers 家族對照表

類型 執行範圍 是否能被多頁共享 能否操作 DOM 主要用途
Dedicated Worker 單一頁面 ❌ 否 ❌ 否 背景計算、重運算任務
SharedWorker 多個分頁(同來源) ✅ 是 ❌ 否 多頁共享資料、統一連線或緩存
Service Worker 網域層級 ✅ 是 ❌ 否 離線快取、攔截請求、推播通知

可以這樣理解:

Dedicated Worker:單頁助理,幫一個頁面處理重任務。
SharedWorker:團隊助理,讓多個頁面共用同一份資料。
Service Worker:守門員,幫整個網站攔截與快取請求。


為什麼需要 SharedWorker?

想像一個情境:你開了同一個網站的兩個分頁(例如一個是聊天頁,一個是通知頁),這兩頁都需要連線到伺服器的 WebSocket。

如果用 Dedicated Worker,每一頁都會各自開一條連線,浪費資源。

但如果用 SharedWorker,它們可以共用同一個背景執行緒與連線,互相同步資料、節省頻寬。


建立 SharedWorker

1. 建立 worker.js

// worker.js
const connections = [];

onconnect = function (e) {
  const port = e.ports[0];
  connections.push(port);

  port.onmessage = (event) => {
    console.log('收到訊息:', event.data);

    // 將訊息廣播給所有連線中的頁面
    connections.forEach((p) => p.postMessage(`[廣播] ${event.data}`));
  };

  port.start(); // 開始監聽
};

2. 在主執行緒中使用

// main.js
const worker = new SharedWorker('./worker.js');
const port = worker.port;

port.onmessage = (e) => {
  console.log('收到來自 SharedWorker 的訊息:', e.data);
};

port.start();

// 傳送資料給 SharedWorker
port.postMessage('Hello from Page A!');

開啟兩個同來源頁面,開啟 console 就會看到兩邊互相廣播的結果 ✨


SharedWorker 的特性

1. 多頁共享

不同分頁(或 iframe)只要屬於相同 origin(協定、網域、port 相同),就能共用同一個 SharedWorker 實例。

這表示:

  • 只需要一個 WebSocket 連線即可多頁使用。
  • 可作為全站級資料快取中樞。
  • 當所有頁面都關閉後,SharedWorker 才會被瀏覽器自動清除。

2. 使用 port 溝通(不是 postMessage()

SharedWorker 必須透過 MessagePort 進行雙向傳遞。每個頁面都要呼叫 port.start(),否則不會接收訊息。

這點與 Dedicated Worker 的 worker.onmessage 最大不同。

3. 支援與相容性

  • SharedWorker 只支援 相同來源(same-origin) 頁面共享。
  • 不支援跨分頁的 localStorage 監聽(可用 BroadcastChannel 作為替代)。
  • Safari 支援度仍有限(需注意相容性)。

實務應用場景

場景 說明
WebSocket 共享連線 多頁面共用一條連線,節省伺服器壓力與頻寬。
多頁資料同步 分頁 A 登入、分頁 B 即時更新登入狀態。
集中快取處理 讓多頁共享同一份 IndexedDB 或計算結果。
協作應用 如線上編輯器或聊天室,可透過 SharedWorker 廣播更新狀態。

範例 Demo

想直接體驗 SharedWorker 多分頁共享的神奇效果,可以參考這個線上範例 - 多分頁共享計數器:⏱️

SharedWorker

記得開啟多個分頁測試,你會看到所有分頁的計數器即時同步!一定要試試看喔~🎉


延伸:目前的使用狀況

SharedWorker 能讓多分頁共享同一個執行緒,但在實務上仍屬於少數人使用的技術。
主要不是因為它不好,而是「相容性、需求量與生態成熟度」讓它顯得相對邊緣。

為什麼比較少人用 SharedWorker?

  1. 相容性風險高
    Safari 直到 16 版才支援,若要顧及 iOS 用戶,採用風險仍高。
  2. 生態尚未成熟
    由於早期支援不足,開發者與框架都較少投入資源。
  3. 替代方案太多且更穩定
    多分頁溝通的需求,現在更常用以下組合:
    • Service Worker + BroadcastChannel:結合離線快取與跨分頁通訊。
    • MessageChannel + IndexedDB:提供雙向傳遞與快取資料機制。
    • localStoragestorage 事件:快速同步小量狀態(登入、偏好設定等)。
      這些方案在瀏覽器相容性、穩定性、除錯體驗上都更好,也更容易「降級處理」。
  4. 工具支援有限
    即使在支援的瀏覽器中,DevTools 對 SharedWorker 的除錯仍不完善。
    Safari 與部分 Chromium 版本下仍缺乏穩定的檢視與監控介面。

Web Workers 現況比較

類型 可跨頁共享 攔截請求 典型用途 支援度 開發難度 流行程度
Dedicated Worker ❌ 否 ❌ 否 計算、壓縮、AI 推論 ✅ 全瀏覽器 ⭐⭐⭐⭐
Shared Worker ✅ 是 ❌ 否 跨分頁共享資料 ⚠️ Safari 16+ ⭐⭐
Service Worker ✅ 是 ✅ 是 PWA、快取、推播 ✅ Safari 11.1+ ⭐⭐⭐ ⭐⭐⭐⭐

Shared Worker 依然在大型協作應用(如雲端 IDE、資料分析平台)中發揮關鍵作用,只是如今更多人選擇更穩定的替代方案來實現相同目標。


小結

SharedWorker 是 Web Worker 家族中最適合「多頁同步」的成員:

Dedicated Worker 解決「單頁卡頓」,
Service Worker 解決「網站離線」,
SharedWorker 解決「多頁共享」。


👉 歡迎追蹤這個系列,我會從 Canvas 開始,一步步帶你認識更多 Web API 🎯


上一篇
Day 26 - Dedicated Worker 讓重運算不再卡畫面
下一篇
Day 28 - WebSocket 讓瀏覽器與伺服器即時對話
系列文
從 Canvas 到各式各樣的 Web API 之旅30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言