設定託管行為

使用 Firebase 託管,您可以針對網站要求自訂託管行為。

什麼是「託管」功能?

  • 指定要將本機專案目錄中的哪些檔案部署至 Firebase 託管。瞭解做法。

  • 提供自訂的 404/找不到網頁。瞭解做法。

  • 為你已移動或刪除的頁面設定 redirects瞭解做法。

  • 為下列任一用途設定 rewrites

    • 使用多個網址顯示相同內容。瞭解詳情

    • 透過託管網址提供函式或存取 Cloud Run 容器。操作說明:函式容器

    • 建立自訂網域動態連結。瞭解做法。

  • 新增 headers 以傳送與要求或回應相關的其他資訊,例如瀏覽器應如何處理頁面及其內容 (驗證、快取、編碼等)。瞭解做法。

  • 設定國際化 (i18n) 改寫,根據使用者的語言偏好設定和/或國家/地區提供特定內容。瞭解詳情 (不同頁面)。

您在哪裡定義「託管」設定?

您可以在 firebase.json 檔案中定義 Firebase 託管設定。執行 firebase init 指令時,Firebase 會自動在專案目錄的根目錄建立 firebase.json 檔案。

您可以在本頁面底部找到完整的 firebase.json 設定範例 (僅涵蓋 Firebase 託管)。請注意,firebase.json 檔案也可能包含其他 Firebase 服務的設定

您可以使用 Hosting REST API 檢查部署的 firebase.json 內容。

「託管」回應的優先順序

本頁說明的不同 Firebase 託管設定選項有時會重疊。如果發生衝突,「託管」會依據下列優先順序決定回應:

  1. 開頭為 /__/* 路徑片段的預留命名空間
  2. 設定的重新導向
  3. 完全比對靜態內容
  4. 已設定的重新寫入
  5. 自訂 404 頁面
  6. 預設 404 網頁

如果您使用 i18n 重寫,系統會擴展完全比對和 404 處理優先順序的涵蓋範圍,以配合您的「i18n 內容」。

指定要部署的檔案

預設 firebase.json 檔案內含的預設屬性 (publicignore) 會定義專案目錄中的哪些檔案應部署至 Firebase 專案。

firebase.json 檔案內的預設 hosting 設定如下所示:

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

公開

必要
public 屬性會指定要部署至 Firebase 託管的目錄。預設值為名為 public 的目錄,但只要該目錄存在於專案目錄中,您都可以指定任何目錄的路徑。

以下是要部署的目錄預設指定名稱:

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

  // ...
}

您可將預設值變更為要部署的目錄:

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

  // ...
}

忽略

選用
ignore 屬性會指定在部署時要忽略的檔案。您可以採用與 Git 處理 .gitignore 的方式一樣,採用 glob

以下是要忽略的檔案預設值:

"hosting": {
  // ...

  "ignore": [
    "firebase.json",  // the Firebase configuration file (the file described on this page)
    "**/.*",  // 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/找不到網頁

選用
當使用者嘗試存取不存在的網頁時,您可以提供自訂的 404 Not Found 錯誤。

在專案的 public 目錄中建立新檔案,並將其命名為 404.html,然後將自訂 404 Not Found 內容加入檔案。

如果瀏覽器在您的網域或子網域上觸發 404 Not Found 錯誤,Firebase 託管就會顯示這個自訂 404.html 頁面的內容。

設定重新導向

選用
如果您已移動頁面或縮短網址,使用網址重新導向可避免無效連結。舉例來說,您可以將瀏覽器從 example.com/team 重新導向至 example.com/about.html

建立含有物件陣列 (稱為「重新導向規則」) 的 redirects 屬性,即可指定網址重新導向。在每個規則中指定網址模式,如果與要求網址路徑相符,就會觸發「託管」以重新導向至指定目的地的網址做為回應。

以下是 redirects 屬性的基本結構。以下範例會發出新的要求至 /bar,將要求重新導向至 /foo

"hosting": {
  // ...

  // Returns a permanent redirect to "/bar" for requests to "/foo" (but not "/foo/**")
  "redirects": [ {
    "source": "/foo",
    "destination": "/bar",
    "type": 301
  } ]
}

redirects 屬性包含重新導向規則的陣列,其中每個規則都必須包含下表中的欄位。

Firebase 託管會將 sourceregex 值與每個要求開頭的所有網址路徑進行比對 (瀏覽器會在瀏覽器判定該路徑中是否存在檔案或資料夾之前)。如果找到相符項目,Firebase 代管來源伺服器就會傳送 HTTPS 重新導向回應,指示瀏覽器透過 destination 網址發出新要求。

欄位 說明
redirects
source (建議)
regex

一種網址模式,如果與初始要求網址相符,就會觸發「託管」功能套用重新導向

destination

瀏覽器應發出新要求的靜態網址

這個網址可以是相對或絕對路徑。

type

HTTPS 回應代碼

  • 301 類型用於「已永久移動」
  • 為「找到」使用 302 類型 (暫時重新導向)

擷取用於重新導向的網址區隔

