新Edge(Chromium)対応及びjsspRpcの動作、親画面の処理対応について

2022年06月01日 00時06分

intra-mart IEサポート終了

記事にもある通り2022年6月16日をもってついにIEのサポートが切れ、同様にintra-martのサポートも終了します。

ブラウザを移行する際に、intra-mart固有の改修についてメモを残しておきます。

今回はjsspRpcについて。

Chromeや新Edge(Chromium版)でページを閉じる際のイベントbeforeunload、unload、pagehide、visibilitychangeは同期処理が許容されなくなってしまいました。詳細

そのため次期ブラウザを利用する際に、上記イベントjsspRpcにcallback関数が設定されていない場合、 jsspRpcのところで処理が止まってしまいます。

1画面の改修

2022/06/03追記

jsspRpcにcallback関数が設定されていた場合でも、ブラウザの遷移の速さによって処理が完了しない場合がありました。

参考:ページ遷移や離脱時に漏れなく解析データの送信をするための Beacon API

そのため次期ブラウザではjsspRpcの代わりにNavigator.sendBeacon()を使用して任意のアドレスにPOSTを行い、ルーティング定義に指定したファンクションコンテナ側の関数を実行する方法に切り替えました。

改修前

sample.html
  <imart type="jsspRpc" name="jsSample" page="jssp_rpc_test/sample1" />
  // callback記載が無いので同期処理
  // イベントの設定 (addEventListener)
  window.addEventListener( 'beforeunload', function ( event ) {
      console.log('start');
      jsSample.sampleFunction();//同期処理のため実行されない。
      console.log('end'); //endは出力されない。
  });

改修後

sample.html
  <imart type="jsspRpc" name="jsSample" page="jssp_rpc_test/sample1" />
  // callback記載が無いので同期処理
  // イベントの設定 (addEventListener)
  window.addEventListener( 'beforeunload', function ( event ) {
      if(agent.indexOf('trident') != -1 ||
        agent.indexOf('msie') != -1 ){
          jsSample.sampleFunction();// IEなので通常通り
      } else if (agent.inedxOf('chrome') != -1){
          var postData = new FormData();
          postData.set('id', 'sak3');
          navigator.sendBeacon('rooting定義で指定したURL', postData);
      }
  });

親画面を呼び出して同期関数を実行した場合の改修

また該当イベントの中に親画面を参照して関数を実行する際も同様にjsspRpc同期関数が含まれていると 動作しませんでした。

改修前

parent.html
  //親画面
  <imart type="jsspRpc" name="jsSample" page="jssp_rpc_test/sample1" />
  // callback記載が無いので同期処理
  function childrenCloseEvent(){
      console.log('親画面start');
      jsSample.sampleFunction();//同期処理のため実行されない。
      console.log('親画面end'); //endは出力されない。
  };
child.html
---
  //子画面
  window.addEventListener( 'beforeunload', function ( event ) {
      if(!window.opener || window.opener.closed) return;
      console.log('子画面start');
      window.opener.childrenCloseEvent();//親画面の関数呼び出し
       //同期処理のため実行されない。
      console.log('子画面end'); //endは出力されない。
  });

子画面のbeforeunloadが発火した際、 consoleに子画面start、親画面startが出力されてjsSample.sampleFunctionは実行されず処理が終了します。

親画面の処理は同期処理で行いたいという要求がある場合、別の方法といいますか 親ページにデータを投げて、子画面は処理を閉じる必要がありました。

親画面との通信

ブラウザ間の通信は何通りかあるようですが、 Window.postMessage()を使用します。

一部制限はありますが、IE10以降でPostmessageは対応しています

改修後

parent.html
  //親画面
  window.addEventListener('message', function(event){
    if (event.origin !== 'http://example.com:8080') return;// 対象ドメイン以外は受け取らない
    childrenCloseEvent(); //該当イベント実行
  }, false);
child.html
  //子画面
  window.addEventListener( 'beforeunload', function ( event ) {
      if(!window.opener || window.opener.closed) return;
      var agent = window.navigator.userAgent.toLowerCase();
      console.log('start');
      if(agent.indexOf('trident') != -1 ||
        agent.indexOf('msie') != -1 ){
        // IEなので通常通り
        window.opener.childrenCloseEvent();//親画面の関数呼び出し
      } else if (agent.inedxOf('chrome') != -1){
          window.opener.postMessage('関数呼び出し', 'http://example.com:8080')
      }
  });

まとめ

  1. Chromeではページを閉じる際のイベントbeforeunload、unload、pagehide、visibilitychangeは同期処理が許容されない
  2. 結果的に閉じるイベント内でjsspRpcを同期処理で使用している場合は改修が必要
  3. 子画面の閉じるイベントと連動して、親画面の処理は同期処理で済ませたい場合、別のデータ通信方法が必要