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

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

Chase Phillips
Matt Giuca
Matt Giuca

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

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

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

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

サイトを複数のオリジンに分割し、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 を提供し、同じドメイン名を使用してそれらのアプリや PWA の関係を確立したいと考えています。

個別のオリジンを使用する

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

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

異なるオリジンを使用すると、アプリ間の分離が確実に行われるため、各アプリが次のような異なるブラウザ機能を個別に管理できます。

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

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

サブドメイン上のアプリ間でローカルデータを共有する場合でも、Cookie を使用してそれらのデータを共有することは可能です。より高度なシナリオでは、サーバーを介したストレージの同期を検討してください。

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

同じオリジンを使用する

2 つ目の方法は、同じオリジンに異なる PWA を作成する方法です。これには、次のシナリオが含まれます。

重複しないパス

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

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

重複するパス / ネストされたパス

同じオリジンにある複数の PWA で、そのうちの 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 回付与する必要があります。
  • ユーザー設定: 設定はオリジンごとに設定されます。たとえば、2 つのアプリでフォントサイズが異なり、ユーザーがその差を補正するために 1 つのアプリでのみズームを調整したい場合、その設定を他のアプリにも適用しない限り、調整できません。

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

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

重複するパスやネストされたパスに関するその他の課題

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

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

  • インストール プロモーション: ユーザーが内部アプリにアクセスした場合(ウェブブラウザなど)、外部アプリがユーザーのデバイスにすでにインストールされている場合、ブラウザにインストール プロモーション バナーは表示されず、BeforeInstallPrompt イベントはトリガーされません。これは、ブラウザが現在のページがすでにインストールされているアプリに属しているかどうかを確認し、属していると判断するためです。この問題を回避するには、内部アプリを手動でインストールするか(ブラウザのメニュー オプション「ショートカットを作成」を使用)、外部アプリの前に内部アプリをインストールします。
  • 通知Badging 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 Mosshold(出典: Unsplash