同じドメインで複数のプログレッシブ ウェブアプリを構築する

同じドメイン名を利用して複数の PWA を構築し、ユーザーが同じ組織またはサービスに属していることを認識できるようにする方法。

Chase Phillips
Demián Renzulli
Demián Renzulli
Matt Giuca
Matt Giuca

マルチオリジン サイトのプログレッシブ ウェブアプリに関するブログ投稿で、Demian は、複数のオリジンで構築されたサイトが、それらすべてを包含する単一のプログレッシブ ウェブアプリを構築しようとする際に直面する課題について説明しました。

このタイプのサイト アーキテクチャの例としては、次のような e コマースサイトがあります。

  • ホームページは https://www.example.com にあります。
  • カテゴリ ページは https://category.example.com でホストされています。
  • https://product.example.com の商品詳細ページ。

記事で説明したように、同一オリジン ポリシーにはいくつかの制限があり、オリジン間でサービス ワーカー、キャッシュ、権限を共有することはできません。そのため、このタイプの構成は避けることを強くおすすめします。また、この方法でサイトを構築している場合は、可能な限り単一オリジン サイト アーキテクチャへの移行を検討してください。

サイトが複数のオリジンに分割されていることを示す図。PWA を構築する際にこの手法は推奨されません。
統一されたプログレッシブ ウェブアプリを構築しようとする場合は、同じサイトのセクションに異なるオリジンを使用しないようにします。

この記事では、異なるオリジンにまたがる単一の PWA ではなく、同じドメイン名を利用して複数の PWA を提供し、それらの PWA が同じ組織またはサービスに属していることをユーザーに認識させたい企業を分析します。

お気づきかもしれませんが、ドメインやオリジンなど、異なるが相互に関連する用語を使用しています。先に進む前に、これらのコンセプトを確認しましょう。

技術用語

  • ドメイン: ドメイン ネーム システム(DNS)で定義されているラベルの任意のシーケンス。たとえば、comexample.com はドメインです。
  • ホスト名: 1 つ以上の IP アドレスに解決される DNS エントリ。たとえば、www.example.com はホスト名になります。example.com は IP アドレスがあればホスト名になります。com は IP アドレスに解決されないため、ホスト名にはなりません。
  • オリジン: スキーム、ホスト名、ポート(省略可)の組み合わせ。たとえば、https://www.example.com:443 はオリジンです。

その名のとおり、同一オリジン ポリシーはオリジンに制限を課すため、この記事では主にこの用語を使用します。ただし、さまざまな「オリジン」を作成するために使用される手法を説明する際には、「ドメイン」または「サブドメイン」という用語が使用されることがあります。

独立したアプリを構築しながら、同じ組織または「ブランド」に属するものとして識別したい場合があります。同じドメイン名を再利用することは、その関係を確立するうえで有効な方法です。次に例を示します。

  • e コマース サイトで、販売者が在庫を管理できるスタンドアロンのエクスペリエンスを作成したいと考えています。ただし、そのエクスペリエンスが、ユーザーが商品を購入するメインのウェブサイトに属していることを販売者が理解できるようにする必要があります。
  • スポーツ ニュース サイトが、主要なスポーツ イベント専用のアプリを構築したいと考えています。ユーザーが通知を通じてお気に入りの試合の統計情報を受け取れるようにし、プログレッシブ ウェブアプリとしてインストールできるようにしながら、ニュース会社が構築したアプリであることをユーザーが認識できるようにしたいと考えています。
  • 会社が、チャット、メール、カレンダーのアプリを別々に作成し、会社名に関連付けられた個別のアプリとして機能させたいと考えています。
統合されたプログレッシブ ウェブアプリを構築しようとする場合は、同じサイトのセクションに異なるオリジンを使用しないでください。
example.com を所有する会社が、同じドメイン名を使用して 3 つの独立したアプリまたは PWA を提供し、それらの関係を確立したいと考えています。

別のオリジンを使用する

このような場合におすすめの方法は、概念的に異なる各アプリを独自のオリジンで公開することです。

