loading...

Cross Tab Communication with Javascript

naismith profile image Chris Naismith ・3 min read

About a month ago an interesting problem came up at work, how can I listen to a form being submitted that may be in another tab? It's something that if it was in the same tab, would be much more straight forward. But I also wanted to know can I send messages between these two, or more, tabs.

What is Cross Tab Communication?

Cross Tab Communication is the ability of multiple tabs, windows, frames of iframes (further known as an instance) to send and receive 'messages' to and from other instances.

Limitations / Gotchas

This does come with some drawbacks. This will only work with domains on the same-origin.

You will not be able to use this across HTTP and HTTPS.
You will not be able to use this across different hosts.
You will not be able to use this across different ports.

How is this useful?

Before getting into some demos, I figure I would go over why this can be useful. Sometimes your users are going to have multiple instances of your site open, and how we handle their experience can be quite important.

For example, Dan Abramov's blog https://overreacted.io/ has a toggle for a dark mode/light mode. Using this, you could switch all open instances to the preferred theme without refreshing.

Examples / Demos

Example 1 - LocalStorage

External link if you don't want the preview


How this works is by setting/modifying a value in local storage or session storage on load of the application. When this happens, an event is fired that can be listened to on any other instance. This event contains information such as the key that was modified, the previous value, the new value and much more. If you're familiar with React, this is similar to how you can compare the previous props, to the current props in class lifecycle method componentDidUpdate.

Drawbacks of Example 1

There are some draw backs to using this method. For one, you can not store objects in local storage/session storage unless they are stringified. This means you would have to parse any of these values which may not be a huge deal, but in my opinion is not ideal.

The second draw back is that the event will not be fired if a value is updated to the same value. In my example I get around that limitation to setting the key loaded to Date.now().

Example 2 - BroadcastChannel

External link if you don't want the preview


In this example, I'm using the BroadcastChannel API. To do this, you create a new BroadcastChannel using a name (Similar to an IRC channel).

After subscribing to the channel you are returned an instance of the BroadcastChannel object, which in this example we use two parts of. You can send a message using the postMessage function, or attach a function to the onmessage property.

Similar with Example 1, and messages you send in one instance will be received in other instances. Along with the ability to subscribe to the same channel multiple times.

Drawbacks/Benefits of Example 2

Unlike Example 1, you are able to post full objects, arrays and other pieces of data.

However, Example 2 is a little bit more complicated and may be overkill depending on what you're trying to do.

Support for the BroadcastChannel API is also limited. Compared to local storage (globally at 92%), BroadcastChannel is at almost 76%. Chrome and Firefox both support it, with no support from IE, Safari and Edge. (Chromium Edge does support it, but is still considered in Beta as of this post).

More Usecases

This could be used in a CMS to let the user know they already have an instance open when trying to modify something, or to keep it in sync across tabs.

Authentication/locked content could be unlocked when logging in so that other windows are not out of sync.

Changing a profile picture

Communication between iframes.

Changing themes of a website, and syncing those changes across all tabs.

Conclusion

I don't think that this is going to be ground breaking and change the way we make our applications. But I do think implementing this across some features of our applications could improve the user experience.

If you have any other use cases you think this would be useful for, I'd love to hear it!

Resources

CanIUse - Localstorage
CanIUse - BroadcastChannel
MDN - BroadcastChannel

Posted on by:

naismith profile

Chris Naismith

@naismith

I'm a software developer at TygerShark in Ontario, and part time instructor at Georgian College

Discussion

markdown guide
 

I learn something new again as usual - never knew BroadcastChannel is a thing until now!

It will be interesting to see better browser support for it. localStorage had been a pain to share objects, especially with Edge due to its aggressive caching when I had to work with a tab/window sync problem at my work recently!

 

Local storage event listeners are not supported everywhere but it still blows my mind when

You logout in one tab and get logged out automatically in other tabs.

 

Some other possibilities :

  • SessionStorage (same than localStorage but w/o persistence)
  • SharedWorker (oups, deprecated !)
  • ServiceWorker (postMessage and loop other all opened window instances to broadcast message).
  • If all tabs are attached because opened from the same source page (const child = window.open()), you can communicate using the instance and window.opener.
 

SharedWorker is not deprecated, right? MDN says nothing about that. It's probably the most well-supported way of doing this although BroadcastChannel has much better DX.

Also the npm package broadcast-channel does this with fallbacks to non-native BroadcastChannel alternatives i.e. localStorage (for IE) and idb.

 

SharedWorker was flagged “removed” from WebKit spec and IE didn’t plan to implement it.
The main reason for the dismiss is the ServiceWorker API that appeared soon after and can handle all the SharedWorker API.

 

I think another method would be server push notifications. In the first tab the client notifies the server that I submitted a form. The server then notifies the second tab.

 

A benefit of this is that you dont need a server to do this. But it breaks down if you start using multiple browsers, and I would imagine containers in firefox as well.

But certainly is an option!