หากเคยใช้ 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 ระบบจะลดจำนวนการอ้างอิง และอินสแตนซ์จะถูกปล่อยหลังจากจำนวนการอ้างอิงถึงศูนย์
กำลังล้างอินสแตนซ์ 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 ที่มีโทเค็นรหัสการตรวจสอบสิทธิ์จะพยายามลงชื่อเข้าใช้ผู้ใช้เมื่อเริ่มต้นโดยที่แอปพลิเคชันไม่จำเป็นต้องเรียกใช้วิธีการลงชื่อเข้าใช้ใดๆ
การระบุโทเค็นรหัสการตรวจสอบสิทธิ์ช่วยให้แอปใช้วิธีการลงชื่อเข้าใช้ของการตรวจสอบสิทธิ์ในไคลเอ็นต์ได้ ซึ่งช่วยให้มั่นใจว่าเซสชันจะดำเนินต่อไปในฝั่งเซิร์ฟเวอร์ แม้จะเป็นวิธีการลงชื่อเข้าใช้ที่ต้องมีการโต้ตอบกับผู้ใช้ก็ตาม นอกจากนี้ยังช่วยให้สามารถถ่ายโอนการดำเนินการที่ใช้ทรัพยากรมากไปยังเซิร์ฟเวอร์ได้ เช่น การค้นหา 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 วิธีนี้เกี่ยวข้องกับการสกัดกั้นคำขอดึงข้อมูลที่ทริกเกอร์ SSR และต่อท้ายโทเค็นกับส่วนหัวของคำขอ
ดูการจัดการเซสชันด้วย Service Worker เพื่อดูตัวอย่างการติดตั้งใช้งาน Service Worker ของ Firebase Auth นอกจากนี้ โปรดดูการเปลี่ยนแปลงฝั่งเซิร์ฟเวอร์สำหรับโค้ดที่สาธิตวิธีแยกวิเคราะห์โทเค็นเหล่านี้จากส่วนหัวเพื่อใช้ในการเริ่มต้น 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);
ผู้ฟังที่มีภาพรวมแบบเรียงอันดับ
แม้ว่าข้อมูลที่ค้นหาในระหว่างระยะ 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);