🚀

【解説】なぜExpo開発でディープリンクのURLスキームは三つのスラッシュ(///)を使うのか

に公開

AIに実装を任せていると、Expo開発でディープリンク実装で、myapp:///homeのように三つのスラッシュ(///)を提案して、「なぜ二つではなく三つのスラッシュなのか?」と疑問に思い、正誤が分からなかったので調べてみました。

公式ドキュメントを探してみたものの、明確な説明がなかなか見つからなかったので記事に残します。本記事では、この「三つのスラッシュ問題」について、Expoの公式な見解に基づいて解説します。

URLスキームの基本構造

URLの一般的な構造は次のようになっています:

scheme://authority/path?query#fragment

例えば、https://zenn.dev/articles/123?mode=edit#section1では:

  • scheme: https
  • authority(ホスト部分): zenn.dev
  • path: /articles/123
  • query: mode=edit
  • fragment: section1

三つのスラッシュが現れる理由

ディープリンクのURLスキームでは、通常ホスト部分が存在しないため、この部分が空になります。しかし、URL構造では scheme:// の後に何もなければ、それはパスの開始なのか、単にホスト部分が省略されているのかが曖昧になってしまいます。

そこで、RFC 3986(URI構文を定義する国際標準規格)に従い、ホスト部分が空の場合は次のような記法になります:

scheme:///path

この形式では、:// の後に何も記述せずに、すぐに三つ目のスラッシュでパスの開始を示しています。

ExpoでのURLスキームの変遷とRFC 3986への準拠

Expo SDK 37のアップデート前後でURLスキームの仕様が変わりました。GitHubのIssue(#10012)では、以前はmyapp://の形式で動作していたアプリが、アップデート後にmyapp:///の形式を要求するようになったことが報告されています。

この変更に対し、Expoの開発チームは以下のように明確に回答しています:

we changed this in SDK 37. Custom URIs with only 2 slashes aren't valid URIs, usually it consists of :///[/...]. In these custom URIs, we don't have a host and must leave that blank in order to comply with RFC 3986.

(訳:SDK 37でこの仕様を変更しました。二つのスラッシュだけのカスタムURIは有効なURIではありません。通常は :///[/...] の形式です。これらのカスタムURIではホストがないため、RFC 3986に準拠するためにその部分を空白にしておく必要があります。)

つまり、Expoの公式見解によれば:

  1. RFC 3986に準拠するための変更である
  2. ディープリンクではホスト部分が存在しないことが多い
  3. その場合、正しいURI形式は scheme:///path となる

RFC 3986の関連規定

Expoチームが言及している「RFC 3986への準拠」について、実際のRFC 3986の関連規定を見てみると:

RFC 3986のSection 3では、URIの一般構文を次のように定義しています:

URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]

hier-part = "//" authority path-abempty
          / path-absolute
          / path-rootless
          / path-empty

さらにRFC 3986の同セクションには以下のような重要な記述があります:

If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character.

つまり、authorityコンポーネント(ホスト部分)が存在する場合、そのパスは空かスラッシュ「/」で始まる必要があるということです。

モバイルアプリのディープリンクでは通常authorityが空なので:

myapp:///home

という形になり、三つ目のスラッシュはパスの開始を示すことになります。

Expoでの実装方法

Expoでは、以下のようにLinking.createURL()メソッドを使用すると、自動的に正しい形式のURLが生成されます:

// Expoの場合
import * as Linking from 'expo-linking';

// 例:'myapp:///profile' が生成される
const url = Linking.createURL('/profile');

Expo SDK 37以降では、この方法が推奨されています。

ディープリンクのURLスキームパターン

Expoの実装に基づくと、モバイルアプリのディープリンクにおいて、URLスキームのパターンは次のようになります:

myapp:///          // ホーム画面
myapp:///profile   // プロフィール画面
myapp:///settings  // 設定画面

ここでの三つ目のスラッシュは、空のホスト部分の後に続くパスの開始を示しています。

実装上の留意点

古いExpoコード(SDK 37以前)でmyapp://homeのようなURLを使用している場合は、myapp:///homeに修正することで、最新のExpo環境での安定した動作が期待できます。

また、URLスキームを実装する際は、次の点に注意しましょう:

  1. Expo SDK 37以降では、三つのスラッシュ形式(scheme:///path)を使用する
  2. アプリ内での動的なリンク生成にはLinking.createURL()を活用する
  3. 外部からアプリを開く場合も同様の形式のURLを使用する

まとめ

Expoにおいて、URLスキームで三つのスラッシュ(///)を使用するのは、Expo開発チームがRFC 3986に準拠した実装を選択したからです。特に:

  1. scheme://authority/pathの形式において
  2. ディープリンクではホスト部分(authority)が空になる
  3. その結果scheme:///pathという形式になる

この形式を使うことで、Expo環境でより安定した動作が期待できます。

次回Expoでディープリンクを実装する際には、この「三つのスラッシュ」を思い出してみてください。

参考資料

Discussion