
当サイト、オリジナルWordPressプラグイン「OJapp PWA Marketing」を使用しています。
各記事は専用アイコンでホーム画面に追加できます。ぜひお試しください。
PWAを作っていると、こんな疑問が出てきます。
同じドメインから、PWAを2個、3個とインストールすることはできるのか?
例えば、サイト全体のアプリとは別に、ツールだけをホーム画面へ置きたい。さらに特定の商品ページや記事も、それぞれ別のアイコンとして置きたい。
Webには1つのドメインの中に大量のURLがあります。それなのにPWAだけ「1ドメイン=1アプリ」と決めてしまうと、少し窮屈です。
実際には、PWAの単位はドメインだけで決まるわけではありません。Web App Manifestのid、start_url、scope、そしてブラウザやOS側の実装が関係します。
さらに設計次第では、サイト単位、グループ単位、ページ単位だけでなく、ユーザーが選んだURLの状態をホーム画面の入口にすることもできます。
- 1 まずid・start_url・scopeは役割が違う
- 2 1S1Aならサイト全体を1つのPWAとして扱う
- 3 でも同じドメインに複数の機能がある
- 4 ディレクトリ単位なら1G1Aという考え方もできる
- 5 1S1Aの仕組みを使って1G1Aにもできる
- 6 さらに1P1Aを組み合わせることもできる
- 7 さらにユーザーが最後の状態を決めるUDA
- 8 UDAは1P1Aの「次の階層」というだけではない
- 9 同じページから複数のApp入口が生まれる
- 10 idは「起動するURL」ではない
- 11 scopeは「アプリのID」ではない
- 12 PWA LABではscopeが広すぎて別アプリ化できないケースもあった
- 13 同じドメインなら何個でも必ずインストールできる?
- 14 何を1つのAppと考えるか
- 15 1ドメインの中に複数のApp入口を作れる
まずid・start_url・scopeは役割が違う
この3つは一緒に出てくることが多いので混乱しやすいのですが、それぞれ役割が違います。
id:そのPWAを識別するためのIDstart_url:ホーム画面から起動した時に最初に開くURLscope:そのPWAとして扱うナビゲーション範囲
かなり大ざっぱに言えば、「誰なのか」「どこから始めるのか」「どこまでをアプリとして扱うのか」です。
似ているように見えますが、同じ設定ではありません。
1S1Aならサイト全体を1つのPWAとして扱う
一般的なPWAは、サイト全体を1つのアプリとして設計することが多いです。
例えば次のような構成です。
{
"id": "/",
"start_url": "/",
"scope": "/",
"display": "standalone"
}サイト全体を1つのサービスとして使うなら、とても分かりやすい設計です。
example.com
├─ /
├─ /news/
├─ /products/
├─ /account/
└─ /tools/
↓
1つのPWA私はこの考え方を1S1A(One Site. One App.)と呼んでいます。
1S1Aと1P1Aの違いでも紹介していますが、1S1Aと1P1Aはどちらが優れているという話ではありません。「何を1つのAppとして扱うか」の違いです。
でも同じドメインに複数の機能がある
問題は、1つのサイトの中に独立した機能が増えてきた時です。
example.com/
example.com/shop/
example.com/tools/
example.com/docs/サイト全体のPWAは欲しい。
でも/tools/は頻繁に使うので、ツール専用アプリとしてもホーム画面へ置きたい。
/docs/も独立したドキュメントアプリのように使いたい。
こうなると、「同じドメインだから全部1つ」という設計だけでは足りなくなります。
ディレクトリ単位なら1G1Aという考え方もできる
そこで使えるのが、私が1G1A(One Group. One App.)と呼んでいる設計です。
例えば/tools/を1つのグループとして扱うなら、次のように明示できます。
{
"id": "/tools/",
"start_url": "/tools/",
"scope": "/tools/",
"display": "standalone"
}/docs/なら、
{
"id": "/docs/",
"start_url": "/docs/",
"scope": "/docs/",
"display": "standalone"
}というように、それぞれ別の入口、識別情報、ナビゲーション範囲を持たせる設計ができます。
example.com/
└─ Site App
example.com/tools/
└─ Tools App
example.com/docs/
└─ Docs App同じオリジンの中でも、「サイト」「ツール群」「ドキュメント群」のようにAppの単位を分けて考えられるわけです。
1S1Aの仕組みを使って1G1Aにもできる
面白いのは、1G1Aのためにまったく別のPWA技術が必要なわけではないことです。
OJappでも、1G1Aは1S1A側の仕組みを利用し、id、start_url、scopeをディレクトリへ明示することで作れます。
<meta name='ojapp:id' content='/tools/'>
<meta name='ojapp:start-url' content='/tools/'>
<meta name='ojapp:scope' content='/tools/'>
<script src='https://ojapp.app/js/ojapp_1s1a.js'></script>つまり、1S1A用の仕組みを使うからといって、必ずルート/を1つのAppにしなければならないわけではありません。
Manifestの設計を変えれば、ディレクトリ単位の入口にもできます。
さらに1P1Aを組み合わせることもできる
ここからさらに細かくできます。
例えばサイト全体やツール群とは別に、特定のページだけをホーム画面へ置きたい場合です。
example.com/
└─ Site App(1S1A)
example.com/tools/
└─ Tools App(1G1A)
example.com/tools/timer/
└─ Timer(1P1A)
example.com/products/coffee/
└─ Coffee(1P1A)1P1A(One Page. One App.)では、サイト全体ではなくページを1つのApp単位として考えます。
タイマーならタイマーの名前とアイコン、商品なら商品画像と商品名というように、ページそのものをホーム画面の入口として扱えます。
詳しい考え方は1P1Aとは?1ページを1アプリとして扱うPWA設計でも整理しています。
つまり、1S1A・1G1A・1P1Aは必ずどれか1つだけを選ぶものではありません。
1つのWebサイトの中で、用途に合わせて複合させることもできます。
さらにユーザーが最後の状態を決めるUDA
ここからもう一段面白い使い方があります。
例えば、次のタイマーを1P1Aとしてホーム画面へ追加できるとします。
https://example.com/timer/これだけなら「タイマーページを1つのAppとして扱う」という1P1Aです。
でもWebでは、URLのクエリに現在の設定状態を持たせることができます。
/timer/?time=3&mode=down
/timer/?time=5&mode=down
/timer/?time=20&mode=up同じタイマーページでも、それぞれ意味が違います。
3分カウントダウン、5分カウントダウン、20分カウントアップ。
ここで、その設定済みURLを起動状態としてホーム画面へ追加できれば、同じページからさらに複数の入口を作れます。
Timer Page
├─ 3m ↓
├─ 5m ↓
└─ 20m ↑私はこの考え方をUDA(User Defined App)と呼んでいます。
UDAは1P1Aの「次の階層」というだけではない
ここは少し大事です。
URLだけを見ると、
Site
↓
Group
↓
Page
↓
Stateと細かくなっていくので、UDAが1P1Aのさらに下の階層のようにも見えます。
ただ、UDAの本質は単純な階層分けではありません。
最後のAppの状態を、サービス提供側ではなくユーザー自身が決める。
そこがポイントです。
開発者はタイマーというWeb機能を提供する。
ユーザーは「5分・カウントダウン」のように自分が使いたい状態を選ぶ。
その結果できたURLを、そのまま自分専用のホーム画面入口として追加する。
Developer
↓
タイマー機能を提供
↓
User
↓
5分・カウントダウンを選択
↓
/timer/?time=5&mode=down
↓
ホーム画面へ追加つまりUDAは、1P1Aの次の階層というより、ユーザーがURLの状態を選ぶことで自分のApp入口を定義する考え方です。
1P1Aのようなページ単位の設計と組み合わせながら、最後の設定をユーザーに決めてもらう形でホーム画面へ追加してもらうこともできます。
UDAについてはPWA UDA(User Defined App)とは?ユーザーが自分のAppを定義する新しい設計思想でも詳しく紹介しています。
同じページから複数のApp入口が生まれる
この考え方まで入れると、「同じドメインから複数インストール」という話がかなり広がります。
example.com/
└─ Site App
example.com/tools/
└─ Tools App
example.com/tools/timer/
└─ Timer App
example.com/tools/timer/?time=3&mode=down
└─ 3m ↓ Timer
example.com/tools/timer/?time=20&mode=up
└─ 20m ↑ Timer最初は「同じドメインから複数のPWAを作れるか?」という話だったのに、最終的には同じページの同じ機能から、ユーザーの設定によって複数のホーム画面入口を作るところまで考えられます。
ただし、クエリを含むPWAの識別や複数インストールの扱いはブラウザやプラットフォームによって差が出る可能性があります。
OJappではクエリを利用した構成を用意していますが、特に複数インストールを前提にする場合は対象端末で実際に確認するのが安全です。
idは「起動するURL」ではない
複数PWAを考える時に特に混乱しやすいのがidです。
idはホーム画面から開くURLを指定するものではありません。
起動先はstart_urlです。
idは、そのPWAの識別情報として使われます。
{
"id": "/tools/",
"start_url": "/tools/dashboard/"
}このように、識別情報と起動先を別々に設計できます。
明示的な安定したidを持たせれば、後からstart_urlを変更しても同じPWAとして識別させる設計ができます。
逆に、有効なidを省略した場合は、Manifest仕様上、実効的なstart_urlが識別情報のフォールバックとして使われます。
ただし、idだけを変えれば、あらゆるブラウザやOSで必ず複数インストールできる、と考えるのは危険です。
最終的なインストールの扱いにはブラウザやプラットフォーム側の実装も関係します。
scopeは「アプリのID」ではない
scopeも、アプリを識別するIDそのものではありません。
Manifestのscopeは、そのPWAとして扱うナビゲーション範囲を示します。
{
"start_url": "/tools/",
"scope": "/tools/"
}なら、/tools/以下をそのPWAのナビゲーション範囲として扱う設計です。
ここで注意したいのが、ManifestのscopeとService Workerのscopeは別物だということです。
ManifestのscopeはPWAのナビゲーション範囲。Service Workerのscopeは、そのService Workerが制御できるページやリクエストの範囲です。
名前が同じなので非常に紛らわしいですが、役割は違います。
PWA LABではscopeが広すぎて別アプリ化できないケースもあった
このあたりは仕様だけ読んでいるより、実際に複数のPWAを同じドメインへ置いた時の方が分かりやすいです。
PWA LABでは、同じドメイン配下にある別々のWeb機能をAndroidでホーム画面へ追加する検証をしていました。
ところが、それぞれ別のものとして追加したかったのに、両方のManifestで広いscope: "/"を使っていた構成では、Android側で期待したように別々のアプリとして扱えないケースがありました。
そこで現在の1P1A系の構成では、Androidでページごとの入口を作りたい場合に固定された広いscopeを持たせない設計も使っています。
一方、iPhoneではscopeを明示した方がホーム画面Webアプリ内の表示を整えやすいケースも実機で確認しています。
そのためOJappの実装では、用途によってiOSとAndroidでManifestの構成を変える方法も検証してきました。
これは「Androidではscopeを書いてはいけない」という一般ルールではありません。
同一ドメインに複数の入口を作るという特殊な設計で、PWA LABが実際に使っている構成の1つです。
同じドメインなら何個でも必ずインストールできる?
ここまで読むと、「じゃあidやscopeを変えれば、同じドメインから何個でもPWAを入れられるのでは?」と思うかもしれません。
そこまでは断定できません。
PWAのインストールやホーム画面追加は、Web App Manifestだけで最終的な挙動が決まるわけではないからです。
ブラウザ、OS、ManifestのURL、id、start_url、scopeなどの組み合わせによって扱いが変わる可能性があります。
特にiPhoneの「ホーム画面に追加」とAndroid ChromeのPWAインストールは、同じ操作に見えても挙動まで完全に同じではありません。
そのため、複数インストールを前提にした設計では対象端末での実機確認が重要です。
何を1つのAppと考えるか
結局、この話で一番大事なのはManifestの項目を暗記することではないと思っています。
まず、何を1つのAppとしてホーム画面へ置きたいのかを考えます。
Site
→ 1S1A
Group
→ 1G1A
Page
→ 1P1Aそして、さらにURLが状態を持つWeb機能なら、ユーザー自身が最後の状態を決めるUDAという考え方も使えます。
Site → 1S1A
Group → 1G1A
Page → 1P1A
User selects a State
↓
UDAUDAだけは単純な階層ではありません。
開発者が完成したAppを全部決めるのではなく、開発者はWeb機能を用意し、最後にユーザーが自分の使い方をURLとして定義する。
そのURLをホーム画面へ置けば、ユーザー自身が作った入口になります。
1ドメインの中に複数のApp入口を作れる
サイト全体を1つのAppとして使う。
その中のツール群だけを別のAppとして使う。
さらに特定のページを1つのAppとして使う。
そして対応するWeb機能なら、最後の設定をユーザーに選んでもらい、その状態を自分専用の入口としてホーム画面へ置いてもらう。
こう考えると、PWAは必ずしも「Webサイトを丸ごとアプリにする技術」だけではありません。
同じドメインの中でも、Site・Group・Pageという単位を使い分け、さらにUDAではユーザーが選んだURLの状態までホーム画面の入口にできます。
Webにもともと存在するURLという仕組みを、そのままAppの入口として使う。
私はこの設計の自由さが、PWAのかなり面白いところだと思っています。
GoogleでOJapp Tipsを優先する情報源に追加
今後、Google検索でOJapp Tipsの記事を見つけやすくできます。

たった1行貼るだけで今すぐPWA化【無料】✨