選用
有時您可能需要擷取重新導向規則網址模式 (sourceregex 值) 的特定區隔,然後在規則的 destination 路徑中重複使用這些區隔。

設定重新寫入

選擇性
使用改寫可讓多個網址顯示相同內容。重寫功能特別適合用於模式比對,因為您可以接受任何符合模式的網址,並讓用戶端程式碼決定要顯示的內容。

您也可以使用重寫功能支援使用 HTML5PushState 進行瀏覽的應用程式。當瀏覽器嘗試開啟符合指定 sourceregex 網址模式的網址路徑時,瀏覽器會改在 destination 網址取得檔案內容。

您可以建立包含物件陣列的 rewrites 屬性 (稱為「重寫規則」) 來指定網址重新寫入。在每項規則中指定網址模式,如果與要求網址路徑相符,就會觸發「託管」功能,視為服務已指定指定的目的地網址。

以下是 rewrites 屬性的基本結構。這個範例針對不存在的檔案或目錄要求提供 index.html

"hosting": {
  // ...

  // Serves index.html for requests to files or directories that do not exist
  "rewrites": [ {
    "source": "**",
    "destination": "/index.html"
  } ]
}

rewrites 屬性包含重新寫入規則的陣列,其中每項規則都必須包含下表中的欄位。

只有在檔案或目錄與指定 sourceregex 網址模式相符的網址路徑不存在時,Firebase 代管才會套用重新寫入規則。當要求觸發重新寫入規則時,瀏覽器會傳回指定 destination 檔案的實際內容,而不是 HTTP 重新導向。

欄位 說明
rewrites
source (建議)
regex

一種網址模式,如果與初始要求網址相符,就會觸發「託管」套用重新寫入的內容

destination

必須存在的本機檔案

這個網址可以是相對或絕對路徑。

將要求直接傳送至函式

您可以使用 rewrites 透過 Firebase 託管網址提供函式。以下範例是使用 Cloud Functions 提供動態內容的摘錄。

例如,如要引導主機網站上來自 /bigben 頁面的所有要求執行 bigben 函式:

"hosting": {
  // ...

  // Directs all requests from the page `/bigben` to execute the `bigben` function
  "rewrites": [ {
    "source": "/bigben",
    "function": {
      "functionId": "bigben",
      "region": "us-central1"  // optional (see note below)
      "pinTag": true           // optional (see note below)
    }
  } ]
}

新增此重寫規則並部署至 Firebase (使用 firebase deploy) 之後,就可以透過下列網址存取函式:

  • 您的 Firebase 子網域:
    PROJECT_ID.web.app/bigbenPROJECT_ID.firebaseapp.com/bigben

  • 任何已連結的自訂網域
    CUSTOM_DOMAIN/bigben

使用託管功能將要求重新導向至函式時,支援的 HTTP 要求方法為 GETPOSTHEADPUTDELETEPATCHOPTIONS。系統不支援 REPORTPROFIND 等其他方法。

將要求直接傳送至 Cloud Run 容器

您可以使用 rewrites 從 Firebase 託管網址存取 Cloud Run 容器。以下範例是使用 Cloud Run 提供動態內容的摘錄。

例如,如要引導託管網站上來自 /helloworld 頁面的所有要求,觸發啟動並執行 helloworld 容器執行個體:

"hosting": {
 // ...

 // Directs all requests from the page `/helloworld` to trigger and run a `helloworld` container
 "rewrites": [ {
   "source": "/helloworld",
   "run": {
     "serviceId": "helloworld",  // "service name" (from when you deployed the container image)
     "region": "us-central1"  // optional (if omitted, default is us-central1)
   }
 } ]
}

新增此重新編寫規則並部署至 Firebase (使用 firebase deploy) 之後,您就能透過下列網址存取容器映像檔:

  • 您的 Firebase 子網域:
    PROJECT_ID.web.app/helloworldPROJECT_ID.firebaseapp.com/helloworld

  • 任何已連結的自訂網域
    CUSTOM_DOMAIN/helloworld

使用託管功能將要求重新導向至 Cloud Run 容器時,支援的 HTTP 要求方法為 GETPOSTHEADPUTDELETEPATCHOPTIONS。系統不支援 REPORTPROFIND 等其他方法。

為獲得最佳效能,請透過下列區域將 Cloud Run 服務與託管服務存放在相同位置:

  • us-west1
  • us-central1
  • us-east1
  • europe-west1
  • asia-east1

下列地區支援從託管重新寫入 Cloud Run 的功能:

  • asia-east1
  • asia-east2
  • asia-northeast1
  • asia-northeast2
  • asia-northeast3
  • asia-south1
  • asia-south2
  • asia-southeast1
  • asia-southeast2
  • australia-southeast1
  • australia-southeast2
  • europe-central2
  • europe-north1
  • europe-southwest1
  • europe-west1
  • europe-west12
  • europe-west2
  • europe-west3
  • europe-west4
  • europe-west6
  • europe-west8
  • europe-west9
  • me-central1
  • me-west1
  • northamerica-northeast1
  • northamerica-northeast2
  • southamerica-east1
  • southamerica-west1
  • us-central1
  • us-east1
  • us-east4
  • us-east5
  • us-south1
  • us-west1
  • us-west2
  • us-west3
  • us-west4
  • us-west1
  • us-central1
  • us-east1
  • europe-west1
  • asia-east1

