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

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

Demo: Real‑time Message Broadcast Across Tabs

<!DOCTYPE html>
<html>
  <head>
    <title>BroadcastChannel Demo</title>
  </head>
  <body>
    <h2>BroadcastChannel Demo</h2>
    <input id="msgInput" placeholder="Enter message to broadcast" />
    <button onclick="sendMessage()">Send</button>
    <ul id="log"></ul>
    <script>
      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 = '';
      }
    </script>
  </body>
</html>
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):

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

Tab B (receiver):

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

Demo: localStorage Data Sync

<!DOCTYPE html>
<html>
  <head>
    <title>localStorage + storage event</title>
  </head>
  <body>
    <h2>localStorage Communication Demo</h2>
    <input id="msgInput" placeholder="Enter message to sync" />
    <button onclick="syncMessage()">Sync</button>
    <ul id="log"></ul>
    <script>
      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);
        }
      });
    </script>
  </body>
</html>
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:

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);
    }
  }
}

Usage example:

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

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

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

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.