หน้านี้ได้รับการแปลโดย Cloud Translation API
Switch to English

กำหนดค่าพฤติกรรมการโฮสต์

ด้วย Firebase Hosting คุณสามารถกำหนดค่าพฤติกรรมการโฮสต์ที่กำหนดเองสำหรับคำขอไปยังไซต์ของคุณ

คุณสามารถกำหนดค่าอะไรสำหรับ Hosting ได้บ้าง?

  • ระบุไฟล์ในไดเร็กทอรีโปรเจ็กต์ในเครื่องที่คุณต้องการปรับใช้กับ Firebase Hosting เรียนรู้วิธีการ

  • แสดงหน้า 404 / Not Found ที่กำหนดเอง เรียนรู้วิธีการ

  • ตั้งค่าการ redirects สำหรับหน้าที่คุณย้ายหรือลบ เรียนรู้วิธีการ

  • ตั้งค่าการ rewrites เพื่อวัตถุประสงค์เหล่านี้:

  • เพิ่ม headers เพื่อส่งต่อข้อมูลเพิ่มเติมเกี่ยวกับคำขอหรือการตอบกลับเช่นเบราว์เซอร์ควรจัดการกับเพจและเนื้อหาอย่างไร (การตรวจสอบสิทธิ์การแคชการเข้ารหัส ฯลฯ ) เรียนรู้วิธีการ

  • ตั้งค่าการเขียนซ้ำระหว่างประเทศ (i18n) เพื่อให้บริการเนื้อหาที่เฉพาะเจาะจงตามค่ากำหนดภาษาและ / หรือประเทศของผู้ใช้ เรียนรู้วิธีการ (หน้าอื่น)

คุณกำหนดการกำหนดค่าโฮสติ้งของคุณไว้ที่ใด

คุณกำหนดการกำหนดค่า Firebase Hosting ในไฟล์ firebase.json Firebase จะสร้างไฟล์ firebase.json ของคุณโดยอัตโนมัติที่รากของไดเร็กทอรีโปรเจ็กต์ของคุณเมื่อคุณรันคำสั่ง firebase init

คุณสามารถดู ตัวอย่างการกำหนดค่า firebase.json ฉบับเต็ม (ครอบคลุมเฉพาะโฮสติ้ง Firebase) ที่ด้านล่างของหน้านี้ โปรดทราบว่าไฟล์ firebase.json ยังสามารถมี การกำหนดค่าสำหรับบริการ Firebase อื่น ๆ

คุณสามารถตรวจสอบเนื้อหา firebase.json ปรับใช้โดยใช้ Hosting REST API

ลำดับความสำคัญของการตอบกลับโฮสติ้ง

