ホスティング動作を構成する

Firebase Hosting では、カスタム エラーページリダイレクトリライトヘッダーなど、カスタマイズされたホスティング動作を構成できます。プロジェクト ディレクトリから Firebase プロジェクトにデプロイするファイルを指定することもできます。

firebase.json ファイルで Firebase Hosting の構成を定義します。

firebase.json ファイルは、プロジェクト ディレクトリのルートにあります。firebase init コマンドを実行すると、Firebase は firebase.json ファイルを自動的に作成します。

このページの最後に、firebase.json の構成例(Firebase Hosting のみを対象)を紹介します。firebase.json ファイルには、他の Firebase サービスの構成も定義できます。

Hosting REST API を使用すると、デプロイされる firebase.json コンテンツを確認できます。

Hosting のレスポンスの優先順位

このページで説明する Firebase Hosting 構成オプションが競合する場合があります。競合が発生した場合、Hosting からのレスポンスは次の優先順位に従って決定されます。

  1. /__/* パスセグメントで始まる予約済みの名前空間
  2. リダイレクトの構成
  3. 正確に一致する静的コンテンツ
  4. リライトの構成
  5. カスタムの 404 ページ
  6. デフォルトの 404 ページ

デプロイするファイルを指定する

デフォルトの firebase.json ファイルに含まれるデフォルトの属性(publicignore)により、プロジェクト ディレクトリ内のどのファイルが Firebase プロジェクトにデプロイされるのかが決まります。

firebase.json ファイルのデフォルトの hosting 構成は次のようになります。

"hosting": {
  "public": "public",  // the only required attribute for hosting
  "ignore": [
    "firebase.json",
    "**/.*",
    "**/node_modules/**"
  ]
}

public

必須
public 属性には、Firebase Hosting にデプロイするディレクトリを指定します。デフォルト値は public という名前のディレクトリですが、プロジェクト ディレクトリ内に存在している任意のディレクトリのパスを指定できます。

デプロイするディレクトリのデフォルト名は次のとおりです。

"hosting": {
  "public": "public"

  // ...
}

デフォルト値は、デプロイするディレクトリに変更できます。

"hosting": {
  "public": "dist/app"

  // ...
}

ignore

省略可
ignore 属性には、デプロイ時に無視するファイルを指定します。Git.gitignore と同じように glob パターンを使用できます。

無視するファイルのデフォルト値は次のとおりです。

"hosting": {
  // ...

  "ignore": [
    "firebase.json",  // the Firebase configuration file (this file)
    "**/.*",  // files with a leading period should be hidden from the system
    "**/node_modules/**"  // contains dependencies used to create your site but not run it
  ]
}

404 / Not Found ページをカスタマイズする

省略可
存在しないページにユーザーがアクセスしようとしたときに、カスタム 404 Not Found エラーを表示するように指定できます。

プロジェクトの public ディレクトリに新しいファイルを作成し、404.html という名前を付けて、カスタムの 404 Not Found コンテンツをそのファイルに追加します。

ブラウザでドメインまたはサブドメインに 404 Not Found エラーが発生した場合、Firebase Hosting はこのカスタム 404.html ページのコンテンツを表示します。

リダイレクトを構成する

省略可
URL リダイレクトは、ページの移動や URL の短縮でリンクが無効にならないようにするために使用します。たとえば、ブラウザを example.com/team から example.com/about.html にリダイレクトできます。

URL リダイレクトを指定するには、firebase.json ファイルの hosting 内に redirects 属性を使用します。次に例を示します。

"hosting": {
  // ...

  // Add the "redirects" attribute within "hosting"
  "redirects": [ {
    // Returns a permanent redirect to "/bar" for requests to "/foo" (but not "/foo/**")
    "source": "/foo",
    "destination": "/bar",
    "type": 301
  }, {
    // Returns a permanent redirect to "/bar" for requests to both "/foo" and "/foo/**"
    "source": "/foo{,/**}"
    "destination": "/bar"
    "type": 301
  }, {
    // Returns a temporary redirect for all requests to files or directories in the "firebase" directory
    "source": "/firebase/**",
    "destination": "https://firebase.google.com/",
    "type": 302
  } ]
}

redirects 属性にはリダイレクト ルールの配列が含まれます。ルールには以下が必ず含まれます。

  • glob パターンを指定する source

  • 静的 URL の destination。相対パスまたは絶対パスを指定できます。

  • HTTP レスポンス コードを指定する type

