Harnessing the Power of Messagechannel and Broadcastchannel

Rate this content

Delve into the world of Web API's - MessageChannel and BroadcastChannel. Explore how these powerful APIs facilitate seamless communication in web workers, iframes, and across tabs. Join us as we uncover the techniques to enhance web interactions and unlock new possibilities. Discover the key to smoother collaboration and improved connectivity in your web projects!

11 min
23 Oct, 2023

Video Summary and Transcription

This talk explores hidden web APIs for communicating between iframes and web workers. It discusses the disadvantages of a naive messaging approach and introduces the message channel API as a solution. The speaker also presents a library called message-channel-shake that simplifies message channel implementation. The talk covers various technologies like React, broadcast channel, and transferable objects.

Available in Español

1. Introduction to Web Messaging

Short description:

Welcome to this talk about web messaging. I'm Daniel Jakobsen, a full-stack staff engineer at Vim. We'll explore hidden web APIs for communicating between iframes and web workers. We'll start with a naive messaging example and then dive into message channel-based messaging using the message channel API.

Hello, everybody. Welcome to this talk about web messaging. I'm Daniel Jakobsen. I'm a full-stack staff engineer at Vim. Not the editor. It's a different company. We do healthcare.

We've encountered many problems that we needed to communicate between iframes and web workers and I wanted to share with you some of the insights we have found and really some hidden web APIs that are not that known that you can leverage and can really help you with communicating between these web components.

So what are we going to learn? We're going to start with a naive messaging example with iframes just to see how we can communicate between them with really the basic building blocks. And then we're going to deep dive a bit into message channel-based messaging. We're going to leverage something that's called message channel API. It's a browser API that's been here for a long, long time, but it's not that known, at least it wasn't for me. And, yeah, we're going to see this basic demo.

2. Naive Communication Example

Short description:

We have a naive communication example where an embedded iframe sends a message to the main page. The main HTML waits for the iframe to load and then uses postMessage to send a payload. The embedded iframe receives the message and verifies its origin before sending a response back to the parent page.

We have here a naive communication example. We have the main site and inside it, there is an embedded iframe. And we can see that we have the message back from the iframe. This is the message that the iframe is sending, and inside the embedded iframe there is a hello from the main page. So let's see how that's going to work.

So this is the main HTML. And inside here, with the first thing we do is we wait for the embedded iframe to load. Once that occurs, we use postMessage. PostMessage is the most basic building block of communication. It allows us to send messages to iframes, web workers, most web components in the browser support postMessage. And here that's exactly what we do, we take the iframe element and we use postMessage, we send some payload and we're going to see in a moment how the embedded iframe receives this message.

So this is the embedded iframe HTML page, and inside here we have an adEventListener, it's a global adEventListener in the window, and we are listening to message event, and the previous postMessage comes directly, one more, comes directly to here, and inside here is a logic to verify that the message comes from the main page, because there could be multiple messages that come here. We do some logic, and then we use yet again the postMessage, but this time the embedded iframe does the postMessage on the parent page. So in the window.parent there is also window.top that you can do postMessage and it works the same way around. Now in the main html page we have the global event listener. We can handle the logic and do some whatever we want.

3. Disadvantages of the Naive Approach

Short description:

The naive approach to web messaging has several disadvantages. It is difficult to implement promise support, as it requires building a messaging system. Additionally, it only supports direct communication between the embedded iframe and the parent or top window, limiting its flexibility. The approach also pollutes the global event handler, which can cause computation overhead and potential privacy concerns.

So there are some disadvantages to this naive approach. It's really hard to implement the promise support with this. You need to like to really implement a messaging system. If you're going to want to have, let's say you send an event to a web worker, you do some async stuff, and you want it to return and you want the main page to promise a wait on that, it's going to be a bit complex to implement that. And also it only supports direct communication, so that means the embedded I-frame can only talk with the parent or the top window, and if the embedded I-frame and the window or the page that it wants to communicate with is somewhere in between, it can't, so that's another disadvantage. And the last one is that it pollutes the global event handler. Many libraries can use the global event handler and can see our messages, sometimes we might not want that. It can cause significant computation overhead, so there are some disadvantages to this.

4. Message Channel API and Implementation

Short description:

We explore the message channel API and its implementation in an example. The channel has two ports that are deeply connected, allowing for bidirectional messaging. We send the second port in the postMessage payload, enabling the embedded iframe to receive it. However, message channel can still be complex and require boilerplate code. To simplify this, I've created the library message-channel-shake, which provides handshake, bidirectional communication, promise support, iframe and web worker support, and React support. We demonstrate an example with React and discuss other technologies like broadcast channel and transferable objects.

So I want to go into the message channel API and see how the same example, we can implement it with a message channel. So first we're going to create a message channel, as simple as that. And then I want to talk about these two things. We have the port one and port two. These are properties in the channel, and they're deeply connected. When I do onMessage on port one, it will receive messages from port two. So on port two, I can do postMessages and it will come to the port one onMessage. On port one, I can do postMessage, and it will arrive in the port two onMessage. So they are deeply connected and this is like the channel that is between them.

