๐Ÿ“ค postMessage in JavaScript: What it is and how it can save you in extreme situations

  


When developing modern web applications, it often happens that you need to make windows, iframes or web workers communicate with each other. 

In these cases, the postMessage method proves to be a fundamental tool. In this article we will see what postMessage is, what it is used for and how to use it, with practical examples.

๐Ÿ”— Do you like Techelopment? Check out the site for all the details!

What is postMessage?

postMessage is a method provided by the window and worker objects in JavaScript, which allows cross-origin communication, such as:

  • between a main window and an iframe;
  • between two open windows or tabs;
  • between a web page and a Web Worker.

What is it for?

It is used to send data from one context to another securely, even if they come from different sources. It is useful when:

  • you embed widgets from other sites (e.g. a YouTube iframe);
  • you use Web Workers to perform heavy operations in the background;
  • you open popup windows or communicate different tabs of the same application.

How to use it: the syntax

window.postMessage(message, targetOrigin, [transfer]);

Parameters:

  • message: the data to send (can be a string, object, array, etc.).
  • targetOrigin: the origin of the recipient (eg: 'https://example.com' or '*').
  • transfer (optional): transferable objects (like ArrayBuffer).

Beware of targetOrigin: it is mandatory

The second parameter of postMessage, called targetOrigin, is mandatory according to the HTML specification. It is used to indicate the origin (protocol + domain + port) of the recipient who should receive the message.

Why is it important?

  • Security: prevents data from being intercepted by unauthorized sources.
  • Control: ensures that the message arrives only in the right window.

Examples:

// Correct
iframe.contentWindow.postMessage({ type: 'ping' }, 'https://example.com');

// Not recommended in production
iframe.contentWindow.postMessage({ type: 'ping' }, '*');
Note: Although in some JavaScript environments the parameter may seem optional, the HTML specification explicitly requires that you always provide targetOrigin.

How to receive messages: window.addEventListener('message', ...)

To receive a message sent with postMessage, the receiver subscribes to the message  event which provides the event object:

window.addEventListener('message', function(event) {
    console.log('Data:', event.data);
    console.log('Origin:', event.origin);
    console.log('Source:', event.source);
});

Explanation of fields:

  • event.data: the received message.
  • event.origin: the origin of the sending window (e.g. https://example.com).
  • event.source: a reference to the window that sent the message.

(Simple) Examples of use

Let's now look at typical postMessage usage scenarios that can inspire new, more robust and structured implementation techniques.

Communication between main window and iframe

<iframe id="myFrame" src="https://otheruser.com/frame.html"></iframe>
// Main window
const iframe = document.getElementById('myFrame');
iframe.contentWindow.postMessage({ type: 'GREETING', text: 'Hello iframe!' }, 'https://otheruser.com');
// In the iframe (frame.html)
window.addEventListener('message', function(event) { 
    if (event.origin !== 'https://yoursite.com') return; 
    console.log('Message received:', event.data);
});

Window Communication

// Open new window
const popup = window.open('https://example.com/popup.html');

// Send message after 1 second
setTimeout(() => {
    popup.postMessage('Hello from the main window!', 'https://example.com');
}, 1000);

// Get response
window.addEventListener('message', (event) => {
    console.log('Response from popup:', event.data);
});


๐Ÿ’˜ When postMessage can save you in development

postMessage can really save you from hours of frustration (or going crazy) in many scenarios of modern web development. It is one of the most underrated APIs, but extremely useful when you are dealing with multiple contexts or sandboxing

Here are the main scenarios where postMessage becomes a lifeline:

๐Ÿงฉ 1. Communication between iframe and main page

Problem: You have a widget (chat, login, payment, etc.) embedded in an <iframe>, but you can't access its content directly (because it's on a different domain).

Solution with postMessage:

  • The host page sends messages to the iframe to tell it what to do (ex: change theme).

  • The iframe sends messages to the page to notify it of events (ex: "user logged in").

Avoid hacks like polling or illegal cross-origin login attempts.


๐ŸŒ 2. Integration between microfrontends (different domains or teams)

Problem: You are working in a microfrontend architecture, where each section of the app is served by a different SPA (and maybe different teams).

Solution with postMessage:

  • Micro-apps communicate events between each other (e.g. “user selected”, “global logout”).

  • Avoid tight coupling between modules.

Isolation + coordination = fewer bugs and more autonomous teams.