Firebase Hosting は、各リクエストの開始時(ファイルまたはフォルダがそのパスに存在するかどうかをブラウザが判断する前)に source 値とすべての URL パスを比較します。一致が見つかった場合、Firebase Hosting のオリジン サーバーが HTTP リダイレクト レスポンスを送信し、destination URL に新しいリクエストを送信するようにブラウザに指示します。

最後に、表示する特定の HTTP レスポンス コードを type 値に指定します。「Moved Permanently」の場合は 301、「Found」(Temporary Redirect)の場合は 302 を指定します。

リダイレクト用の URL セグメントをキャプチャする

省略可
場合によっては、リダイレクト source URL の特定のセグメントをキャプチャしてから、このセグメントをリダイレクト destination URL で再利用する必要があります。

これらのセグメントは、セグメントを識別する : プレフィックスを追加することでキャプチャできます。セグメントの後の残りの URL パスもキャプチャする必要がある場合は、セグメントの直後に * を使用します。次に例を示します。

"hosting": {
  // ...

  "redirects": [ {
    "source": "/blog/:post*",  // captures the entire URL segment beginning at "post"
    "destination": "https://blog.myapp.com/:post", // includes the entire URL segment identified and captured by the "source" value
    "type": 301
  }, {
    "source": "/users/:id/profile",  // captures only the URL segment "id", but nothing following
    "destination": "/users/:id/newProfile",  // includes the URL segment identified and caputured by the "source" value
    "type": 301
  } ]
}

リライトを構成する

省略可
リライトは、複数の URL で同じコンテンツを表示するために使用します。パターンに一致する URL を受け取って、クライアント側コードで表示内容を決定するようにできるため、パターン マッチングで使用すると特に有用です。

リライトを使用すると、ナビゲーションに HTML5 pushState を使用するアプリをサポートできます。指定された source URL をブラウザで開こうとすると、destination URL にあるファイルのコンテンツが表示されます。

URL リライトを指定するには、firebase.json ファイルの hosting 内に rewrites 属性を使用します。次に例を示します。

"hosting": {
  // ...

  // Add the "rewrites" attribute within "hosting"
  "rewrites": [ {
    // Serves index.html for requests to files or directories that do not exist
    "source": "**",
    "destination": "/index.html"
  }, {
    // Serves index.html for requests to both "/foo" and "/foo/**"
    // Using "/foo/**" only matches paths like "/foo/xyz", but not "/foo"
    "source": "/foo{,/**}",
    "destination": "/index.html"
  }, {
    // Excludes specified pathways from rewrites
    "source": "!/@(js|css)/**",
    "destination": "/index.html"
  } ]
}

rewrites 属性にはリライトルールの配列が含まれます。ルールには以下が必ず含まれます。

  • glob パターンを指定する source

  • destination(存在するローカル ファイル)

Firebase Hosting は、指定された source にファイルまたはディレクトリが存在しない場合にのみリライトルールを適用します。ルールがトリガーされると、ブラウザは HTTP リダイレクトではなく、指定された destination ファイルの実際のコンテンツを返します。

関数にリクエストを送信する

rewrites を使用すると、Firebase Hosting の URL から関数を提供できます。次のコードは、Cloud Functions を使用して動的コンテンツを提供する部分を表しています。

たとえば、Hosting サイトの /bigben ページからすべてのリクエストを送信して bigben 関数を実行する場合は、次のようになります。

"hosting": {
  // ...

  // Add the "rewrites" attribute within "hosting"
  "rewrites": [ {
    "source": "/bigben",
    "function": "bigben"
  } ]
}

このリライトルールを追加して Firebase にデプロイすると(firebase deploy を使用)、次の URL から関数にアクセスできるようになります。

  • Firebase のサブドメイン: projectID.web.app/bigbenprojectID.firebaseapp.com/bigben

  • 接続されたカスタム ドメイン: custom-domain/bigben

Cloud Run コンテナにリクエストを送信する

rewrites を使用すると、Firebase Hosting の URL から Cloud Run コンテナにアクセスできます。次のコードは、Cloud Run を使用して動的コンテンツを提供する部分を表しています。

たとえば、Hosting サイトのページ(/helloworld)からのすべてのリクエストを送信して、helloworld コンテナ インスタンスの起動と実行をトリガーする場合は、次のようにします。

