demo · v140
Mobile SharedWorker Compatibility Tester
SharedWorker finally ships in Chrome for Android in version 140. This page probes availability, runs a live ping test, simulates multi-tab shared state, and documents mobile-specific gotchas alongside a progressive fallback chain.
Live SharedWorker ping test
Multi-tab shared counter (inline simulation)
Three “tabs” share the same SharedWorker counter. Incrementing from any tab updates all of them — this is the same SharedWorker instance, not three separate ones.
Tab A
Tab B
Tab C
Mobile-specific gotchas
Worker suspension when all tabs background
On Android, when all connected tabs move to the background, Chrome may suspend the SharedWorker after a short idle timeout. Reconnecting when a tab comes to the foreground re-creates the port connection. Store critical state in IndexedDB or BroadcastChannel before backgrounding.
Storage quota is shared across workers
SharedWorker storage (IndexedDB, Cache API) shares the same quota bucket as the page. On Android with storage pressure, the OS may evict the quota aggressively. Monitor navigator.storage.estimate() and persist critical keys under the persistent storage bucket.
Debugging on Android DevTools
Open chrome://inspect on desktop, connect the Android device via USB, and look for the “Shared workers” section under the device's chrome target. The worker shows a separate DevTools panel. Breakpoints and console work the same as desktop.
Blob URL workers and Android origin restrictions
SharedWorkers created from blob: URLs must share the same blob URL origin. On Android, blob URLs created in one tab cannot be reused in another tab's SharedWorker constructor — use a same-origin script URL instead for cross-tab sharing.
Platform support matrix
| Browser / Platform | SharedWorker | Notes |
|---|---|---|
| Chrome desktop | Yes (since v8) | Full support, all origins |
| Chrome Android | Yes (since v140) | Same-origin only; blob URL caveat above |
| Chrome iOS | No | WKWebView restriction; Apple controls the engine |
| Firefox desktop | Yes | Full support |
| Firefox Android | Yes | Full support since Firefox for Android 109 |
| Safari macOS | Yes | Full support |
| Safari iOS | Partial | Available but worker lifetime tied to tab; iOS 17.4+ |
| Samsung Internet | Yes | Chromium-based, follows Chrome Android support |
Build for Android first — progressive fallback
-
1
SharedWorker — feature detect:
typeof SharedWorker !== 'undefined'. Best for: multi-tab state, shared WebSocket, auth token store. Works on Chrome 140+ Android, all desktop browsers. - 2 BroadcastChannel — fallback when SharedWorker is absent. Best for: broadcasting events across tabs (no persistent state). Works on all modern browsers including Chrome iOS.
-
3
localStorage events — last resort. Write to a
localStoragekey; other tabs receive thestorageevent. Reliable but synchronous writes can block the main thread. No iOS restriction.
// Progressive fallback chain
let channel;
if (typeof SharedWorker !== "undefined") {
// Best: SharedWorker — persistent, rich API surface
const sw = new SharedWorker("/worker.js", { name: "app-bus" });
sw.port.start();
channel = {
send: msg => sw.port.postMessage(msg),
onmessage: cb => { sw.port.onmessage = e => cb(e.data); }
};
} else if ("BroadcastChannel" in window) {
// Good: BroadcastChannel — no persistent worker, but works everywhere
const bc = new BroadcastChannel("app-bus");
channel = {
send: msg => bc.postMessage(msg),
onmessage: cb => { bc.onmessage = e => cb(e.data); }
};
} else {
// Fallback: localStorage events
channel = {
send: msg => {
localStorage.setItem("app-bus", JSON.stringify({ msg, ts: Date.now() }));
},
onmessage: cb => {
window.addEventListener("storage", e => {
if (e.key === "app-bus") cb(JSON.parse(e.newValue).msg);
});
}
};
}
see also
- SharedWorker on Android — feature index
- Multi-tab Bus — live cross-tab messaging demo
- Android detection — sibling concept
- ChromeStatus entry
- SharedWorker spec