同じドメイン名を利用して複数の PWA を構築し、同じ組織またはサービスに属していることをユーザーに認識させる方法。
マルチオリジン サイトにおけるプログレッシブ ウェブアプリに関するブログ投稿で、Demian は、複数のオリジンで構築されたサイトが、それらをすべて網羅する単一のプログレッシブ ウェブアプリを構築しようとする際に直面する課題について説明しています。
このタイプのサイト アーキテクチャの例として、次の条件を満たす e コマース サイトがあります。
- ホームページは
https://www.example.com
にあります。 - カテゴリ ページは
https://category.example.com
でホストされています。 https://product.example.com
の商品の詳細ページ。
この記事で説明したように、同一オリジン ポリシーにはいくつかの制限があり、オリジン間でのサービス ワーカー、キャッシュ、権限の共有を妨げます。そのため、このタイプの構成は避け、すでにこの方法でサイトを構築している場合は、可能な限り単一オリジン サイト アーキテクチャへの移行を検討することを強くおすすめします。

この記事では、その逆のケースについて説明します。異なるオリジンにまたがる単一の PWA ではなく、同じドメイン名を利用して複数の PWA を提供し、それらの PWA が同じ組織またはサービスに属していることをユーザーに認識させるというケースを分析します。
ご存じのとおり、ドメインやオリジンなど、異なるが関連する用語が使用されています。先に進む前に、これらのコンセプトを確認しましょう。
技術用語
- ドメイン: ドメイン ネーム システム(DNS)で定義されているラベルのシーケンス。たとえば、
com
とexample.com
はドメインです。 - ホスト名: 1 つ以上の IP アドレスに解決される DNS エントリ。たとえば、
www.example.com
はホスト名、example.com
は IP アドレスがある場合はホスト名、com
は IP アドレスに解決されないため、ホスト名にはなりません。 - オリジン: スキーム、ホスト名、(オプションで)ポートの組み合わせ。たとえば、
https://www.example.com:443
はオリジンです。
名前が示すように、同一オリジン ポリシーはオリジンに制限を課します。この記事では、この用語を主に使用します。ただし、さまざまな「オリジン」を作成するために、使用されている手法を表すために「ドメイン」または「サブドメイン」を使用します。
関連する複数の PWA を使用する場合
独立したアプリを構築しつつ、同じ組織または「ブランド」に属するものとして識別したい場合もあります。同じドメイン名を再利用する方法が、この関係を確立する良い方法です。次に例を示します。
- ある e コマース サイトが、販売者が在庫を管理できるようにスタンドアロン エクスペリエンスを作成したいと考えています。その際、在庫はユーザーが商品を購入するメインのウェブサイトに属していることを販売者に理解してもらいたいと考えています。
- スポーツニュース サイトが、大規模なスポーツ イベント向けの特定のアプリを作成したいと考えています。ユーザーが自分のお気に入りの試合の統計情報を通知で受け取れるようにし、プログレッシブ ウェブアプリとしてインストールできるようにします。また、ユーザーがニュース メディアが作成したアプリであると認識できるようにします。
- チャット、メール、カレンダーの個別のアプリを作成して、会社の名前に関連付けられた個別のアプリとして機能させたい。

個別のオリジンを使用する
このような場合は、概念的に異なるアプリごとに独自のオリジンで公開することをおすすめします。
すべてのドメイン内で同じドメイン名を使用する場合は、サブドメインを使用します。たとえば、複数のインターネット アプリやサービスを提供する企業は、https://mail.example.com
でメールアプリをホストし、https://calendar.example.com
でカレンダー アプリをホストしながら、ビジネスのメインサービスを https://www.example.com
で提供できます。別の例として、https://footballcup.example.com
のサッカー チャンピオンシップなど、重要なスポーツ イベントに専用に独立したアプリを作成したいスポーツ サイトがあります。このアプリは、https://www.example.com
でホストされているメインのスポーツ サイトとは別に、ユーザーがインストールして使用できます。このアプローチは、ユーザーが会社のブランドで独自の独立したアプリを作成できるプラットフォームにも役立ちます。たとえば、販売者が https://merchant1.example.com
、https://merchant2.example.com
などで独自の PWA を作成できるアプリなどです。
異なるオリジンを使用すると、アプリ間の分離が確実に行われるため、各アプリが次のような異なるブラウザ機能を個別に管理できます。
- インストール可能: 各アプリには独自のマニフェストがあり、独自のインストール可能なエクスペリエンスを提供します。
- ストレージ: 各アプリには独自のキャッシュ、ローカル ストレージ、基本的にはすべての種類のデバイスローカル ストレージがあり、他のアプリと共有されません。
- サービス ワーカー: 各アプリには、登録されたスコープ用の独自のサービス ワーカーがあります。
- 権限: 権限もオリジンでスコープされます。これにより、ユーザーはどのサービスに権限を付与しているかを正確に把握でき、通知などの機能が各アプリに適切に関連付けられます。
このようなレベルの分離を作成することは、複数の独立した PWA のユースケースで最も望ましいため、このアプローチを強くおすすめします。
サブドメイン上のアプリがローカルデータを相互に共有する場合でも、引き続き Cookie を介して共有できます。より高度なシナリオでは、サーバー経由でストレージを同期することを検討できます。