すべてのサイトで同じドメイン名を使用する場合は、サブドメインを使用します。たとえば、複数のインターネット アプリやサービスを提供する企業は、メールアプリを https://mail.example.com で、カレンダー アプリを https://calendar.example.com でホストし、ビジネスのメイン サービスを https://www.example.com で提供できます。別の例として、https://footballcup.example.com で開催されるサッカーの選手権などの重要なスポーツ イベント専用の独立したアプリを作成したいスポーツ サイトがあります。このアプリは、https://www.example.com でホストされているメインのスポーツ サイトとは別に、ユーザーがインストールして使用できます。このアプローチは、顧客が会社のブランドで独自の独立したアプリを作成できるプラットフォームにも役立つ可能性があります。たとえば、販売者が https://merchant1.example.comhttps://merchant2.example.com などで独自の PWA を作成できるアプリなどです。

異なるオリジンを使用すると、アプリ間の分離が保証されます。つまり、各アプリは次のブラウザ機能を個別に管理できます。

  • インストール可能性: 各アプリには独自の Manifest があり、独自のインストール可能なエクスペリエンスを提供します。
  • ストレージ: 各アプリは、他のアプリと共有することなく、独自のキャッシュ、ローカル ストレージ、デバイスローカル ストレージのすべての形式を基本的に備えています。
  • サービス ワーカー: 各アプリには、登録されたスコープ用の独自のサービス ワーカーがあります。
  • 権限: 権限もオリジンごとにスコープ設定されます。これにより、ユーザーはどのサービスに権限を付与しているかを正確に把握でき、通知などの機能が各アプリに適切に割り当てられます。

このような分離は、複数の独立した PWA のユースケースで最も望ましいので、このアプローチを強くおすすめします

サブドメインのアプリがローカルデータを共有したい場合は、引き続き Cookie を使用して共有できます。より高度なシナリオでは、サーバーを介してストレージを同期することを検討できます。

ALT_TEXT_HERE
サブドメインを使用して、異なるオリジンで異なる PWA をビルドすることをおすすめします。

同じオリジンを使用する

2 つ目のアプローチは、同じオリジンに異なる PWA を構築することです。これには、次のシナリオが含まれます。

重複しないパス

同じオリジンでホストされ、パスが重複していない複数の PWA または概念的な「ウェブアプリ」。次に例を示します。

  • https://example.com/app1/
  • https://example.com/app2/

パスの重複/ネスト

同じオリジンに複数の PWA があり、そのうちの 1 つのスコープがもう 1 つのスコープ内にネストされている場合:

  • https://example.com/(「外部アプリ」)
  • https://example.com/app/(「内部アプリ」)

サービス ワーカー API とマニフェスト形式を使用すると、パスレベルのスコープを使用して上記のいずれかを行うことができます。ただし、どちらの場合も、同じオリジンを使用すると多くの問題と制限が発生します。その根本原因は、ブラウザがこれらを別個の「アプリ」として完全に認識しないことにあります。そのため、このアプローチは推奨されません

ALT_TEXT_HERE
同じオリジンで 2 つの独立した PWA(「app1」、「app2」)を提供するためにパス(重複の有無を問わず)を使用することは推奨されません。

次のセクションでは、これらの課題と、別々のオリジンを使用できない場合の対処法について詳しく分析します。

複数の同一オリジン PWA の課題

以下に、同一オリジン アプローチに共通する実用的な問題を示します。

  • ストレージ: Cookie、ローカル ストレージ、デバイスローカル ストレージのすべての形式がアプリ間で共有されます。そのため、ユーザーが 1 つのアプリのローカルデータを消去すると、オリジンからすべてのデータが消去されます。1 つのアプリに対してのみ行うことはできません。Chrome などの一部のブラウザでは、アプリの 1 つをアンインストールする際に、ローカルデータを消去するようユーザーに積極的に促します。この場合、オリジンの他のアプリのデータも影響を受けます。もう 1 つの問題は、アプリがストレージ割り当てを共有する必要があることです。つまり、どちらかのアプリが過剰な容量を使用すると、もう一方のアプリに悪影響が及ぶことになります。
  • 権限: ブラウザの権限はオリジンに関連付けられています。つまり、ユーザーが 1 つのアプリに権限を付与すると、そのオリジン上のすべてのアプリに同時に適用されます。これは良いことのように聞こえるかもしれませんが(権限を複数回リクエストする必要がない)、ユーザーが 1 つのアプリの権限をブロックすると、他のアプリがその権限をリクエストしたり、その機能を使用したりできなくなることを覚えておいてください。ブラウザの権限はオリジンごとに 1 回付与するだけで済みますが、システムレベルの権限は、複数のアプリが同じオリジンを指しているかどうかに関係なく、アプリごとに 1 回付与する必要があります。
  • ユーザー設定: 設定はオリジンごとに設定されます。たとえば、2 つのアプリでフォントサイズが異なり、ユーザーがそのうちの 1 つのズームのみを調整して補正したい場合、他のアプリにも設定を適用しないと調整できません。

