MessageChannelMain and MessagePortMain classes
Electron adds MessageChannelMain and MessagePortMain classes to the main process because the main process is not a web page and has no Blink integration, so it lacks the native MessagePort and MessageChannel classes. These Electron classes behave similarly to their web counterparts.
MessageChannelMain use case
MessageChannelMain is used when you need to establish direct communication between different contexts in Electron. Common use cases include connecting two renderer processes without routing through the main process, implementing worker processes, creating reply streams for request-response patterns, and communicating with the main world of context-isolated pages.
MessagePort transfer methods
MessagePort objects can be transferred between renderer and main process only using ipcRenderer.postMessage() or WebContents.postMessage() methods. The usual IPC methods like send and invoke cannot be used to transfer MessagePorts.
MessagePortMain uses Node.js-style events API
MessagePortMain in the main process uses the Node.js-style events API with .on('message', ...) instead of the web-style .onmessage property used by MessagePort in the renderer.
MessagePortMain requires start() call
MessagePortMain queues messages until the .start() method has been called. Messages sent before start() is called will be buffered and delivered once the method is invoked.
MessagePort close event
Electron adds a close event to MessagePort that is not present in the web specification. This event is emitted when the other end of the channel is closed. Ports can also be implicitly closed by being garbage-collected. In the renderer, listen with port.onclose or port.addEventListener('close', ...); in the main process, use port.on('close', ...).
MessageChannel message queuing before listener registration
It is safe to send messages on a MessageChannel before the other end has registered a listener. Messages will be queued until a listener is registered on the receiving end.
MessagePort is lightweight
MessageChannels are lightweight and cheap to create, making them suitable for creating a new channel for each request, such as in streaming or request-response scenarios.
MessagePort serialization
MessagePort can transfer serializable objects and can carry other MessagePorts within the transferred data.
Main world in context-isolated pages
When context isolation is enabled, the main world refers to the global scope of the actual web page content (index.html), as opposed to the isolated world which is created by the preload script. Messages from the main process are delivered to the isolated world by default. MessageChannels can be used to communicate directly with the main world by transferring a port from the preload script to the main world via window.postMessage().
MessageChannel pair connection
A MessageChannel is created with new MessageChannel() in the renderer or new MessageChannelMain() in the main process, producing a pair of connected ports. Messages sent to port1 are received by port2 and vice-versa.
MessagePorts bridge same-origin restrictions
By passing MessagePorts via the main process, you can connect two pages that might not otherwise be able to communicate due to same-origin restrictions.
Worker process use case with MessageChannels
MessageChannels enable direct communication between a main application window and a hidden worker window (implemented as a BrowserWindow), avoiding the performance overhead of relaying messages through the main process.
Reply streams implementation
Using MessageChannels, you can implement a reply stream pattern where a single request responds with a stream of data. The renderer sends a MessagePort to the main process along with the request, the main process sends multiple messages on that port, and closes it when finished to signal completion.
WebContents.postMessage usage
WebContents.postMessage() is used to send messages and transfer MessagePorts from the main process to a renderer process. It accepts a channel name, message data, and an array of MessagePorts to transfer.
ipcRenderer.postMessage usage
ipcRenderer.postMessage() is used to send messages and transfer MessagePorts from a renderer process to the main process. It accepts a channel name, message data, and an array of MessagePorts to transfer.