"hosting": {
 // ...

 // Add the "rewrites" attribute within "hosting"
 "rewrites": [ {
   "source": "/helloworld",
   "run": {
     "serviceId": "helloworld",  // "service name" (from when you <a href="#deploy">deployed the container image)</a>
     "region": "us-central1"     // optional (if omitted, default is us-central1)
   }
 } ]
}

このリライトルールを追加して Firebase にデプロイすると(firebase deploy を使用)、次の URL からコンテナ イメージにアクセスできるようになります。

  • Firebase のサブドメイン: projectID.web.app/helloworldprojectID.firebaseapp.com/helloworld

  • 接続されたカスタム ドメイン: custom-domain/helloworld

rewrites を使用して、カスタム ドメインの Dynamic Links を作成できます。Dynamic Links にカスタム ドメインを設定する方法については、Dynamic Links のドキュメントをご覧ください。

例:

  • Dynamic Links にのみドメインを使用する

    "hosting": {
      // ...
    
      "appAssociation": "AUTO",  // required for Dynamic Links (default is AUTO if not specified)
    
      // Add the "rewrites" attribute within "hosting"
      "rewrites": [ {
        "source": "/**",  // Dynamic Links start with "https://<your-domain>/"
        "dynamicLinks": true
      } ]
    }
    
  • Dynamic Links に使用するパス プレフィックスを指定する

    "hosting": {
      // ...
    
      "appAssociation": "AUTO",  // required for Dynamic Links (default is AUTO if not specified)
    
      // Add the "rewrites" attribute within "hosting"
      "rewrites": [ {
        "source": "/promos/**",  // Dynamic Links can start with "https://<your-domain>/promos/"
        "dynamicLinks": true
      }, {
        "source": "/links/share/**",  // Dynamic Links can start with "https://<your-domain>/links/share/"
        "dynamicLinks": true
      } ]
    }
    

firebase.json ファイルに Dynamic Links を構成するには、次のことを行う必要があります。

  • appAssociation 属性を AUTO に設定する。

    • この属性を構成に追加しないと、appAssociation のデフォルトは AUTO になります。
    • この属性を AUTO に設定すると、Hosting はリクエストされたときに assetlinks.jsonapple-app-site-association のファイルを動的に生成します。
  • Dynamic Links の rewrites 属性にリライトルールの配列を指定する。ルールには以下が必ず含まれます。

    • source。Dynamic Links に使用するパスを指定します。

      • URL のパスを書き換えるルールとは異なり、Dynamic Links の書き換えルールに正規表現を含めることはできません。
    • dynamicLinks 属性。true に設定します。

ヘッダーを構成する

省略可
ヘッダーを使用すると、クライアントとサーバーはリクエストまたはレスポンスと一緒に追加情報を渡すことができます。ヘッダーの一部は、ブラウザがページとそのコンテンツを処理する方法(アクセス制御、認証、キャッシュ、エンコードなど)に影響を与える可能性があります。

ファイル固有のカスタム レスポンス ヘッダーを指定するには、firebase.json ファイルの hostingheaders 属性を使用します。次に例を示します。

"hosting": {
  // ...

  // Add the "headers" attribute within "hosting"
  "headers": [ {
    // Specifies a CORS header for all font files
    "source": "**/*.@(eot|otf|ttf|ttc|woff|font.css)",
    "headers": [ {
      "key": "Access-Control-Allow-Origin",
      "value": "*"
    } ]
  }, {
    // Overrides the default 1 hour browser cache with a 2 hour cache for all image files
    "source": "**/*.@(jpg|jpeg|gif|png)",
    "headers": [ {
      "key": "Cache-Control",
      "value": "max-age=7200"
    } ]
  }, {
    // Sets the cache header for 404 pages to cache for 5 minutes
    "source": "404.html",
    "headers": [ {
      "key": "Cache-Control",
      "value": "max-age=300"
    } ]
  } ]
}

headers 属性には定義の配列が含まれます。定義には以下が必ず含まれます。

  • リライトルールに関係なく、Hosting が元のリクエストパスと照合する source 値。

  • Hosting がリクエストパスに適用する(サブ)headers の配列。サブヘッダーの配列には、指定された keyvalue が必ず含まれます。

動的コンテンツの提供とマイクロサービスのホスティングの詳細については、Hosting セクションの Cache-Control をご覧ください。