您可以使用 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": "/**",  // the Dynamic Links start with "https://CUSTOM_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/**",  // the Dynamic Links start with "https://CUSTOM_DOMAIN/promos/"
        "dynamicLinks": true
      }, {
        "source": "/links/share/**",  // the Dynamic Links start with "https://CUSTOM_DOMAIN/links/share/"
        "dynamicLinks": true
      } ]
    }
    

在您的 firebase.json 檔案中設定 Dynamic Links 需要下列項目:

欄位 說明
appAssociation

必須設為 AUTO

  • 如果未在設定中加入這項屬性,appAssociation 的預設值為 AUTO
  • 將這項屬性設為 AUTO 後,「託管」功能可以在收到要求時動態產生 assetlinks.jsonapple-app-site-association 檔案。
rewrites
source

您要用於 Dynamic Links 的路徑

與重寫網址路徑的規則不同,動態連結的重寫規則不能包含規則運算式。

dynamicLinks 必須設為 true

設定標頭

選用
標頭可讓用戶端和伺服器在傳送要求或回應時一併傳送其他資訊。有些標頭組合可能會影響瀏覽器處理網頁及其內容的方式,包括存取權控管、驗證、快取和編碼。

建立包含標頭物件陣列的 headers 屬性,以指定檔案專屬的自訂回應標頭。在每個物件中指定網址模式,如果與要求網址路徑相符,就會觸發「託管」來套用指定的自訂回應標頭。

以下是 headers 屬性的基本結構。這個範例會將 CORS 標頭套用至所有字型檔案。

"hosting": {
  // ...

  // Applies a CORS header for all font files
  "headers": [ {
    "source": "**/*.@(eot|otf|ttf|ttc|woff|font.css)",
    "headers": [ {
      "key": "Access-Control-Allow-Origin",
      "value": "*"
    } ]
  } ]
}

headers 屬性包含定義的陣列,每個定義都必須包含下表中的欄位。

欄位 說明
headers
source (建議)
regex

一種網址模式,如果與初始要求網址相符,就會觸發「託管」功能套用自訂標頭

如要建立與自訂 404 頁面相符的標頭,請使用 404.html 做為 sourceregex 的值。

(子子)headers 的陣列

「託管」套用至要求路徑的自訂標頭

每個子標題都必須包含 keyvalue 組合 (請參閱後兩列)。

key 標頭名稱,例如 Cache-Control
value 標頭的值,例如 max-age=7200

如要進一步瞭解 Cache-Control,請參閱「託管」一節,瞭解如何提供動態內容及託管微服務。您也可以進一步瞭解 CORS 標頭。

控管「.html」擴充功能

選用
cleanUrls 屬性可讓您控管網址是否應加入 .html 副檔名。

如果設為 true,「託管」功能會自動從上傳檔案的網址中移除 .html 擴充功能。如果在要求中加入 .html 副檔名,「託管」會執行 301 重新導向至相同路徑,但會刪除 .html 副檔名。

以下說明如何加入 cleanUrls 屬性,以控制網址是否包含 .html

"hosting": {
  // ...

  // Drops `.html` from uploaded URLs
  "cleanUrls": true
}

控制結尾斜線

選用
trailingSlash 屬性可讓您控制靜態內容網址是否應包含結尾斜線。

  • 如果設為 true,「託管」會重新導向網址,並在結尾加上斜線。
  • 如果設為 false,「託管」會重新導向網址,藉此移除結尾的斜線。
  • 如未指定,「託管」功能只會對目錄索引檔案 (例如 about/index.html) 使用結尾斜線。

以下說明如何新增 trailingSlash 屬性來控制結尾斜線:

"hosting": {
  // ...

  // Removes trailing slashes from URLs
  "trailingSlash": false
}

trailingSlash 屬性不會影響到 Cloud Functions 或 Cloud Run 提供的動態內容重新寫入作業。

Glob 模式比對

Firebase 託管設定選項會大量使用 extglob 的 glob 模式比對標記法,類似於 Git 處理 gitignore 規則和 Bower 處理 ignore 規則的方式。這個維基網頁是更詳細的參考資料,但以下為本頁使用範例的說明:

  • firebase.json:只比對 public 目錄根目錄中的 firebase.json 檔案

  • ** - 比對任意子目錄中的任何檔案或資料夾

  • * - 僅比對 public 根目錄中的檔案和資料夾

  • **/.* - 在任意子目錄中比對開頭為 . 的任何檔案 (通常是隱藏檔案,例如 .git 資料夾中)

  • **/node_modules/** - 比對 node_modules 資料夾任意子目錄中的任何檔案或資料夾,這類子目錄本身可位於 public 目錄的任意子目錄中

  • **/*.@(jpg|jpeg|gif|png) — 比對任意子目錄中任何結尾為下列其中一個檔案:.jpg.jpeg.gif.png

完整託管設定範例

以下是 Firebase 託管的完整 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",

  }
}