LoginSignup
54
37

More than 3 years have passed since last update.

異なるドメイン間でlocalstorageを共有する方法

Last updated at Posted at 2019-10-21

はじめに

localStorageは基本的に同じドメイン内(厳密にはポート番号なども一致している必要がある)でしか有効ではありませんが、postMessage API(Web Messaging API)を使用することでクロスドメインでも共有することができます。

調べてみても古い記事が多かったり、サンプルのコードが無かったりだったので自分用の備忘録も兼ねてやり方をご紹介します。

構成

【ドメインA】
・localstorageのデータを持つ側。
・ドメインBからの要求に応じてlocalstorageの操作を行う。

【ドメインB】
・ドメインAに保存されているlocalstorageの値の参照や更新を要求する側。

(実際の動作確認はA側をGithub Pages、B側をローカルサーバーに置いた状態で行いました。)

ドメインA側

ドメインB側からのメッセージをトリガーにlocalstorageの操作を行っています。
(厳密にメッセージの中身を検証して処理を切り分けたりまではしていません。)

index.html
<body>
  <script>
    (function() {
      var origin = 'http://B.com';
      window.addEventListener('message', function(event) {
        // 送信元が指定のオリジンと一致していれば処理を行う
        if(event.origin === origin) {
          var message = event.data;

          // メッセージが'get'ならlocalstorageの値を返す
          if(message === 'get') {
            var storageData = localStorage.getItem('test');
            event.source.postMessage(storageData, event.origin);
          }
          // getでなければメッセージを分割してlocalstorageに保存する
          else {
            var messageArray = message.split(',');
            var key = messageArray[0];
            var value = messageArray[1];
            localStorage.setItem(key, value);
          }
        }
      });
    })();
  </script>
</body>

ドメインB側

display:noneで非表示にしたiframeでドメインA側のindex.htmlを読み込み、iframeObject.contentWindowでWindowオブジェクトを取得して、それに対してpostMessageでメッセージを送っています。

index.html
<body>
  <iframe id="iframe" src="http://A.com/index.html" style="display: none;"></iframe>
  <input type="text" name="text" id="text">
  <button id="set">ストレージに値を入れる</button>
  <button id="get">ストレージの値を取得する</button>
  <script>
  (function() {
    var iframeWindow = document.querySelector('#iframe').contentWindow;
    var $text = document.querySelector('#text');
    var $setButton = document.querySelector('#set');
    var $getButton = document.querySelector('#get');
    var origin = 'http://A.com';

    window.addEventListener('message', function(event) {
      // 送信元が指定のオリジンと一致していれば処理を行う
      if(event.origin === origin) {
        alert(event.data);
      }
    });

    $setButton.addEventListener('click', function() {
      // テキストエリアに入力されている値を送信
      iframeWindow.postMessage(`test,${$text.value}`, origin);
    });

    $getButton.addEventListener('click', function() {
      // localstorageの値の取得を要求するメッセージ送信
      iframeWindow.postMessage('get', origin);
    });

  })();
  </script>
</body>

以上になります。
もう少しややこしいロジックが必要かと思っていましたが、postMessage APIのおかげで意外と楽にできました。

54
37
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
54
37