หากเคยใช้ Firebase JS SDK หรือ Firebase Client SDK อื่นๆ คุณอาจคุ้นเคยกับอินเทอร์เฟซ FirebaseApp และวิธีใช้เพื่อกำหนดค่าอินสแตนซ์ของแอป Firebase มี FirebaseServerApp เพื่ออำนวยความสะดวกในการดำเนินการที่คล้ายกันในฝั่งเซิร์ฟเวอร์
FirebaseServerApp เป็นตัวแปรของ FirebaseApp สำหรับใช้ในสภาพแวดล้อมการแสดงผลฝั่งเซิร์ฟเวอร์ (SSR) ซึ่งรวมถึงเครื่องมือในการดำเนินการเซสชัน Firebase ต่อไป ที่ครอบคลุมการแสดงผลฝั่งไคลเอ็นต์ (CSR) / การแสดงผลฝั่งเซิร์ฟเวอร์ เครื่องมือและกลยุทธ์เหล่านี้ช่วยปรับปรุงเว็บแอปแบบไดนามิกที่สร้างด้วย Firebase และ
ติดตั้งใช้งานในสภาพแวดล้อมของ Google เช่น Firebase App Hosting ได้
ใช้ FirebaseServerApp เพื่อทำสิ่งต่อไปนี้
- เรียกใช้โค้ดฝั่งเซิร์ฟเวอร์ภายในบริบทของผู้ใช้ ซึ่งแตกต่างจาก Firebase Admin SDK ที่มีสิทธิ์การดูแลระบบอย่างเต็มรูปแบบ
- เปิดใช้ App Check ในสภาพแวดล้อม SSR
- ดำเนินการต่อในเซสชัน Firebase Auth ที่สร้างในไคลเอ็นต์
วงจรการใช้งาน FirebaseServerApp
เฟรมเวิร์กการแสดงผลฝั่งเซิร์ฟเวอร์ (SSR) และรันไทม์อื่นๆ ที่ไม่ใช่เบราว์เซอร์ เช่น Cloud Worker จะเพิ่มประสิทธิภาพเวลาเริ่มต้นโดยการนำทรัพยากรกลับมาใช้ใหม่ในการดำเนินการหลายครั้ง FirebaseServerApp ออกแบบมาเพื่อรองรับสภาพแวดล้อมเหล่านี้
โดยใช้กลไกการนับอ้างอิง หากแอปเรียกใช้
initializeServerApp ด้วยพารามิเตอร์เดียวกันกับ
initializeServerApp ก่อนหน้า แอปจะได้รับอินสแตนซ์ FirebaseServerApp เดียวกันกับที่
เริ่มต้นไว้แล้ว ซึ่งจะช่วยลดค่าใช้จ่ายในการเริ่มต้นที่ไม่จำเป็น
และการจัดสรรหน่วยความจำ เมื่อเรียกใช้ deleteApp ในอินสแตนซ์ FirebaseServerApp
ระบบจะลดจำนวนการอ้างอิง และจะปล่อยอินสแตนซ์หลังจากที่
จำนวนการอ้างอิงเป็น 0
การล้างข้อมูลอินสแตนซ์ FirebaseServerApp
การทราบว่าเมื่อใดควรเรียกใช้ deleteApp ในอินสแตนซ์ FirebaseServerApp อาจเป็นเรื่องยาก โดยเฉพาะหากคุณเรียกใช้การดำเนินการแบบไม่พร้อมกันหลายรายการแบบ ขนานกัน releaseOnDeref ของ FirebaseServerAppSettings ช่วยให้กระบวนการนี้ง่ายขึ้น
หากคุณกำหนดreleaseOnDerefการอ้างอิงให้กับออบเจ็กต์ที่มีอายุการใช้งานตามขอบเขตของคำขอ (เช่น ออบเจ็กต์ส่วนหัวของคำขอ SSR) FirebaseServerAppจะลดจำนวนการอ้างอิงเมื่อเฟรมเวิร์กเรียกคืนออบเจ็กต์ส่วนหัว ซึ่งจะล้างข้อมูลในอินสแตนซ์ FirebaseServerApp โดยอัตโนมัติ
ตัวอย่างการใช้งาน releaseOnDeref มีดังนี้
/// Next.js
import { headers } from 'next/headers'
import { FirebaseServerAppSettings, initializeServerApp} from "firebase/app";
export default async function Page() {
const headersObj = await headers();
let appSettings: FirebaseServerAppSettings = {};
appSettings.releaseOnDeref = headersObj;
const serverApp = initializeServerApp(firebaseConfig, appSettings);
...
}
ดำเนินการต่อในเซสชันที่ได้รับการตรวจสอบสิทธิ์ซึ่งสร้างขึ้นในไคลเอ็นต์
เมื่อเริ่มต้นอินสแตนซ์ของ FirebaseServerApp ด้วยโทเค็นรหัสการตรวจสอบสิทธิ์ ระบบจะเปิดใช้การเชื่อมโยงเซสชันของผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์ระหว่างสภาพแวดล้อมการแสดงผลฝั่งไคลเอ็นต์ (CSR) กับการแสดงผลฝั่งเซิร์ฟเวอร์ (SSR) อินสแตนซ์ของ Firebase Auth SDK ที่เริ่มต้นด้วยออบเจ็กต์ FirebaseServerApp ซึ่งมีโทเค็นรหัส Auth จะพยายามลงชื่อเข้าใช้ผู้ใช้เมื่อเริ่มต้นโดยไม่ต้องให้แอปพลิเคชันเรียกใช้เมธอดการลงชื่อเข้าใช้ใดๆ
การระบุโทเค็นรหัสการให้สิทธิ์จะช่วยให้แอปใช้เมธอดการลงชื่อเข้าใช้ของ Auth บน ไคลเอ็นต์ได้ ซึ่งจะช่วยให้เซสชันทำงานต่อไปในฝั่งเซิร์ฟเวอร์ได้ แม้แต่สำหรับ เมธอดการลงชื่อเข้าใช้ที่ต้องมีการโต้ตอบของผู้ใช้ นอกจากนี้ ยังช่วยให้ การส่งต่อการดำเนินการที่ต้องใช้ทรัพยากรมากไปยังเซิร์ฟเวอร์ เช่น คำค้นหา Firestore ที่ได้รับการตรวจสอบสิทธิ์ ซึ่งจะช่วยปรับปรุงประสิทธิภาพการแสดงผลของแอป
/// Next.js
import { initializeServerApp } from "firebase/app";
import { getAuth } from "firebase/auth";
// Replace the following with your app's
// Firebase project configuration
const firebaseConfig = {
// ...
};
const firebaseServerAppSettings = {
authIdToken: token // See "Pass client tokens to the server side
// rendering phase" for an example on how transmit
// the token from the client and the server.
}
const serverApp =
initializeServerApp(firebaseConfig,
firebaseServerAppSettings);
const serverAuth = getAuth(serverApp);
// FirebaseServerApp and Auth will now attempt
// to sign in the current user based on provided
// authIdToken.
ใช้ App Check ในสภาพแวดล้อม SSR
การบังคับใช้ App Check จะขึ้นอยู่กับอินสแตนซ์ App Check SDK ที่ Firebase SDK ใช้
เพื่อเรียก getToken ภายใน จากนั้นระบบจะรวมโทเค็นที่ได้ไว้ในคำขอ
ไปยังบริการ Firebase ทั้งหมด เพื่อให้แบ็กเอนด์ตรวจสอบแอปได้
อย่างไรก็ตาม เนื่องจาก SDK ของ App Check ต้องใช้เบราว์เซอร์เพื่อเข้าถึงฮิวริสติกที่เฉพาะเจาะจง สำหรับการตรวจสอบแอป จึงเริ่มต้นใช้งานในสภาพแวดล้อมของเซิร์ฟเวอร์ไม่ได้
FirebaseServerApp เป็นอีกทางเลือกหนึ่ง หากมีการระบุโทเค็น App Check
ที่ไคลเอ็นต์สร้างขึ้นในระหว่างFirebaseServerAppการเริ่มต้น SDK ของผลิตภัณฑ์ Firebase จะใช้โทเค็นดังกล่าวเมื่อเรียกใช้บริการ Firebase ซึ่งจะช่วยให้ไม่จำเป็นต้องมีอินสแตนซ์ App Check SDK
/// Next.js
import { initializeServerApp } from "firebase/app";
// Replace the following with your app's
// Firebase project configuration
const firebaseConfig = {
// ...
};
const firebaseServerAppSettings = {
appCheckToken: token // See "Pass client tokens to the server side
// rendering phase" for an example on how transmit
// the token from the client and the server.
}
const serverApp =
initializeServerApp(firebaseConfig,
firebaseServerAppSettings);
// The App Check token will now be appended to all Firebase service requests.
ส่งโทเค็นไคลเอ็นต์ไปยังระยะการแสดงผลฝั่งเซิร์ฟเวอร์
หากต้องการส่งโทเค็นรหัสการตรวจสอบสิทธิ์ที่ได้รับการตรวจสอบสิทธิ์ (และโทเค็น App Check) จากไคลเอ็นต์ ไปยังเฟสการแสดงผลฝั่งเซิร์ฟเวอร์ (SSR) ให้ใช้ Service Worker แนวทางนี้ เกี่ยวข้องกับการสกัดกั้นคำขอ Fetch ที่ทริกเกอร์ SSR และต่อท้ายโทเค็น ในส่วนหัวของคำขอ
ดูการใช้งานอ้างอิงของ Service Worker ของ Firebase Auth ได้ที่การจัดการเซสชันด้วย Service Worker ดูการเปลี่ยนแปลงฝั่งเซิร์ฟเวอร์สำหรับโค้ด
ที่แสดงวิธีแยกวิเคราะห์โทเค็นเหล่านี้จากส่วนหัวเพื่อใช้ในการเริ่มต้นFirebaseServerApp
ใช้ Firestore ในสภาพแวดล้อม SSR
เมื่อสร้างเว็บแอปพลิเคชันด้วยการแสดงผลฝั่งเซิร์ฟเวอร์ (SSR) คุณมักจะต้อง แชร์ข้อมูลระหว่างเซิร์ฟเวอร์กับไคลเอ็นต์เพื่อเพิ่มประสิทธิภาพและประสบการณ์ของผู้ใช้ SDK ของ Firestore มีเครื่องมือการซีเรียลไลซ์ที่ช่วยให้คุณบันทึกสแนปชอตและประเภทข้อมูลที่เฉพาะเจาะจงในเซิร์ฟเวอร์ และส่งไปยังคอมโพเนนต์ฝั่งไคลเอ็นต์ได้โดยตรง กระบวนการนี้จะขจัดการดึงข้อมูลที่ซ้ำซ้อนโดย อนุญาตให้ไคลเอ็นต์ไฮเดรตสถานะโดยใช้ข้อมูลที่ดึงข้อมูลล่วงหน้าในระหว่างระยะ SSR นอกจากนี้ คุณยังเปลี่ยนจากสถานะที่ทำให้เป็นอนุกรมเหล่านี้ไปเป็น Listener แบบเรียลไทม์ได้ เพื่อให้มั่นใจว่าแอปพลิเคชันจะซิงค์ข้อมูลกับฐานข้อมูลอยู่เสมอ
ส่วนนี้จะอธิบายวิธีนำข้อมูลที่ดึงมาในระหว่างเฟสการแสดงผลฝั่งเซิร์ฟเวอร์ (SSR) มาใช้ซ้ำภายในคอมโพเนนต์ฝั่งไคลเอ็นต์
ซีเรียลไลซ์ประเภทข้อมูล
ข้อมูลบางประเภทใน Firestore มีtoJSONเมธอดในการแปลงข้อมูล
เป็นรูปแบบที่ทำให้เป็นอนุกรมได้ ซึ่งรวมถึงอินสแตนซ์ของออบเจ็กต์ เช่น Bytes, GeoPoint, Timestamp และ VectorValue
เมื่อมีข้อมูลในรูปแบบ JSON แล้ว คุณจะส่งข้อมูลจากเซิร์ฟเวอร์ไปยังไคลเอ็นต์ผ่านกลไกเฟรมเวิร์กมาตรฐาน หรือเป็นพารามิเตอร์ไปยังคอมโพเนนต์ที่ครอบคลุมส่วนต่างๆ ได้ เช่น
import {
Bytes
} from 'firebase/firestore';
const BYTES_DATA = new Uint8Array([0, 1, 2, 3, 4, 5]);
const bytes = Bytes.fromUint8Array(BYTES_DATA);
const bytesJSON = bytes.toJSON();
ยกเลิกการซีเรียลไลซ์ประเภทข้อมูล
ประเภทข้อมูล Firestore มีเมธอดแบบคงที่ fromJSON เพื่อแปลงข้อมูลที่
ทำให้เป็นอนุกรมเป็นประเภทข้อมูล Firestore ที่ใช้งานได้
เช่น ตัวอย่างต่อไปนี้จะยกเลิกการซีเรียลไลซ์ประเภทข้อมูล Bytes
import {
Bytes
} from 'firebase/firestore';
// Assuming the same `bytesJSON` variable from the previous example.
const deserializedBytes = Bytes.fromJSON(bytesJSON);
แปลงและเลิกแปลงสแนปชอตของ Firestore
คุณสามารถจัดรูปแบบอินสแตนซ์ของ
DocumentSnapshot และ QuerySnapshot โดยใช้ toJSON ได้เช่นเดียวกับประเภทข้อมูล Firestore อย่างไรก็ตาม หากต้องการยกเลิกการซีเรียลไลซ์
คุณต้องใช้ฟังก์ชันแบบสแตนด์อโลน documentSnapshotFromJSON และ
querySnapshotFromJSON แทนเมธอด fromJSON แบบคงที่
เช่น querySnapshot ของการดำเนินการ query สามารถ
ทำให้เป็นอนุกรมได้โดยใช้วิธี toJSON ดังนี้
import {
collection,
getDocs,
query,
querySnapshotFromJSON
} from 'firebase/firestore';
// Assuming a configured instance of Firestore in the variable `firestore`.
const queryRef = query(collection(firestore, QUERY_PATH));
const querySnapshot = await getDocs(queryRef);
const querySnapshotJson = querySnapshot.toJSON();
จากนั้นจะยกเลิกการซีเรียลไลซ์ข้อมูลนี้ได้
import {
querySnapshotFromJSON
} from 'firebase/firestore';
// deserializedSnapshot is an object of type QuerySnapshot:
const deserializedSnapshot =
querySnapshotFromJSON(firestore, querySnapshotJson);
ผู้ฟังที่มีสแนปชอตแบบอนุกรม
แม้ว่าข้อมูลที่ค้นหาในระยะ SSR จะมีประโยชน์สำหรับการแสดงผล CSR เริ่มต้น แต่คุณอาจยังต้องตรวจสอบบริการ Firestore เพื่อดูข้อมูลอัปเดตแบบเรียลไทม์
หากแอปของคุณต้องมีการอัปเดตแบบเรียลไทม์เหล่านี้ คุณสามารถใช้ฟังก์ชัน onSnapshotResume
เพื่อเริ่มต้น SnapshotListenerFirestore ด้วยข้อมูล Snapshot
ที่แปลงเป็นอนุกรมแล้ว เช่น
const observer = {
next: (qs) => {
console.log("onSnapshot invoked: ", qs.data());
},
error: (e) => {
console.log("error callback invoked: ", e.toString());
}
};
const unsubscribe = onSnapshotResume(firestore, querySnapshotJson, observer);