マルチオリジン サイトでのプログレッシブ ウェブアプリ

マルチオリジン サイトでプログレッシブ ウェブアプリを構築する際の課題と回避策。

Demián Renzulli
Demián Renzulli

公開日: 2019 年 8 月 19 日

以前は、マルチオリジン アーキテクチャを使用するメリットがいくつかありました。プログレッシブ ウェブアプリの場合、このアプローチには多くの課題があります。特に、同一生成元ポリシーは、サービス ワーカーやキャッシュ、権限などの共有や、複数の生成元にわたるスタンドアロン エクスペリエンスの実現に制限を課します。

複数のオリジンの良い使い方と悪い使い方を説明し、マルチオリジン サイトでプログレッシブ ウェブアプリを構築する際の課題と回避策について説明します。

複数のオリジンの良い使用例と悪い使用例

サイトがマルチオリジン アーキテクチャを採用する正当な理由はいくつかあります。そのほとんどは、独立した一連のウェブ アプリケーションを提供することや、完全に分離されたエクスペリエンスを作成することに関連しています。避けるべき使用方法もあります。

メリット

まず、有用な理由を見てみましょう。

  • ローカライズ / 言語: 国コード トップレベル ドメインを使用して、異なる国で提供されるサイトを分離する(例: https://www.google.com.ar)、またはサブドメインを使用して、異なる地域をターゲットとするサイトを分割する(例: https://newyork.craigslist.org)または特定の言語(https://en.wikipedia.org など)のコンテンツを提供する場合。

  • 独立したウェブアプリ: メインオリジンのサイトとは目的が大きく異なるエクスペリエンスを提供するために、異なるサブドメインを使用している。たとえば、ニュースサイトでは、クロスワード パズルのウェブアプリを https://crosswords.example.com から意図的に配信し、メインのウェブサイトとリソースや機能を共有することなく、独立した PWA としてインストールして使用できます。

デメリット

これらのいずれも行っていない場合は、プログレッシブ ウェブアプリの構築時にマルチオリジン アーキテクチャを使用すると、デメリットが生じる可能性があります。

にもかかわらず、多くのサイトでは、特に理由もなく、または「レガシー」な理由で、このような構造が維持されています。たとえば、統一されたエクスペリエンスの一部であるべきサイトの一部を、サブドメインを使用して任意に分離するなどが挙げられます。

たとえば、次のパターンは避けることを強くおすすめします。

  • サイトのセクション: サイトのさまざまなセクションをサブドメインに分離します。ニュースサイトでは、ホームページが https://www.example.com にあり、スポーツ セクションが https://sports.example.com、政治が https://politics.example.com にあるといったことは珍しくありません。e コマース サイトの場合、商品カテゴリに https://category.example.com、商品ページに https://product.example.com などを使用します。

  • ユーザーフロー: サイトのさまざまな小さな部分(ログイン フローや購入フローのページなど)をサブドメインに分割することも、おすすめできません。たとえば、https://login.example.comhttps://checkout.example.com を使用します。

単一オリジンへの移行が不可能な場合は、プログレッシブ ウェブアプリの構築時に考慮できる課題と(可能な場合は)回避策のリストを以下に示します。

さまざまなオリジンにわたる PWA の課題と回避策

複数のオリジンでウェブサイトを構築する場合、統一された PWA エクスペリエンスを提供することは困難です。その主な理由は、同一生成元ポリシーによって多くの制約が課せられるためです。1 つずつ見ていきましょう。

Service Worker

サービス ワーカー スクリプト URL のオリジンは、register() を呼び出すページのオリジンと同じである必要があります。つまり、たとえば、https://www.example.com のページは、https://section.example.com のサービス ワーカー URL を使用して register() を呼び出すことはできません。

もう 1 つの考慮事項は、Service Worker が制御できるのは、その Service Worker が属するオリジンとパスでホストされているページのみであることです。つまり、Service Worker が https://www.example.com でホストされている場合、そのオリジンからの URL のみを制御できます(スコープ パラメータで定義されたパスに従って)。たとえば、https://section.example.com のような他のサブドメインのページは制御できません。

この場合、回避策は複数のサービス ワーカー(オリジンごとに 1 つ)を使用することだけです。

キャッシュ

Cache オブジェクト、indexedDB、localStorage も単一のオリジンに制限されます。つまり、https://www.section.example.com などから https://www.example.com に属するキャッシュにアクセスすることはできません。

このようなシナリオでキャッシュを適切に管理するには、次の方法があります。

  • ブラウザ キャッシュを活用する: 従来のブラウザ キャッシュのベスト プラクティスを使用することを常に推奨します。この手法には、サービス ワーカーのキャッシュでは実現できない、オリジン間でキャッシュ保存されたリソースを再利用できるというメリットもあります。サービス ワーカーで HTTP キャッシュを使用する方法に関するベスト プラクティスについては、こちらの投稿をご覧ください。

  • サービス ワーカーのインストールを軽量に保つ: 複数のサービス ワーカーを維持している場合は、ユーザーが新しいオリジンに移動するたびに大きなインストール費用を支払うことがないようにしてください。つまり、絶対に必要となるリソースのみをプリキャッシュします。

権限

権限はオリジンにもスコープ設定されます。つまり、ユーザーがオリジン https://section.example.com に特定の権限を付与した場合、その権限は https://www.example.com などの他のオリジンには引き継がれません。

オリジン間で権限を共有する方法がないため、この場合の唯一の解決策は、特定の機能(位置情報など)が必要なサブドメインごとに権限をリクエストすることです。ウェブプッシュなどの場合、別のサブドメインでユーザーが権限を承認したかどうかを追跡する Cookie を維持して、再度リクエストしないようにすることができます。

インストール

PWA をインストールするには、各オリジンに、それ自体に対する相対パスである start_url を含む独自のマニフェストが必要です。つまり、特定のオリジン(https://section.example.com など)でインストール プロンプトを受け取ったユーザーは、別のオリジン(https://www.example.com など)で start_url を使用して PWA をインストールすることはできません。言い換えれば、サブドメインでインストール プロンプトを受け取ったユーザーは、アプリのメイン URL ではなく、サブページの PWA のみをインストールできます。

また、各サブドメインがインストール条件を満たし、ユーザーに PWA のインストールを求める場合、同じユーザーがサイトを移動するたびに複数のインストール プロンプトを受け取るという問題もあります。

この問題を軽減するには、プロンプトがメインのオリジンでのみ表示されるようにします。ユーザーがインストール条件を満たすサブドメインにアクセスした場合:

  1. beforeinstallprompt イベントをリッスンします
  2. プロンプトが表示されないようにするevent.preventDefault() を呼び出します。

これにより、サイトの意図しない部分にプロンプトが表示されないようにしながら、メインのオリジン(ホームページなど)には引き続き表示できます。

スタンドアロン モード

スタンドアロン ウィンドウでナビゲーションを行う場合、ユーザーが PWA のマニフェストで設定されたスコープ外に移動すると、ブラウザの動作が変わります。この動作は、ブラウザのバージョンとベンダーによって異なります。たとえば、最新の Chrome バージョンでは、ユーザーがスタンドアロン モードでスコープ外に移動すると、Chrome カスタムタブが開きます。

ほとんどの場合、この問題に対する解決策はありませんが、サブドメインでホストされているエクスペリエンスの一部(ログイン ワークフローなど)については、回避策を適用できます。

  1. 新しい URL https://login.example.com が全画面 iframe 内で開く可能性があります。
  2. iframe 内でタスク(ログイン プロセスなど)が完了すると、postMessage() を使用して、iframe から親ページに結果情報を渡すことができます。
  3. 最後に、メッセージがメインページで受信されたら、リスナーを登録解除して、iframe を DOM から削除します。

まとめ

同一生成元ポリシーは、複数のオリジン上に構築されたサイトで一貫性のある PWA エクスペリエンスを実現しようとする場合に、多くの制限を課します。そのため、ユーザーに最高の体験を提供するため、サイトを異なるオリジンに分割することは強くおすすめしません。

すでにこの方法で構築されている既存のサイトでは、マルチオリジン PWA を正しく動作させるのは難しいかもしれませんが、いくつかの回避策を検討しました。それぞれにトレードオフがあるため、ウェブサイトでどの方法を採用するかは、状況に応じてご判断ください。

長期的な戦略やサイトの再設計を評価する際は、マルチオリジン アーキテクチャを維持する重要な理由がない限り、単一オリジンへの移行を検討してください。

技術的なレビューと提案をしてくださった Penny Mclachlan、Paul Covell、Dominick Ng、Alberto Medina、Pete LePage、Joe Medley、Cheney Tsai、Martin Schierle、Andre Bandarra に感謝いたします。