So this time we are still using postMessage, but there is something special going on in here. We are sending the second port in the postMessage payload, specifically in the argument that is called transferable objects, a message port is one of them. And this allows us to... This allows the embedded iframe to receive this message port. So we can see here the same embedded iframe, but now this event that ports zero, it's actually port two. So now we can do a postMessage on that, and it's going to come back to the onMessage on the first port. So I want to talk about a bit what went here. The line of communication was safe. We had that direct line from the port two to port one. Nobody saw anything in between. And it opens a lot of possibilities. So message channel is great, but it can still be a bit complex. There is a lot of boilerplate code that we will usually want to create, like handshake between the mainframe and the embedded iframe or mainframe and the webworker. This is much easier to implement than the naive approach, but still, it requires a bit of boilerplate. And we are here in the React Advanced Conference, and if we want to use refrec, it also requires a bit of wrapping. So I've created this library, it's called message-channel-shake. It's really in an alpha state, but I urge you to look in the source code to see a bit how the boilerplate there is implemented. Maybe it will be even better and you can use it out of the box, but it has all those things that we want, all the boilerplates, out of the box.

So it's handshake, bidirectional communication, promise support, iframe and web worker support, and React support. Let's see an example with React, and that's why we're here, and see how we can implement the same thing we saw before, but with message-channel-shake. So the initiator is the main page, and we first wrap our app with the message-channel-shake provider, a React provider, and then somewhere inside the component tree, we're gonna use the iframe-channel-wrapper, and the first properties are the same properties you could pass to a regular iframe, and then these are some special properties you need to pass to your message-channel-shake implementation. So first there's the channel ID, both the main page and the embedded iframe need to talk in the same channel, so it will be secure, and then we have message callbacks, so the main page, the initiator, can handle events from the embedded iframe or WebWalker. I want you to notice that the callback is async, so you can actually do async logic and return a response, and it will go back to the embedded iframe. Let's see how it looks in the embedded iframe, so in the embedded iframe, we have a receiver provider, which has the same set of properties that's needed like before, and somewhere inside the component for the receiver, you can use a hook that is called useportmessenger, and in the portmessenger, we can just send messages, and that is actually a promise. In the response, we can get a payload back from the main page message handler, and we can do whatever we want, so a bit of a summary, it was quick. What did we see? We've seen how to communicate naively between iframes, we've seen how to use message channel, we've seen how message channel shake can help leveraging message channel and reduce a bit of the boilerplate. If you want to further enhance some communication knowledge between iframes, web workers, tabs, I urge you to read about these technologies. There is broadcast channel, it's also a web API, there is system, it's a library to allow cross-region communication in broadcast channel, and there are transferable objects that are more than the other message port.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

JSNation 2023JSNation 2023
25 min
Pushing the Limits of Video Encoding in Browsers With WebCodecs
High quality video encoding in browsers have traditionally been slow, low-quality and did not allow much customisation. This is because browsers never had a native way to encode videos leveraging hardware acceleration. In this talk, I’ll be going over the secrets of creating high-quality videos in-browsers efficiently with the power of WebCodecs and WebAssembly. From video containers to muxing, audio and beyond, this talk will give you everything you need to render your videos in browsers today!
JSNation 2022JSNation 2022
28 min
MIDI in the Browser... Let's Rock the Web!
If you own an electronic music instrument made in the last 3 decades, it most likely supports the MIDI protocol. What if I told you that it is possible to interact with your keytar or drum machine directly from your beloved browser? You would go crazy, right? Well, prepare to do so…With built-in support in Chrome, Firefox and Opera, this possibility is now a reality. This talk will introduce the audience to the Web MIDI API and to my own WEBMIDI.js library so you can get rockin' fast.Web devs, man your synths!
JSNation 2023JSNation 2023
11 min
Web Push Notifications Done Right
Finally, Web Push API is available in all major browsers and platforms. It's a feature that can take your users' experience to the next level or... ruin it! In my session, after a tech intro about how Web Push works, we'll explore implementing smart permission request dialogues, various types of notifications themselves, and communicating with your app for more sophisticated scenarios - all done right, with the best possible UX.
JSNation Live 2021JSNation Live 2021
34 min
Service Workers: How to Run a Man-in-the-middle Attack on Your Own Site for Fun and Profit
Service workers bring amazing new capabilities to the web. They make fully offline web apps possible, improve performance, and bring more resilience and stability to any site. In this talk, you'll learn how these man-in-the-middle attacks on your own site work, different approaches you can use, and how they might replace many of our current best practices.

Workshops on related topic

Node Congress 2022Node Congress 2022
57 min
Writing Universal Modules for Deno, Node and the Browser
This workshop will walk you through writing a module in TypeScript that can be consumed users of Deno, Node and the browsers. I will explain how to set up formatting, linting and testing in Deno, and then how to publish your module to deno.land/x and npm. We’ll start out with a quick introduction to what Deno is.