Help us understand the problem. What is going on with this article?

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

はじめに

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のおかげで意外と楽にできました。

Sr_Bangs
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした