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.

?

Checking SharedWorker availability...

Running feature detection.

Loading platform info...

Live SharedWorker ping test

Not run yet
Not run yet

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.

Shared counter worker

Tab A

0

Tab B

0

Tab C

0

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. 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. 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. 3 localStorage events — last resort. Write to a localStorage key; other tabs receive the storage event. 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