How SharedWorker Works Across Multiple Browser Tabs
The SharedWorker interface allows multiple browser
contexts—such as tabs, windows, or iframes—to run and interact with a
single shared JavaScript background thread. By binding connections to a
centralized script instance via explicit communication ports, web
applications can centralize network requests, synchronize application
state, and manage shared resources without duplicating background
processing across each open tab.
The Same-Origin Instance Model
When a browser tab instantiates a
new SharedWorker(scriptURL, [name]), the browser checks if
a worker instance already exists for that exact script URL and name
under the same origin (protocol, domain, and port).
- If an instance already exists, the browser simply connects the new tab to the running worker.
- If no matching worker exists, the browser spawns a new background thread, loads the script, and executes it.
Because execution is scoped to the origin, data within the worker thread resides in a single, shared memory space accessible by any eligible browsing context.
Port-Based Communication
Unlike standard dedicated Web Workers that use the worker instance
directly to send and receive messages, SharedWorker relies
on MessagePort objects provided by the Channel Messaging
API.
- Tab Connection: When a tab initializes the worker,
it receives a reference to a dedicated port via
worker.port. - Worker Event Handling: Inside the shared worker
script, the runtime fires the
onconnectevent each time a new tab connects. - Port Assignment: The
connectevent contains aportsarray containing the communication port corresponding to that specific tab (e.ports[0]). - Data Transfer: Both the tab and the shared worker
communicate asynchronously through their respective port objects using
port.postMessage()and theport.onmessageevent handler (orport.addEventListener('message', ...)combined withport.start()).
// main.js (Tabs)
const worker = new SharedWorker('worker.js');
worker.port.start();
worker.port.onmessage = (event) => {
console.log('Message received from SharedWorker:', event.data);
};
worker.port.postMessage('Hello from Tab');// worker.js (SharedWorker)
const connections = [];
self.onconnect = (event) => {
const port = event.ports[0];
connections.push(port);
port.start();
port.onmessage = (e) => {
// Broadcast data to all connected tabs
connections.forEach((conn) => {
conn.postMessage(`Broadcasting: ${e.data}`);
});
};
};Lifecycle and Resource Management
A SharedWorker remains active as long as at least one
connected tab, window, or iframe maintains an open port to it. Once all
connected browsing contexts are closed or explicitly close their ports,
the browser terminates the worker instance to reclaim system memory.
This architecture is especially effective for maintaining a single persistent WebSocket or Server-Sent Events (SSE) connection, centralizing data caching, and eliminating duplicate network polling across multi-tab user sessions.