同じオリジンを使用する
2 つ目のアプローチは、同じオリジンに異なる PWA を構築する方法です。これには、次のシナリオが含まれます。
重複しないパス
同じオリジンでホストされ、パスが重複しない複数の PWA または概念的な「ウェブアプリ」。次に例を示します。
https://example.com/app1/
https://example.com/app2/
重複するパス/ネストされたパス
同じオリジンにある複数の PWA で、そのうちの 1 つのスコープが他のスコープ内にネストされている場合:
https://example.com/
(「外側のアプリ」)https://example.com/app/
(「内部アプリ」)
サービス ワーカー API とマニフェスト形式では、パスレベルのスコーピングを使用して、上記のいずれかを行うことができます。ただし、どちらの場合も、同じオリジンを使用すると多くの問題と制限が生じます。その根本的な原因は、ブラウザがこれらを明確に異なる「アプリ」と見なさないことです。そのため、このアプローチは推奨されません。

次のセクションでは、これらの課題について詳しく分析し、個別のオリジンを使用できない場合にできることについて説明します。
複数の同一オリジン PWA の課題
以下に、両方の同一オリジン アプローチに共通する実用的な問題を示します。
- ストレージ: Cookie、ローカル ストレージ、あらゆる種類のデバイスローカル ストレージは、アプリ間で共有されます。そのため、ユーザーが 1 つのアプリのローカルデータを消去すると、オリジンからすべてのデータが消去されます。1 つのアプリに対してのみ消去することはできません。Chrome やその他のブラウザでは、アプリの 1 つをアンインストールする際にローカルデータを消去するようユーザーに積極的にプロンプトが表示されます。これは、オリジン上の他のアプリのデータにも影響します。また、アプリはストレージ クォータも共有する必要があります。つまり、どちらかがスペースを使いすぎた場合、もう一方に悪影響が及ぶことになります。
- 権限: ブラウザの権限はオリジンに関連付けられています。つまり、ユーザーが 1 つのアプリに権限を付与すると、そのオリジンのすべてのアプリに同時に適用されます。これは良いことのように聞こえますが(権限を複数回リクエストする必要がない)、ユーザーが 1 つのアプリに対する権限をブロックすると、他のアプリがその権限をリクエストしたり、その機能を使用したりできなくなります。ブラウザの権限はオリジンごとに 1 回のみ付与する必要がある場合でも、システムレベルの権限は、複数のアプリが同じオリジンを参照しているかどうかにかかわらず、アプリごとに 1 回付与する必要があります。
- ユーザー設定: 設定はオリジンごとに設定されます。たとえば、2 つのアプリのフォントサイズが異なり、ユーザーがその差を補正するために 1 つのアプリのみでズームを調整したい場合、他のアプリにも設定を適用しない限り、その調整を行うことはできません。
こうした課題により、このアプローチを推奨することは困難です。ただし、別のオリジンを使用するで説明したように、別のオリジン(サブドメインなど)を使用できない場合は、重複するパスやネストされたパスではなく、重複しないパスを使用することを強くおすすめします。
前述のように、このセクションで説明する課題は、同じオリジンのアプローチの両方に共通しています。次のセクションでは、重複するパスやネストされたパスを使用することをおすすめしない理由について詳しく説明します。
重複するパスやネストされたパスに関するその他の課題
重複/ネストされたパスのアプローチ(https://example.com/
が外側のアプリで、https://example.com/app/
が内側のアプリ)の追加の問題は、内側のアプリのすべての 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 Mossholder(出典: Unsplash)