📤 postMessage in JavaScript: cos'è e come può salvarti in situazione estreme

  



Quando si sviluppano applicazioni web moderne, capita spesso di dover far comunicare tra loro finestre, iframe o web worker. 

In questi casi, il metodo postMessage si rivela uno strumento fondamentale. In questo articolo vedremo cos’è postMessage, a cosa serve e come si utilizza, con esempi pratici.

🔗 Ti piace Techelopment? Dai un'occhiata al sito per tutti i dettagli!

Cos’è postMessage?

postMessage è un metodo fornito dagli oggetti window e worker in JavaScript, che consente la comunicazione cross-origin (tra contesti diversi), come ad esempio:

  • tra una finestra principale e un iframe;
  • tra due finestre o tab aperte;
  • tra una pagina web e un Web Worker.

A cosa serve?

Serve per inviare dati da un contesto all’altro in modo sicuro, anche se provengono da origini diverse. È utile quando:

  • si incorporano widget da altri siti (es. un iframe YouTube);
  • si usano Web Worker per eseguire operazioni pesanti in background;
  • si aprono finestre popup o si comunicano tab diverse della stessa applicazione.

Come si usa: la sintassi

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

Parametri:

  • message: il dato da inviare (può essere stringa, oggetto, array, ecc.).
  • targetOrigin: la origine del destinatario (es: 'https://esempio.com' o '*').
  • transfer (opzionale): oggetti trasferibili (come ArrayBuffer).

Attenzione a targetOrigin: è obbligatorio

Il secondo parametro di postMessage, chiamato targetOrigin, è obbligatorio secondo le specifiche HTML. Serve a indicare l’origine (protocollo + dominio + porta) del destinatario che deve ricevere il messaggio.

Perché è importante?

  • Sicurezza: impedisce che i dati vengano intercettati da origini non autorizzate.
  • Controllo: garantisce che il messaggio arrivi solo alla finestra giusta.

Esempi:

// Corretto
iframe.contentWindow.postMessage({ tipo: 'ping' }, 'https://esempio.com');

// Sconsigliato in produzione
iframe.contentWindow.postMessage({ tipo: 'ping' }, '*');
Nota: Anche se in alcuni ambienti JavaScript il parametro può sembrare opzionale, le specifiche HTML richiedono esplicitamente di fornire sempre targetOrigin.

Come ricevere i messaggi: window.addEventListener('message', ...)

Per ricevere un messaggio inviato con postMessage, il ricevente si registra all'evento message che offre l’oggetto event:

window.addEventListener('message', function(event) {
  console.log('Dati:', event.data);
  console.log('Origine:', event.origin);
  console.log('Provenienza:', event.source);
});