ตัวเลือกการกำหนดค่า Firebase Hosting ต่างๆที่อธิบายไว้ในหน้านี้บางครั้งอาจทับซ้อนกัน หากมีข้อขัดแย้ง Hosting จะกำหนดการตอบสนองโดยใช้ลำดับความสำคัญดังต่อไปนี้:

  1. เนมสเปซที่สงวนไว้ซึ่งขึ้นต้นด้วยส่วนเส้นทาง /__/*
  2. การ เปลี่ยนเส้นทางที่ กำหนดค่าไว้
  3. เนื้อหาคงที่ตรงทั้งหมด
  4. กำหนดค่าการ เขียนซ้ำ
  5. หน้า 404 ที่กำหนดเอง
  6. หน้า 404 เริ่มต้น

หากคุณกำลังใช้การ เขียนซ้ำ i18n ลำดับความสำคัญของการจัดการแบบตรงทั้งหมดและ 404 จะขยายขอบเขตเพื่อรองรับ "เนื้อหา i18n" ของคุณ

ระบุไฟล์ที่จะปรับใช้

แอตทริบิวต์เริ่มต้น - public และ ignore - รวมอยู่ในไฟล์ firebase.json เริ่มต้นจะกำหนดว่าไฟล์ใดในไดเรกทอรีโครงการของคุณที่ควรทำให้ใช้งานได้กับโครงการ Firebase ของคุณ

การกำหนดค่า hosting เริ่มต้นในไฟล์ firebase.json มีลักษณะดังนี้:

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

สาธารณะ

จำเป็นต้องใช้
แอตทริบิวต์ public ระบุไดเร็กทอรีที่จะปรับใช้กับ Firebase Hosting ค่าดีฟอลต์คือไดเร็กทอรีที่มีชื่อว่า public แต่คุณสามารถระบุพา ธ ของไดเร็กทอรีใดก็ได้ตราบเท่าที่มีอยู่ในไดเร็กทอรีโปรเจ็กต์ของคุณ

ต่อไปนี้เป็นชื่อที่ระบุดีฟอลต์ของไดเร็กทอรีที่จะปรับใช้:

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

  // ...
}

คุณสามารถเปลี่ยนค่าดีฟอลต์เป็นไดเร็กทอรีที่คุณต้องการปรับใช้:

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

  // ...
}

ไม่สนใจ

ไม่จำเป็น
แอตทริบิวต์ ignore ระบุไฟล์ที่จะละเว้นในการปรับใช้ สามารถใช้ globs แบบเดียวกับที่ Git จัดการกับ .gitignore

ต่อไปนี้เป็นค่าดีฟอลต์สำหรับไฟล์ที่จะละเว้น:

"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 / Not Found

ไม่จำเป็น
คุณสามารถให้บริการข้อผิดพลาด 404 Not Found กำหนดเอง 404 Not Found เมื่อผู้ใช้พยายามเข้าถึงเพจที่ไม่มีอยู่

สร้างไฟล์ใหม่ใน ไดเร็กทอรี public ของโปรเจ็กต์ของคุณตั้งชื่อว่า 404.html จากนั้นเพิ่มเนื้อหา 404 Not Found กำหนดเองของคุณลงในไฟล์

Firebase Hosting จะแสดงเนื้อหาของหน้า 404.html กำหนดเองนี้หากเบราว์เซอร์ทริกเกอร์ข้อผิดพลาด 404 Not Found ในโดเมนหรือโดเมนย่อยของคุณ

กำหนดค่าการเปลี่ยนเส้นทาง

ไม่จำเป็น
ใช้การเปลี่ยนเส้นทาง URL เพื่อป้องกันไม่ให้ลิงก์เสียหากคุณย้ายเพจหรือย่อ URL ตัวอย่างเช่นคุณสามารถเปลี่ยนเส้นทางเบราว์เซอร์จาก example.com/team ไปที่ example.com/about.html

ระบุการเปลี่ยนเส้นทาง URL โดยสร้างแอตทริบิวต์การ redirects ที่มีอาร์เรย์ของออบเจ็กต์ (เรียกว่า "กฎการเปลี่ยนเส้นทาง") ในแต่ละกฎระบุรูปแบบ URL ที่หากตรงกับเส้นทาง URL ที่ร้องขอจะทริกเกอร์ Hosting ให้ตอบสนองด้วยการเปลี่ยนเส้นทางไปยัง URL ปลายทางที่ระบุ

นี่คือโครงสร้างพื้นฐานสำหรับแอตทริบิวต์การ redirects ตัวอย่างนี้เปลี่ยนเส้นทางการร้องขอไปยัง /foo โดยการร้องขอใหม่ไปยัง /bar

"hosting": {
  // ...

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

แอตทริบิวต์การ redirects มีอาร์เรย์ของกฎการเปลี่ยนเส้นทางโดยแต่ละกฎจะต้องมีฟิลด์ในตารางด้านล่าง

Firebase Hosting จะเปรียบเทียบ source หรือค่า regex กับเส้นทาง URL ทั้งหมดเมื่อเริ่มต้นคำขอทุกครั้ง (ก่อนที่เบราว์เซอร์จะพิจารณาว่ามีไฟล์หรือโฟลเดอร์อยู่ที่เส้นทางนั้นหรือไม่) หากพบรายการที่ตรงกันเซิร์ฟเวอร์ต้นทางของโฮสติ้ง Firebase จะส่งการตอบสนองการเปลี่ยนเส้นทาง HTTP เพื่อบอกให้เบราว์เซอร์ส่งคำขอใหม่ที่ URL destination

สนาม ลักษณะ
redirects
source (แนะนำ)
หรือ regex

รูปแบบ URL ที่หากตรงกับ URL คำขอเริ่มต้นจะทริกเกอร์ Hosting ให้ใช้การเปลี่ยนเส้นทาง

destination

URL คงที่ซึ่งเบราว์เซอร์ควรส่งคำขอใหม่

URL นี้อาจเป็นเส้นทางสัมพัทธ์หรือเส้นทางสัมบูรณ์

type

รหัสตอบกลับ HTTP

  • ใช้ประเภท 301 สำหรับ "ย้ายถาวร"
  • ใช้ประเภท 302 สำหรับ 'Found' (การเปลี่ยนเส้นทางชั่วคราว)

จับภาพส่วน URL สำหรับการเปลี่ยนเส้นทาง

ไม่จำเป็น
บางครั้งคุณอาจต้องจับภาพบางส่วนของรูปแบบ URL ของกฎการเปลี่ยนเส้นทาง (ค่า source หรือค่า regex ) จากนั้นใช้กลุ่มเหล่านี้ซ้ำในเส้นทาง destination ของกฎ

กำหนดค่าการเขียนซ้ำ

ไม่จำเป็น
ใช้การเขียนซ้ำเพื่อแสดงเนื้อหาเดียวกันสำหรับหลาย URL การเขียนซ้ำมีประโยชน์อย่างยิ่งกับการจับคู่รูปแบบเนื่องจากคุณสามารถยอมรับ URL ใด ๆ ที่ตรงกับรูปแบบและปล่อยให้โค้ดฝั่งไคลเอ็นต์ตัดสินใจว่าจะแสดงอะไร

คุณยังสามารถใช้การเขียนซ้ำเพื่อรองรับแอพที่ใช้ HTML5 pushState สำหรับการนำทาง เมื่อเบราว์เซอร์พยายามเปิดเส้นทาง URL ที่ตรงกับ source ระบุหรือรูปแบบ URL regex เบราว์เซอร์จะได้รับเนื้อหาของไฟล์ที่ URL destination แทน

ระบุการเขียน URL ใหม่โดยการสร้างแอตทริบิวต์การ rewrites ที่มีอาร์เรย์ของวัตถุ (เรียกว่า "กฎการเขียนซ้ำ") ในแต่ละกฎระบุรูปแบบ URL ที่หากตรงกับเส้นทาง URL ที่ร้องขอจะทริกเกอร์ Hosting ให้ตอบสนองราวกับว่าบริการได้รับ URL ปลายทางที่ระบุ

นี่คือโครงสร้างพื้นฐานสำหรับแอตทริบิวต์การ rewrites ตัวอย่างนี้ทำหน้าที่ index.html สำหรับการร้องขอไปยังไฟล์หรือไดเร็กทอรีที่ไม่มีอยู่

"hosting": {
  // ...

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

แอตทริบิวต์ rewrites มีอาร์เรย์ของกฎการ rewrites โดยแต่ละกฎต้องรวมฟิลด์ในตารางด้านล่าง

Firebase Hosting จะใช้กฎการเขียนซ้ำหากไฟล์หรือไดเรกทอรีไม่มีอยู่ในเส้นทาง URL ที่ตรงกับ source ระบุหรือรูปแบบ URL regex เมื่อคำขอทริกเกอร์กฎการเขียนซ้ำเบราว์เซอร์จะส่งคืนเนื้อหาจริงของไฟล์ destination ระบุแทนการเปลี่ยนเส้นทาง HTTP

สนาม ลักษณะ
rewrites
source (แนะนำ)
หรือ regex

รูปแบบ URL ที่หากตรงกับ URL คำขอเริ่มต้นจะทริกเกอร์ Hosting เพื่อใช้การเขียนซ้ำ

destination

ไฟล์ในเครื่องที่ต้องมีอยู่

URL นี้อาจเป็นเส้นทางสัมพัทธ์หรือเส้นทางสัมบูรณ์

คำขอโดยตรงไปยังฟังก์ชัน

คุณสามารถใช้การ rewrites เพื่อให้บริการฟังก์ชันจาก URL โฮสติ้งของ Firebase ตัวอย่างต่อไปนี้เป็นข้อความที่ตัดตอนมาจาก การแสดงเนื้อหาแบบไดนามิกโดยใช้ Cloud Functions

ตัวอย่างเช่นหากต้องการสั่งให้คำขอทั้งหมดจากเพจ /bigben บนไซต์โฮสติ้งของคุณดำเนินการฟังก์ชัน bigben :

"hosting": {
  // ...

  // Directs all requests from the page `/bigben` to execute the `bigben` function
  "rewrites": [ {
    "source": "/bigben",
    "function": "bigben"
  } ]
}

หลังจากเพิ่มกฎการเขียนซ้ำนี้และปรับใช้กับ Firebase (โดยใช้การ firebase deploy ) ฟังก์ชันของคุณจะเข้าถึงได้ผ่าน URL ต่อไปนี้:

คำขอโดยตรงไปยังคอนเทนเนอร์ Cloud Run

คุณสามารถใช้การ rewrites เพื่อเข้าถึงคอนเทนเนอร์ Cloud Run จาก URL โฮสติ้งของ Firebase ตัวอย่างต่อไปนี้เป็นข้อความที่ตัดตอนมาจาก การแสดงเนื้อหาแบบไดนามิกโดยใช้ 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 ) อิมเมจคอนเทนเนอร์ของคุณจะเข้าถึงได้ผ่าน URL ต่อไปนี้:

คุณสามารถใช้การ rewrites เพื่อสร้างลิงก์ไดนามิกของโดเมนที่กำหนดเอง เยี่ยมชมเอกสาร 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
      } ]
    }
    
  • ระบุคำนำหน้าเส้นทางโดเมนที่กำหนดเองเพื่อใช้สำหรับลิงก์แบบไดนามิก

    "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
      } ]
    }
    

การกำหนดค่า Dynamic Links ในไฟล์ firebase.json ของคุณต้องการสิ่งต่อไปนี้:

สนาม ลักษณะ
appAssociation

ต้องตั้งค่าเป็น AUTO

  • หากคุณไม่รวมแอตทริบิวต์นี้ในการกำหนดค่าของ appAssociation เริ่มต้นสำหรับ appAssociation คือ AUTO
  • ด้วยการตั้งค่าแอตทริบิวต์นี้เป็น AUTO โฮสติ้งสามารถสร้างไฟล์การ apple-app-site-association assetlinks.json และ apple-app-site-association assetlinks.json แบบไดนามิกเมื่อมีการร้องขอ
rewrites
source

เส้นทางที่คุณต้องการใช้สำหรับลิงก์แบบไดนามิก

ไม่เหมือนกับกฎที่เขียนเส้นทางไปยัง URL ใหม่กฎการเขียนซ้ำสำหรับลิงก์แบบไดนามิกต้องไม่มีนิพจน์ทั่วไป

dynamicLinks ต้องตั้งค่า true

กำหนดค่าส่วนหัว

ไม่จำเป็น
ส่วนหัวอนุญาตให้ไคลเอ็นต์และเซิร์ฟเวอร์ส่งข้อมูลเพิ่มเติมพร้อมกับคำขอหรือการตอบกลับ ส่วนหัวบางชุดอาจส่งผลต่อวิธีที่เบราว์เซอร์จัดการกับเพจและเนื้อหารวมถึงการควบคุมการเข้าถึงการพิสูจน์ตัวตนการแคชและการเข้ารหัส

ระบุส่วนหัวการตอบกลับเฉพาะไฟล์ที่กำหนดเองโดยสร้างแอ็ตทริบิวต์ headers ที่มีอาร์เรย์ของออบเจ็กต์ส่วนหัว ในแต่ละออบเจ็กต์ระบุรูปแบบ URL ที่หากตรงกับเส้นทาง URL คำขอจะทริกเกอร์ Hosting ให้ใช้ส่วนหัวการตอบกลับที่กำหนดเองที่ระบุ

นี่คือโครงสร้างพื้นฐานสำหรับแอตทริบิวต์ 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

รูปแบบ URL ที่หากตรงกับ URL คำขอเริ่มต้นจะทริกเกอร์ Hosting ให้ใช้ส่วนหัวที่กำหนดเอง

หากต้องการสร้างส่วนหัวให้ตรงกับ หน้า 404 ที่กำหนดเอง ของคุณให้ใช้ 404.html เป็นค่า source หรือ regex

อาร์เรย์ของ headers (ย่อย)

ส่วนหัวแบบกำหนดเองที่ Hosting ใช้กับเส้นทางการร้องขอ

ส่วนหัวย่อยแต่ละรายการต้องมี คู่ key และ value (ดูสองแถวถัดไป)

key ชื่อของส่วนหัวตัวอย่างเช่น Cache-Control
value ค่าสำหรับส่วนหัวเช่น max-age=7200

คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับ Cache-Control ในส่วนโฮสติ้งที่อธิบายการให้บริการเนื้อหาแบบไดนามิกและการโฮสต์ไมโครเซอร์วิส คุณยังสามารถเรียนรู้เพิ่มเติมเกี่ยวกับส่วนหัว CORS

ควบคุมส่วนขยาย .html

ไม่จำเป็น
แอตทริบิวต์ cleanUrls ช่วยให้คุณควบคุมได้ว่า URL ควรมีนามสกุล .html หรือไม่

เมื่อ true โฮสติ้งจะลบนามสกุล .html จาก URL ไฟล์ที่อัปโหลดโดยอัตโนมัติ หากมีการเพิ่มส่วนขยาย .html ในคำขอ Hosting จะดำเนินการเปลี่ยนเส้นทาง 301 ไปยังเส้นทางเดียวกัน แต่กำจัดส่วนขยาย .html

วิธีควบคุมการรวม .html ใน URL โดยรวมแอตทริบิวต์ cleanUrls :

"hosting": {
  // ...

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

ควบคุมเครื่องหมายทับ

ไม่จำเป็น
แอตทริบิวต์ trailingSlash ช่วยให้คุณสามารถควบคุมได้ว่า URL ของเนื้อหาคงที่ควรมีเครื่องหมายทับหรือไม่

  • เมื่อ true โฮสติ้งจะเปลี่ยนเส้นทาง URL เพื่อเพิ่มเครื่องหมายทับ
  • หาก false โฮสติ้งจะเปลี่ยนเส้นทาง URL เพื่อลบเครื่องหมายทับ
  • เมื่อไม่ระบุ Hosting จะใช้เฉพาะเครื่องหมายทับสำหรับไฟล์ดัชนีไดเรกทอรีเท่านั้น (ตัวอย่างเช่น about/index.html )

ต่อไปนี้เป็นวิธีควบคุมเครื่องหมายทับโดยการเพิ่มแอตทริบิวต์ trailingSlash :

"hosting": {
  // ...

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

แอตทริบิวต์ trailingSlash ไม่มีผลต่อการเขียนซ้ำไปยังเนื้อหาแบบไดนามิกที่ให้บริการโดย Cloud Functions หรือ Cloud Run

การจับคู่รูปแบบลูกโลก

ตัวเลือกการกำหนดค่า Firebase Hosting ใช้ประโยชน์จาก รูปแบบการจับคู่รูปแบบ glob กับ extglob ได้อย่างครอบคลุมเช่นเดียวกับวิธีที่ Git จัดการกฎ gitignore และ Bower จัดการกับการ ignore กฎ หน้าวิกินี้ เป็นการอ้างอิงโดยละเอียด แต่ต่อไปนี้เป็นคำอธิบายของตัวอย่างที่ใช้ในหน้านี้:

  • firebase.json - จับคู่ไฟล์ firebase.json ในรูทของไดเร็กทอรี public

  • ** - จับคู่ไฟล์หรือโฟลเดอร์ใด ๆ ในไดเร็กทอรีย่อยที่กำหนดเอง

  • * - จับคู่ไฟล์และโฟลเดอร์ในรูทของไดเร็กทอรี public

  • **/.* - จับคู่ไฟล์ที่ขึ้นต้นด้วย . (โดยปกติจะซ่อนไฟล์เช่นในโฟลเดอร์ .git ) ในไดเร็กทอรีย่อยที่กำหนดเอง

  • **/node_modules/** - จับคู่ไฟล์หรือโฟลเดอร์ใด ๆ ในไดเร็กทอรีย่อยที่กำหนดเองของโฟลเดอร์ node_modules ซึ่งสามารถอยู่ในไดเร็กทอรีย่อยของไดเร็กทอรี public โดยพลการ

  • **/*.@(jpg|jpeg|gif|png) - จับคู่ไฟล์ใด ๆ ในไดเร็กทอรีย่อยตามอำเภอใจที่ลงท้ายด้วยอย่างใดอย่างหนึ่งต่อไปนี้: .jpg , .jpeg , .gif หรือ. .png

ตัวอย่างการกำหนดค่าโฮสติ้งแบบเต็ม

ต่อไปนี้เป็นตัวอย่างการกำหนดค่า firebase.json แบบเต็มสำหรับ Firebase Hosting โปรดทราบว่าไฟล์ 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",

  }
}