ブラウザのウィンドウ間でメッセージをやりとりする方法はwindow.postMessage()
を使う方法が有名ですが、もう一つBroadcastChannel
というものを使った方法もあります。二者の特徴をまとめたのが以下です。
-
window.postMessage()
- 異なるオリジン間でメッセージの送受信が可能
- 送信相手のwindowへの参照が必要
-
BroadcastChannel
- 同一オリジン間でしかメッセージの送受信ができない
- 送信相手への参照が必要がない
ということで同一オリジンのウィンドウ間のメッセージのやりとりはBroadcastChannel
を使うべきです。他のサイトはメッセージを受信することができないのでセキュリティ的に好ましいですし、開発者としても送信相手へのwindow参照を持つ必要がなく実装が単純になります。逆にオリジンを跨ぐ場合はwindow.postMessage()
を使うしかないということになります。
ちなみにBroadcastChannel
は主要なブラウザ全てでサポート済みです。
使用方法
BroadcastChannelにはチャンネルという概念があり、あるチャンネルに送られたメッセージは同じチャンネルでしか受信されません。チャンネルはBroadcastChannel
のコンストラクタにチャンネル名を与えることで指定します。以下の例ではチャンネル名としてchannelName
を指定しています。
使い方は非常にシンプルです。
送信方法
const channel = new BroadcastChannel('channelName');
channel.postMessage(message);
message
は送信するメッセージです。message
として送れる型の制約は正確に述べると複雑ですが、少なくともJSONと対応する型は送れます。オブジェクトや配列をネストした複合型でもOKです。
受信方法
const channel = new BroadcastChannel('channelName');
channel.addEventListener('message', ev => {
const message = ev.data;
});
上記コードによりchannel.postMessage(message)
で送信したメッセージが変数message
として受信されます。
以上!
補足: 同一オリジンとは?
補足としてここでいう「同一オリジン」の意味を説明します。ここでいう「オリジン」とは簡単に言えばスクリプトが動いているブラウザのアドレスバーに表示されているURLのホスト名より前側(ポートがあるならポートより前側)の部分のことです。
まず一般にオリジンとはプロトコル、ホスト名、ポート番号の組のことです。例えばhttp://example.com:8080/path.html
というURLのオリジンはhttp://example.com:8080
です。
そしてここでいうオリジンがなんのオリジンかというと、閲覧コンテキストのオリジンと説明できます。閲覧コンテキストのオリジンとは先程の通り簡単に言えばブラウザのアドレスバーのURLのオリジンです。スクリプトファイル自体のURLではありません。 つまり例えば以下のHTMLページがhttps://www.example.com/index.html
として表示されている場合、その<script>
タグのスクリプトの閲覧コンテキストはスクリプトファイルのURLのオリジンであるhttps://other.domain.net
ではなく https://www.example.com
です。
<!DOCTYPE html>
<html>
<head>
<script src="https://other.domain.net/index.js"></script>
</head>
<body>
</body>
</html>
以上で説明したオリジンが同じスクリプト同士ではBroadcastChannel
で通信できるということです。
あとがき
window.postMessage()
は前から知ってたけどBroadcastChannel
は最近知ったので、みんな知らないんじゃね?と勝手に思って書いた記事。