Spiegazione dei campi:

  • event.data: il messaggio ricevuto.
  • event.origin: l’origine della finestra mittente (es: https://esempio.com).
  • event.source: un riferimento alla finestra che ha inviato il messaggio.

Esempi (semplici) di utilizzo

Vediamo ora scenari tipici di utilizzo di postMessage che possono dare spunto a nuove tecniche di implementazione più robuste e strutturate.

Comunicazione tra finestra principale e iframe

<iframe id="myFrame" src="https://altrouser.com/frame.html"></iframe>
// Finestra principale
const iframe = document.getElementById('myFrame');
iframe.contentWindow.postMessage({ type: 'SALUTO', testo: 'Ciao iframe!' }, 'https://altrouser.com');
// Nell’iframe (frame.html)
window.addEventListener('message', function(event) {
  if (event.origin !== 'https://tuosito.com') return;
  console.log('Messaggio ricevuto:', event.data);
});

Comunicazione tra finestre

// Apri nuova finestra
const popup = window.open('https://esempio.com/popup.html');

// Invia messaggio dopo 1 secondo
setTimeout(() => {
  popup.postMessage('Ciao dalla finestra principale!', 'https://esempio.com');
}, 1000);

// Ricevi risposta
window.addEventListener('message', (event) => {
  console.log('Risposta dalla popup:', event.data);
});


💘 Quando postMessage può salvarti nello sviluppo

postMessage può davvero salvarti da ore di frustrazione (o dall’impazzire) in molti scenari dello sviluppo web moderno. È una delle API più sottovalutate, ma estremamente utile quando hai a che fare con contesti multipli o sandboxing

Ecco gli scenari principali dove postMessage diventa un'ancora di salvezza:

🧩 1. Comunicazione tra iframe e pagina principale

Problema: Hai un widget (chat, login, pagamento, etc.) incorporato in un <iframe>, ma non puoi accedere direttamente al suo contenuto (perché è su un dominio diverso).

Soluzione con postMessage:

  • La pagina host invia messaggi all'iframe per dirgli cosa fare (es: cambiare tema).

  • L'iframe invia messaggi alla pagina per notificare eventi (es: "utente loggato").

Eviti hack tipo polling o tentativi illegali di accesso cross-origin.


🌐 2. Integrazione tra microfrontend (diversi domini o team)

Problema: Stai lavorando in un’architettura a microfrontend, dove ogni sezione dell'app è servita da una SPA diversa (e magari da team diversi).

Soluzione con postMessage:

  • Le micro-app comunicano eventi tra loro (es: “utente selezionato”, “logout globale”).

  • Eviti tight coupling tra moduli.

Isolamento + coordinazione = meno bug e team più autonomi.


🔐 3. Autenticazione via popup (OAuth, login esterno)

Problema: Usi un flusso di autenticazione con popup (es. Google Sign-In, Facebook Login) e vuoi ricevere il token nella pagina principale.

Soluzione con postMessage:

  • Il popup, una volta autenticato, invia il token tramite postMessage alla finestra principale.

Evitato: brutti redirect, uso di URL con token, localStorage condivisi.


📦 4. Editor embeddati o strumenti di terze parti

Problema: Vuoi integrare nel tuo sito uno strumento interattivo (es. editor di testo, grafici, configuratori), ma è ospitato su un dominio esterno.

Soluzione con postMessage:

  • Il tool manda eventi tipo "contenuto aggiornato", "errore", "salvataggio riuscito".

  • Tu puoi rispondere con comandi, impostazioni o contenuti.

Interazione fluida anche con servizi esterni.


🧵 5. Sincronizzazione tra finestre o tab

Problema: Hai la tua app aperta in più tab o finestre, e vuoi tenerle sincronizzate (logout, notifiche, modifiche in tempo reale).

Soluzione con postMessage:

  • Le finestre si inviano eventi tra loro (via window.opener, window.parent, o BroadcastChannel come alternativa moderna).

Esperienza utente coerente e centralizzata.


⚙️ 6. Web Worker e performance

Problema: Devi fare operazioni pesanti (calcoli, parsing JSON, trasformazioni) ma non vuoi bloccare il thread principale.

Soluzione con postMessage:

  • Invia dati al Web Worker → elabora → ritorna il risultato con postMessage.

UI fluida anche con operazioni complesse.


👮 Validazione avanzata del messaggio ricevuto

Quando ricevi messaggi da altre finestre, iframe o Web Worker tramite postMessage, non dovresti mai fidarti ciecamente del contenuto ricevuto. Anche se un messaggio arriva da un'origine apparentemente valida, potrebbe essere stato manipolato o inviato per errore.

Per motivi di sicurezza, manutenibilità e robustezza del codice, è importante implementare una validazione approfondita. Ecco alcuni accorgimenti fondamentali:

🔒 1. Verifica dell'origine (origin)

Controlla che il messaggio provenga da un dominio atteso. Non usare mai '*' in ambienti di produzione.

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

if (event.origin !== trustedOrigin) return; // Scarta messaggi non autorizzati

🧱 2. Controllo della struttura del messaggio

Il messaggio può essere qualsiasi tipo. Controlla sempre che sia un oggetto valido e che abbia le proprietà previste.

const msg = event.data;

if (typeof msg === 'object' && msg !== null && 'type' in msg) {
  // Messaggio valido strutturalmente
}

✅ 3. Validazione dei valori attesi

Verifica che i valori dei campi siano nel formato corretto:

if (msg.type === 'SALUTO' && typeof msg.testo === 'string') {
  console.log('Saluto ricevuto:', msg.testo);
}

🧪 4. Validazione avanzata con librerie (facoltativo)

Per messaggi più complessi, puoi usare librerie di validazione come zod, joi o ajv. Esempio con zod:

import { z } from 'zod';

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

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

if (parsed.success) {
  console.log('Saluto valido:', parsed.data.testo);
}

🚫 5. Cosa evitare

  • Non fidarti di event.data a priori.
  • Non ignorare event.origin, nemmeno durante i test.
  • Non dare per scontata la struttura del messaggio.
  • Non esporre dati sensibili a mittenti non verificati.

⚡Compatibilità Browser

Per quanto riguarda la compatibilità con i diversi browser oggi sul mercato, fortunatamente postMessage è ampiamente supportato:

  • Tutti i principali browser (Chrome, Firefox, Safari, Edge, Opera) lo supportano da tempo.
  • Funziona anche in mobile.
  • Per dettagli aggiornati: caniuse.com/postMessage

⚙️ Uso con Web Worker

postMessage è alla base del funzionamento dei Web Worker. Di seguito trovi un esempio semplice per stuzzicare la tua curiosita che puoi soddisfare leggendo l'articolo Web Worker in JavaScript: cosa sono, come si usano e perché servono (e differenze con Service Worker):

// Nel main thread
const worker = new Worker('worker.js');
worker.postMessage('Esegui un calcolo');

// Nel worker (worker.js)
onmessage = function(event) {
  // Riceve messaggio
  postMessage('Risultato pronto');
};

✖️ Errori comuni da evitare

  • Usare '*' come targetOrigin in produzione.
  • Non verificare event.origin quando si riceve un messaggio.
  • Dimenticare che postMessage è asincrono.
  • Aspettarsi che la comunicazione funzioni tra file file:// (serve un server locale per testare).

⚽ Conclusione

postMessage è un potente strumento per creare applicazioni web modulari e comunicanti. La sua corretta implementazione consente di mantenere separati i contesti di esecuzione e migliorare la sicurezza e la scalabilità del codice.

postMessage è un alleato potente quando:

  • hai contesti isolati ma cooperanti (iframe, popup, microfrontend),

  • lavori con origini diverse (cross-origin),

  • vuoi mantenere performance o sicurezza,

  • vuoi decoupling tra componenti (comunicazione senza dipendenza diretta).



Follow me #techelopment

Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
X: techelopment
Bluesky: @techelopment
telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment