Frontend Development 9 min read

Master Cross‑Tab Communication: BroadcastChannel vs localStorage in JavaScript

Learn how to synchronize data across multiple browser tabs using the native BroadcastChannel API and the fallback localStorage + storage event, with step‑by‑step code examples, usage scenarios, feature comparisons, compatibility notes, and a reusable TabMessenger class for seamless inter‑tab messaging.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Master Cross‑Tab Communication: BroadcastChannel vs localStorage in JavaScript

Hello, I'm Shi Xiaoshi, an open‑source contributor and author of the "Tampermonkey Script Practical Guide". While developing Tampermonkey scripts, I needed a way for multiple tabs of the same web app to share messages—e.g., when one tab logs out, all others should log out too.

Instead of the older

GM_saveTab

API, I discovered that the native

BroadcastChannel

API and the

localStorage

+

storage

event can easily solve cross‑tab data sharing.

Using BroadcastChannel for Tab Communication

What is BroadcastChannel?

BroadcastChannel

is a browser‑provided API that enables communication between different tabs of the same origin, acting like a broadcast station where any tab can send a message and all listening tabs receive it.

Example

<code>const channel = new BroadcastChannel('my-channel');</code>
<code>channel.onmessage = (e) => {
  console.log('Received message:', e.data);
};</code>
<code>channel.postMessage('Hello, other tabs!');</code>
<code>channel.close();</code>

Demo: Real‑time Message Broadcast Across Tabs

<code>&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;BroadcastChannel Demo&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h2&gt;BroadcastChannel Demo&lt;/h2&gt;
    &lt;input id="msgInput" placeholder="Enter message to broadcast" /&gt;
    &lt;button onclick="sendMessage()"&gt;Send&lt;/button&gt;
    &lt;ul id="log"&gt;&lt;/ul&gt;
    &lt;script&gt;
      const channel = new BroadcastChannel('demo_channel');
      const log = document.getElementById('log');
      channel.onmessage = (event) => {
        const li = document.createElement('li');
        li.textContent = `Received: ${event.data}`;
        log.appendChild(li);
      };
      function sendMessage() {
        const input = document.getElementById('msgInput');
        channel.postMessage(input.value);
        input.value = '';
      }
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code>
BroadcastChannel demo GIF
BroadcastChannel demo GIF

Using localStorage + storage Event for Synchronization

storage Event

When you need to support older browsers or avoid adding BroadcastChannel,

localStorage

can be used for communication. Changing

localStorage

in one tab triggers a

storage

event in all other tabs.

Tab A (sender):

<code>localStorage.setItem('laoliu', JSON.stringify({
  type: '不想工作',
  text: "只要胆子大,天天都是假"
}));</code>

Tab B (receiver):

<code>window.addEventListener('storage', (event) => {
  if (event.key === 'laoliu') {
    const msg = JSON.parse(event.newValue);
    if (msg.type === '不想工作') {
      alert('6666,你个老六');
    }
  }
});</code>

Demo: localStorage Data Sync

<code>&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;localStorage + storage event&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h2&gt;localStorage Communication Demo&lt;/h2&gt;
    &lt;input id="msgInput" placeholder="Enter message to sync" /&gt;
    &lt;button onclick="syncMessage()"&gt;Sync&lt;/button&gt;
    &lt;ul id="log"&gt;&lt;/ul&gt;
    &lt;script&gt;
      const log = document.getElementById('log');
      function syncMessage() {
        const input = document.getElementById('msgInput');
        localStorage.setItem('crossTabMessage', JSON.stringify({
          text: input.value,
          timestamp: Date.now()
        }));
        input.value = '';
      }
      window.addEventListener('storage', (event) => {
        if (event.key === 'crossTabMessage') {
          const data = JSON.parse(event.newValue);
          const li = document.createElement('li');
          li.textContent = `Received: ${data.text}`;
          log.appendChild(li);
        }
      });
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code>
localStorage demo GIF
localStorage demo GIF

Key Considerations

The

storage

event fires only in tabs *other* than the one that performed the change.

The sender does not receive its own message; only receivers respond.

Include a unique identifier such as a timestamp in the payload to avoid cache‑related misinterpretations.

Feature Comparison

Both BroadcastChannel and

localStorage

+

storage

support same‑origin communication, but BroadcastChannel offers automatic object serialization, true bidirectional messaging, and a cleaner API, while

localStorage

works in older browsers but requires manual serialization and cannot receive its own messages.

Complete Wrapper Demo

A reusable

TabMessenger

class abstracts the two approaches:

<code>class TabMessenger {
  constructor(channelName = 'default') {
    this.isBroadcastSupported = typeof BroadcastChannel !== 'undefined';
    this.channelName = channelName;
    if (this.isBroadcastSupported) {
      this.channel = new BroadcastChannel(channelName);
    } else {
      window.addEventListener('storage', this._onStorage.bind(this));
    }
  }
  onMessage(handler) {
    if (this.isBroadcastSupported) {
      this.channel.onmessage = (e) => handler(e.data);
    } else {
      this.storageHandler = handler;
    }
  }
  postMessage(msg) {
    if (this.isBroadcastSupported) {
      this.channel.postMessage(msg);
    } else {
      localStorage.setItem('__tab_msg_' + this.channelName, JSON.stringify({
        msg,
        ts: Date.now()
      }));
    }
  }
  _onStorage(e) {
    if (e.key.startsWith('__tab_msg_' + this.channelName)) {
      const data = JSON.parse(e.newValue);
      this.storageHandler?.(data.msg);
    }
  }
}</code>

Usage example:

<code>const messenger = new TabMessenger('myApp');
messenger.onMessage((data) => {
  console.log('Received:', data);
});
messenger.postMessage('Hello, other pages!');</code>

Conclusion

Without any heavy frameworks, native browser APIs allow effortless data synchronization across tabs. For modern browsers,

BroadcastChannel

is the preferred choice due to its simplicity and directness; for legacy support, the

localStorage

+

storage

fallback remains reliable.

FrontendJavaScriptWeb APIlocalStorageBroadcastChannelcross-tab communication
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.