開発状況
- vue.jsでdevserverを使って、localhost開発をしている。
- 開発しているSPA(ページA)が、別ウィンドウでページBを開いて、そちらとpostMessageで通信をしている。
- 本番で動く場合は、ページAもページBも同一ドメインである。
- 開発中は、ページAはLocalhostで、ページBが諸般の事情でインターネット上の開発サーバを利用する状況
問題
同一ドメインの場合では問題ないのですが、開発環境ではドメインが違うので以下のようなエラーがでます。
Uncaught DOMException: Blocked a frame with origin "http://localhost:8080" from accessing a cross-origin frame.
ちなみに、ページAからページBを開いて、ページBから通信を待つのは、以下のようにしています。
const win = window.open('http://example.com')
// オープン先のサイトのロード時間があるので、1秒ほど待機をしてからイベントを設定する。
setTimeout(() => {
win.addEventListener('message', event => {
const data = event.data
if (data.command === 'close_page') {
win.close()
}
}, false)
},
1000)
何をしているかというと、ページBを開いて、ページBで何かを作業して、処理が完了したら、ページBからpostMessageを送ってもらいます。ページAは、それを待ち受けて、ページBを閉じるというものです。
ここでは端折っていますが、ページBからページAに必要なデータも送ってもらっています。
解決法
まずは、以下を試しましたが、うまくいきませんでした。
クロスドメイン制約を回避するChromeショートカットを作る
でも、それなりにセキュリティレベルは落ちているし、開発用のChrome環境としてもよいので、これはこれで生かしておきます。
次に、Chromeの実験的な機能を操作できるフラグがあるということを、ソースは失念しましたが、見つけて、変更しました。
ChromeのURLに「chrome://flags/」を入力します。
下記のように「Disable site isolation」を「Disable」にしたらエラーがでなくなりました。
イベントリスナーが設定されているかを確認する
今回、addEventListenerで待ち受けているのですが、これをモニターする方法も探しました。
DevToolsのイベントの監視にあります。
みんながお世話になっている開発者ツールのコンソールで、「getEventListeners(window)」と入力すると、イベント一覧が取得できます。
今回は、「message」イベントを仕掛けているので、「messege」を開きます。
ここでは2個ありあした。その1個目の「lisner」を開くと、「FunctionLocation」が「」がでてきます。こいつになります。
なぜ1個目だとわかったかというと、同一ドメインでの場合と開発環境での場合で比較したからです。
エラーがでにく本番の場合で、イベントが効いてないようなら、こちらで調べてみてもいいかもしれません。
最後に
個人的に、「Disable site isolation」を「Disable」にしたら、「enable site isolation」で、ほんとにページ間通信ができないんじゃない!?って考えているのですが、まぁ、とりあえず、デバッグを進めたいので目をつむっておきます。
このあたり、Chromeのデバッグ関係の詳しい説明があれば嬉しいんですけど。。。。