このような課題があるため、このアプローチを推奨することは困難です。ただし、別のオリジンを使用するで説明したように、別のオリジン(サブドメインなど)を使用できない場合は、提示した 2 つの同一オリジン オプションのうち、重複するパスやネストされたパスよりも、重複しないパスを使用することを強くおすすめします。

前述のように、このセクションで説明する課題は、同一オリジン アプローチの両方に共通しています。次のセクションでは、重複するパスやネストされたパスを使用することがおすすめできない戦略である理由について詳しく説明します。

パスの重複/ネストに関する追加の課題

パスの重複/ネスト化アプローチ(https://example.com/ が外部アプリ、https://example.com/app/ が内部アプリ)の追加の問題は、内部アプリのすべての URL が実際には外部アプリと内部アプリの両方の一部と見なされることです。

実際には、次のような問題が発生します。

  • インストール プロモーション: ユーザーがインナーアプリ(ウェブブラウザなど)にアクセスしたときに、アウターアプリがすでにユーザーのデバイスにインストールされている場合、ブラウザにはインストール プロモーション バナーは表示されず、BeforeInstallPrompt イベントもトリガーされません。これは、ブラウザが現在のページがすでにインストールされているアプリに属するかどうかを確認し、属すると判断するためです。この問題を回避するには、内側のアプリを手動でインストールする(ブラウザのメニュー オプションの [ショートカットを作成] を使用)か、外側のアプリの前に内側のアプリをインストールします。
  • 通知バッジ API: 外側のアプリはインストールされているが、内側のアプリはインストールされていない場合、内側のアプリからの通知とバッジは、外側のアプリ(インストールされているアプリの最も近い囲みスコープ)に誤って関連付けられます。この機能は、両方のアプリがユーザーのデバイスにインストールされている場合に正しく動作します。
  • リンクのキャプチャ: 外側のアプリが内側のアプリに属する URL をキャプチャする可能性があります。これは、外側のアプリはインストールされているが、内側のアプリはインストールされていない場合に特に起こりやすくなります。同様に、内部アプリにリンクする外部アプリ内のリンクは、外部アプリのスコープ内とみなされるため、内部アプリへのリンクキャプチャは行われません。また、ChromeOS と Android では、これらのアプリが Google Play ストアに追加されると(信頼できるウェブ アクティビティとして)、外部アプリがすべてのリンクをキャプチャします。内部アプリがインストールされている場合でも、OS はユーザーに外部アプリで開くという選択肢を提示します。

まとめ

この記事では、デベロッパーが同じドメイン内で互いに関連する複数のプログレッシブ ウェブアプリを構築する方法について説明しました。

まとめると、独立した PWA をホストするには、別のオリジン(サブドメインの使用など)を使用することを強くおすすめします。これらを同じオリジンでホストすると、ブラウザがこれらを別個のアプリとして完全に認識しないため、多くの問題が発生します。

  • 別のオリジン: 推奨
  • 同じオリジン、重複しないパス: 非推奨
  • 同じオリジン、重複するパス/ネストされたパス: 強く非推奨

異なるオリジンを使用できない場合は、重複しないパス(https://example.com/app1/https://example.com/app2/ など)を使用することが強く推奨されます。重複するパスやネストされたパス(外側のアプリの https://example.com/ や内側のアプリの https://example.com/app/ など)を使用するよりも、重複しないパスを使用する方が望ましいです。

参考情報

技術的なレビューと提案をしてくれた Joe Medley、Dominick Ng、Alan Cutter、Daniel Murphy、Penny McLachlan、Thomas Steiner、Darwin Huang に感謝します。

写真: Tim MossholderUnsplash