๐Ÿ” 3. Authentication via popup (OAuth, external login)

Problem: You use a popup authentication flow (e.g. Google Sign-In, Facebook Login) and want to receive the token on the main page.

Solution with postMessage:

  • The popup, once authenticated, sends the token via postMessage to the main window.

Avoided: bad redirects, use of tokenized URLs, shared localStorage.


๐Ÿ“ฆ 4. Embedded data editors or third-party tools

Problem: You want to integrate an interactive tool (e.g. text editor, graphics, configurators) into your site, but it is hosted on an external domain.

Solution with postMessage:

  • The tool sends events such as "content updated", "error", "save successful".

  • You can respond with commands, settings or content.

Fluid interaction even with external services.


๐Ÿงต 5. Synchronization between windows or tabs

Problem: You have your app open in multiple tabs or windows, and you want to keep them synchronized (logout, notifications, real-time changes).

Solution with postMessage:

  • Windows send events to each other (via window.opener, window.parent, or BroadcastChannel as a modern alternative).

Consistent, centralized user experience.


⚙️ 6. Web Worker and performance

Problem: You have to do heavy operations (calculations, JSON parsing, transformations) but you don't want to block the main thread.

Solution with postMessage:

  • Send data to Web Worker → process → return result with postMessage.

Fluid UI even with complex operations.


๐Ÿ‘ฎ Advanced validation of the received message

When receiving messages from other windows, iframes or Web Workers via postMessage, you should never blindly trust the received content. Even if a message comes from a seemingly valid source, it could have been manipulated or sent by mistake.

For reasons of security, maintainability and code robustness, it is important to implement thorough validation. Here are some basic tips:

๐Ÿ”’ 1. Check the origin (origin)

Check that the message comes from an expected domain. Never use '*' in production environments.

const trustedOrigin = 'https://example.com';

if (event.origin !== trustedOrigin) return; // Discard unauthorized messages

๐Ÿงฑ 2. Check the message structure

The message can be any type. Always check that it is a valid object and has the expected properties.

const msg = event.data;

if (typeof msg === 'object' && msg !== null && 'type' in msg) {
    // Structurally valid message
}

✅ 3. Validation of expected values

Check that the field values ​​are in the correct format:

if (msg.type === 'GREETING' && typeof msg.testo === 'string') {
    console.log('Greeting received:', msg.testo);
}

๐Ÿงช 4. Advanced validation with libraries (optional)

For more complex messages, you can use validation libraries like zod, joi or ajv. Example with zod:

import { z } from 'zod';

const MessageSchema = z.object({
    type: z.literal('GREETING'),
    text: z.string(),
});

const parsed = MessageSchema.safeParse(event.data);

if (parsed.success) {
    console.log('Valid greeting:', parsed.data.text);
}

๐Ÿšซ 5. What to avoid

  • Don't trust event.data a priori.
  • Don't ignore event.origin, not even during testing.
  • Don't take the message structure for granted.
  • Don't expose sensitive data to unverified senders.

⚡Browser Compatibility

As for compatibility with the different browsers on the market today, fortunately postMessage is widely supported:

  • All major browsers (Chrome, Firefox, Safari, Edge, Opera) have supported it for a long time.
  • It also works on mobile.
  • For up-to-date details: caniuse.com/postMessage

⚙️ Use with Web Worker

postMessage is the basis of how Web Workers work. Below is a simple example to pique your curiosity that can be satisfied by reading the article Web Worker in JavaScript: what they are, how to use them and why they are needed (and differences with Service Worker):

// In the main thread
const worker = new Worker('worker.js');
worker.postMessage('Perform a calculation');

// In the worker (worker.js)
onmessage = function(event) {
    // Receive message
    postMessage('Result ready');
};

✖️ Common mistakes to avoid

  • Using '*' as targetOrigin in production.
  • Not checking event.origin when receiving a message.
  • Forgetting that postMessage is asynchronous.
  • Expecting communication to work between file:// files (need a local server to test).

⚽ Conclusion

postMessage is a powerful tool for creating modular and communicating web applications. Its correct implementation allows you to keep execution contexts separate and improve code security and scalability.

postMessage is a powerful ally when:

  • you have isolated but cooperating contexts (iframes, popups, microfrontends),

  • you work with different origins (cross-origin),

  • you want to maintain performance or security,

  • you want decoupling between components (communication without direct dependency).



Follow me #techelopment

Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
/>telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment