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
Top comments (9)
Some other possibilities :
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.
Ah I see, TIL. Thanks!
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.
When I first learned about localStorage storage event I've created a JavaScript library for sending messages between tabs called Sysend.js, it also support cross-domain communication. The first implementation used LS then added BroadcastChannel if supported. To give you perpective the idea for the project was based on my StackOverflow question Sending notifications between instances of the page in the same browser that I've asked in 2014 (even before ES6 was standarized), and I think I was the first one that implemented library like this.
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!