また、CORS ヘッダーの詳細も確認してください。

.html 拡張子を制御する

省略可
cleanUrls 属性を使用すると、URL に .html 拡張子を含めるかどうかを制御できます。

true の場合、Hosting はアップロードされたファイルの URL から拡張子 .html を自動的に削除します。.html 拡張子がリクエストに追加された場合、Hosting は同じパスへの 301 リダイレクトを実行しますが、.html 拡張子は削除されます。

.html 拡張子を含めるには、firebase.json ファイルの hostingcleanUrls 属性を使用します。次に例を示します。

"hosting": {
  // ...

  // Add the "cleanUrls" attribute within "hosting"
  "cleanUrls": true
}

末尾のスラッシュを制御する

省略可
trailingSlash 属性を使用すると、URL に末尾のスラッシュを含めるかどうかを制御できます。

  • true の場合、Hosting は URL のリダイレクトで末尾のスラッシュを追加します。
  • false の場合、Hosting は URL のリダイレクトで末尾のスラッシュを削除します。
  • 指定しない場合、Hosting はディレクトリ インデックス ファイル(たとえば、about/index.html)にのみ末尾にスラッシュを追加します。

末尾にスラッシュを含めるには、firebase.json ファイルの hostingtrailingSlash 属性を使用します。次に例を示します。

"hosting": {
  // ...

  // Add the "trailingSlash" attribute within "hosting"
  "trailingSlash": false
}

glob パターン マッチング

Firebase Hosting 構成オプションでは、Git で gitignore ルールを処理する場合や Bowerignore ルールを処理する場合と同様に、extglob を使用する glob パターン マッチング表記を使用します。より詳しい参考資料としては、こちらの Wiki ページをご覧ください。以下では、このページで使用した例について説明します。

  • firebase.json - public ディレクトリのルートにある firebase.json ファイルにのみ一致します。

  • ** - 任意のサブディレクトリ内にあるファイルまたはフォルダと一致します。

  • * - public ディレクトリのルートにあるファイルとフォルダにのみ一致します。

  • **/.* - 任意のサブディレクトリ内にある「.」で始まるファイル(通常は .git フォルダ内などにある非表示ファイル)と一致します。

  • **/node_modules/** - node_modules フォルダの任意のサブディレクトリ内にあるファイルまたはフォルダと一致します。このフォルダ自体が public ディレクトリの任意のサブディレクトリとなります。

  • **/*.@(jpg|jpeg|gif|png) - 任意のサブディレクトリ内にあるファイルで、.jpg.jpeg.gif.png のいずれかで終了するものと一致します。

Hosting の完全な構成の例

以下に、Firebase Hosting の完全な firebase.json 構成例を示します。firebase.json ファイルには、他の Firebase サービスの構成も定義できます。

{
  "hosting": {

    "public": "dist/app",  // "public" is the only required attribute for Hosting

    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],

    "redirects": [ {
      "source": "/foo",
      "destination": "/bar",
      "type": 301
    }, {
      "source": "/firebase/**",
      "destination": "https://www.firebase.com",
      "type": 302
    } ],

    "rewrites": [ {
      // Shows the same content for multiple URLs
      "source": "/app/**",
      "destination": "/app/index.html"
    }, {
      // Configures a custom domain for Dynamic Links
      "source": "/promos/**",
      "dynamicLinks": true
    }, {
      // Directs a request to Cloud Functions
      "source": "/bigben",
      "function": "bigben"
    }, {
      // Directs a request to a Cloud Run containerized app
      "source": "/helloworld",
      "run": {
        "serviceId": "helloworld",
        "region": "us-central1"
      }
    } ],

    "headers": [ {
      "source": "**/*.@(eot|otf|ttf|ttc|woff|font.css)",
      "headers": [ {
        "key": "Access-Control-Allow-Origin",
        "value": "*"
      } ]
    }, {
      "source": "**/*.@(jpg|jpeg|gif|png)",
      "headers": [ {
        "key": "Cache-Control",
        "value": "max-age=7200"
      } ]
    }, {
      "source": "404.html",
      "headers": [ {
        "key": "Cache-Control",
        "value": "max-age=300"
      } ]
    } ],

    "cleanUrls": true,

    "trailingSlash": false

    // Required to configure custom domains for Dynamic Links
    "appAssociation": "AUTO",

  }
}