หากคุณเคยใช้ 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 ที่สร้างในไคลเอ็นต์
วงจรการใช้งาน FirebaseServerApp
เฟรมเวิร์กการแสดงผลฝั่งเซิร์ฟเวอร์ (SSR) และรันไทม์ที่ไม่ใช่เบราว์เซอร์อื่นๆ เช่น Cloud Worker จะเพิ่มประสิทธิภาพเวลาเริ่มต้นโดยการนำทรัพยากรกลับมาใช้ซ้ำในการดำเนินการหลายครั้ง FirebaseServerApp ได้รับการออกแบบมาเพื่อรองรับสภาพแวดล้อมเหล่านี้โดยใช้กลไกการนับการอ้างอิง หากแอปเรียกใช้ initializeServerApp ด้วยพารามิเตอร์เดียวกับ initializeServerApp ก่อนหน้า แอปจะได้รับอินสแตนซ์ FirebaseServerApp เดียวกันที่เริ่มต้นไว้แล้ว ซึ่งจะช่วยลดค่าใช้จ่ายในการเริ่มต้นที่ไม่จำเป็นและการจัดสรรหน่วยความจำ เมื่อมีการเรียกใช้ deleteApp ในอินสแตนซ์ FirebaseServerApp ระบบจะลดจำนวนการอ้างอิง และอินสแตนซ์จะได้รับการปล่อยหลังจากจำนวนการอ้างอิงเป็น 0
การล้างข้อมูลอินสแตนซ์ FirebaseServerApp
การทราบเวลาที่ควรเรียกใช้ deleteApp ในอินสแตนซ์ FirebaseServerApp อาจเป็นเรื่องยาก โดยเฉพาะอย่างยิ่งหากคุณดำเนินการแบบอะซิงโครนัสหลายรายการแบบขนาน ช่อง releaseOnDeref ของ FirebaseServerAppSettings ช่วยให้การดำเนินการนี้ง่ายขึ้น หากคุณกำหนดการอ้างอิงออบเจ็กต์ที่มีอายุการใช้งานตามขอบเขตของคำขอ (เช่น ออบเจ็กต์ส่วนหัวของคำขอ SSR) ให้กับ releaseOnDeref 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 ได้ในไคลเอ็นต์ ซึ่งจะช่วยให้เซสชันดำเนินการต่อในฝั่งเซิร์ฟเวอร์ แม้แต่เมธอดการลงชื่อเข้าใช้ที่ต้องมีการโต้ตอบของผู้ใช้ นอกจากนี้ ยังช่วยให้สามารถย้ายการดำเนินการที่ใช้ทรัพยากรมากไปยังเซิร์ฟเวอร์ เช่น การค้นหา 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 ทั้งหมด ซึ่งช่วยให้แบ็กเอนด์ตรวจสอบแอปได้
อย่างไรก็ตาม เนื่องจาก App Check SDK ต้องใช้เบราว์เซอร์เพื่อเข้าถึงฮิวริสติกเฉพาะสำหรับการตรวจสอบแอป จึงไม่สามารถเริ่มต้นในสภาพแวดล้อมเซิร์ฟเวอร์ได้
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 ได้ที่ การจัดการเซสชันด้วย Service
Worker นอกจากนี้ โปรดดูการเปลี่ยนแปลง
ฝั่งเซิร์ฟเวอร์สำหรับโค้ด
ที่แสดงวิธีแยกวิเคราะห์โทเค็นเหล่านี้จากส่วนหัวเพื่อใช้ในการ
FirebaseServerAppเริ่มต้น
ใช้ Firestore ในสภาพแวดล้อม SSR
เมื่อสร้างเว็บแอปพลิเคชันด้วยการแสดงผลฝั่งเซิร์ฟเวอร์ (SSR) คุณมักจะต้องแชร์ข้อมูลระหว่างเซิร์ฟเวอร์และไคลเอ็นต์เพื่อเพิ่มประสิทธิภาพและประสบการณ์ของผู้ใช้ Firestore SDK มีเครื่องมือการซีเรียลไลซ์ที่ช่วยให้คุณบันทึกสแนปชอตและประเภทข้อมูลที่เฉพาะเจาะจงในเซิร์ฟเวอร์ แล้วส่งข้อมูลเหล่านั้นไปยังคอมโพเนนต์ฝั่งไคลเอ็นต์ได้โดยตรง กระบวนการนี้ช่วยลดการดึงข้อมูลซ้ำซ้อนโดยช่วยให้ไคลเอ็นต์เติมข้อมูลสถานะโดยใช้ข้อมูลที่ดึงไว้ล่วงหน้าในระยะ 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);
Listener ที่มีสแนปชอตที่ซีเรียลไลซ์แล้ว
แม้ว่าข้อมูลที่ค้นหาในระยะ SSR จะมีประโยชน์สำหรับการแสดงผล CSR ครั้งแรก แต่คุณอาจยังต้องตรวจสอบบริการ Firestore เพื่อดูการอัปเดตแบบเรียลไทม์ของข้อมูลดังกล่าว
หากแอปต้องมีการอัปเดตแบบเรียลไทม์เหล่านี้ คุณสามารถใช้onSnapshotResume
ฟังก์ชันเพื่อเริ่มต้น SnapshotListener ของ Firestore ด้วยข้อมูล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);