แอปที่ใช้ Firebase Web API ที่มีเนมสเปซจากcompat
ไลบรารีย้อนกลับไปตั้งแต่เวอร์ชัน 8 หรือเวอร์ชันก่อนหน้า ควรพิจารณาย้ายข้อมูลไปยัง API แบบโมดูลตามวิธีการในคู่มือนี้
คำแนะนำนี้ถือว่าคุณคุ้นเคยกับ API ที่มีเนมสเปซและจะใช้ข้อดีของ Module Bundler เช่น Webpack หรือ Rollup เพื่ออัปเกรดและการพัฒนาแอปแบบโมดูลอย่างต่อเนื่อง
เราขอแนะนําอย่างยิ่งให้ใช้เครื่องมือรวมโมดูลในสภาพแวดล้อมการพัฒนา หากไม่ได้ใช้ คุณจะไม่สามารถใช้ข้อดีหลักๆ ของ API แบบโมดูลในการลดขนาดแอป คุณจะต้องมี npm หรือ yarn เพื่อติดตั้ง SDK
ขั้นตอนในการอัปเกรดในคู่มือนี้จะอิงตามเว็บแอปสมมติที่ใช้ SDK Authentication และ Cloud Firestore การทำตามตัวอย่างจะช่วยให้คุณเข้าใจแนวคิดและขั้นตอนปฏิบัติที่จำเป็นในการอัปเกรด Firebase Web SDK ที่รองรับทั้งหมด
เกี่ยวกับไลบรารีที่มีเนมสเปซ (compat
)
ไลบรารีสําหรับ Firebase Web SDK มี 2 ประเภท ได้แก่
- โมดูล - อินเทอร์เฟซ API ใหม่ที่ออกแบบมาเพื่ออำนวยความสะดวกในการนำโค้ดที่ไม่ได้ใช้ออก (Tree-shaking) เพื่อให้เว็บแอปมีขนาดเล็กและรวดเร็วที่สุด
- มีเนมสเปซ (
compat
) - แพลตฟอร์ม API ที่คุ้นเคยซึ่งเข้ากันได้กับ SDK เวอร์ชันเก่าอย่างสมบูรณ์ ซึ่งช่วยให้คุณอัปเกรดได้โดยไม่ต้องเปลี่ยนโค้ด Firebase ทั้งหมดพร้อมกัน ไลบรารี Compat มีข้อดีด้านขนาดหรือประสิทธิภาพน้อยมากหรือไม่มีเลยเมื่อเทียบกับไลบรารีที่มีเนมสเปซ
คู่มือนี้จะถือว่าคุณจะใช้ประโยชน์จากไลบรารีที่เข้ากันได้เพื่ออำนวยความสะดวกในการอัปเกรด ไลบรารีเหล่านี้ช่วยให้คุณใช้โค้ดที่มีเนมสเปซต่อไปได้ควบคู่ไปกับโค้ดที่ผ่านการรีแฟกทอริงสำหรับ API แบบโมดูล ซึ่งหมายความว่าคุณจะคอมไพล์และแก้ไขข้อบกพร่องของแอปได้ง่ายขึ้นเมื่อดำเนินการตามกระบวนการอัปเกรด
สําหรับแอปที่มีการใช้งาน Firebase Web SDK เพียงเล็กน้อย เช่น แอปที่เรียกใช้ Authentication API เพียงอย่างเดียว ก็อาจเหมาะที่จะรีแฟกทอเรียลโค้ดที่มีเนมสเปซเก่าๆ โดยไม่ต้องใช้ไลบรารี compat หากจะอัปเกรดแอปดังกล่าว ให้ทําตามวิธีการในคู่มือนี้สําหรับ "API แบบโมดูล" โดยไม่ต้องใช้ไลบรารี compat
เกี่ยวกับกระบวนการอัปเกรด
แต่ละขั้นตอนของกระบวนการอัปเกรดจะมีขอบเขตเพื่อให้คุณแก้ไขซอร์สโค้ดของแอปให้เสร็จ แล้วคอมไพล์และเรียกใช้แอปได้โดยไม่มีปัญหา โดยสรุปแล้ว สิ่งที่คุณต้องทำเพื่ออัปเกรดแอปมีดังนี้
- เพิ่มไลบรารีแบบโมดูลและไลบรารีที่เข้ากันได้ลงในแอป
- อัปเดตคำสั่งการนําเข้าในโค้ดเป็น compat
- ปรับโค้ดสำหรับผลิตภัณฑ์เดียว (เช่น Authentication) ให้เป็นรูปแบบโมดูล
- ไม่บังคับ: เมื่อถึงจุดนี้ ให้นำไลบรารีและโค้ด Authentication compat ออกสำหรับ Authentication เพื่อให้ได้รับประโยชน์ด้านขนาดแอปสำหรับ Authentication ก่อนดำเนินการต่อ
- ปรับแต่งฟังก์ชันของผลิตภัณฑ์แต่ละรายการ (เช่น Cloud Firestore, FCM ฯลฯ) ให้เป็นรูปแบบโมดูล คอมไพล์ และทดสอบจนกว่าทุกส่วนจะเสร็จสมบูรณ์
- อัปเดตโค้ดการเริ่มต้นเป็นรูปแบบโมดูล
- นำคำสั่งและโค้ดความเข้ากันได้ที่เหลือทั้งหมดออกจากแอป
ดาวน์โหลด SDK เวอร์ชันล่าสุด
หากต้องการเริ่มต้นใช้งาน ให้ดาวน์โหลดไลบรารีแบบโมดูลและไลบรารีที่เข้ากันได้โดยใช้ npm โดยทำดังนี้
npm i firebase@11.3.0 # OR yarn add firebase@11.3.0
อัปเดตการนําเข้าเป็น compat
หากต้องการให้โค้ดทำงานต่อไปหลังจากอัปเดต Dependency ให้เปลี่ยนคำสั่งการนําเข้าเพื่อใช้เวอร์ชัน "compat" ของการนําเข้าแต่ละรายการ เช่น
ก่อน: เวอร์ชัน 8 หรือเก่ากว่า
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
After: compat
// compat packages are API compatible with namespaced code
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
ปรับโครงสร้างเป็นรูปแบบโมดูล
แม้ว่า API ที่มีเนมสเปซจะอิงตามเนมสเปซและรูปแบบบริการแบบเชนจุด แต่แนวทางแบบโมดูลหมายความว่าโค้ดของคุณจะจัดระเบียบโดยเน้นที่ฟังก์ชันเป็นหลัก ใน API แบบโมดูล แพ็กเกจ firebase/app
และแพ็กเกจอื่นๆ จะไม่แสดงการส่งออกที่ครอบคลุมซึ่งมีเมธอดทั้งหมดจากแพ็กเกจ แต่แพ็กเกจจะส่งออกฟังก์ชันแต่ละรายการแทน
ใน API แบบโมดูล ระบบจะส่งบริการเป็นอาร์กิวเมนต์แรก จากนั้นฟังก์ชันจะใช้รายละเอียดของบริการเพื่อดำเนินการที่เหลือ มาดูวิธีการทำงานของวิธีนี้ในตัวอย่าง 2 รายการที่เปลี่ยนโครงสร้างการเรียก API Authentication และ Cloud Firestore
ตัวอย่างที่ 1: การจัดระเบียบฟังก์ชัน Authentication
Before: compat
โค้ดที่เข้ากันได้จะเหมือนกับโค้ดที่มีเนมสเปซ แต่การนําเข้าจะเปลี่ยนไป
import firebase from "firebase/compat/app";
import "firebase/compat/auth";
const auth = firebase.auth();
auth.onAuthStateChanged(user => {
// Check for user status
});
หลัง: โมดูล
ฟังก์ชัน getAuth
จะรับ firebaseApp
เป็นพารามิเตอร์แรก
ฟังก์ชัน onAuthStateChanged
ไม่ได้เชื่อมโยงกับอินสแตนซ์ auth
ดังที่ควรจะเป็นใน API ที่มีเนมสเปซ แต่เป็นฟังก์ชันอิสระที่ใช้ auth
เป็นพารามิเตอร์แรก
import { getAuth, onAuthStateChanged } from "firebase/auth";
const auth = getAuth(firebaseApp);
onAuthStateChanged(auth, user => {
// Check for user status
});
อัปเดตการจัดการวิธีการตรวจสอบสิทธิ์ getRedirectResult
มีการเปิดตัวการเปลี่ยนแปลงที่ส่งผลต่อเวอร์ชันเดิมใน getRedirectResult
เมื่อไม่มีการเรียกการดำเนินการเปลี่ยนเส้นทาง API แบบโมดูลจะแสดงผลเป็น null
ต่างจาก API ที่มีเนมสเปซซึ่งแสดงผลเป็น UserCredential
ที่มีผู้ใช้ null
Before: compat
const result = await auth.getRedirectResult()
if (result.user === null && result.credential === null) {
return null;
}
return result;
หลัง: โมดูล
const result = await getRedirectResult(auth);
// Provider of the access token could be Facebook, Github, etc.
if (result === null || provider.credentialFromResult(result) === null) {
return null;
}
return result;
ตัวอย่างที่ 2: การจัดระเบียบฟังก์ชัน Cloud Firestore
Before: compat
import "firebase/compat/firestore"
const db = firebase.firestore();
db.collection("cities").where("capital", "==", true)
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
})
.catch((error) => {
console.log("Error getting documents: ", error);
});
หลัง: โมดูล
ฟังก์ชัน getFirestore
ใช้ firebaseApp
เป็นพารามิเตอร์แรก ซึ่งแสดงผลจาก initializeApp
ในตัวอย่างก่อนหน้านี้ โปรดสังเกตว่าโค้ดในการสร้างคําค้นหานั้นแตกต่างกันมากใน API แบบโมดูล ไม่มีการต่อเชื่อม และตอนนี้มีการแสดงเมธอด เช่น query
หรือ where
เป็นฟังก์ชันอิสระ
import { getFirestore, collection, query, where, getDocs } from "firebase/firestore";
const db = getFirestore(firebaseApp);
const q = query(collection(db, "cities"), where("capital", "==", true));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
อัปเดตการอ้างอิงไปยัง Firestore DocumentSnapshot.exists
API แบบโมดูลจะทําการเปลี่ยนแปลงที่ทําให้ใช้งานไม่ได้ ซึ่งก็คือมีการเปลี่ยนแปลงพร็อพเพอร์ตี้ firestore.DocumentSnapshot.exists
เป็นเมธอด ฟังก์ชันการทำงานโดยพื้นฐานแล้วเหมือนกัน (การทดสอบว่าเอกสารมีอยู่หรือไม่) แต่คุณต้องปรับโค้ดให้ใช้เมธอดใหม่ดังที่แสดง
Before:compat
if (snapshot.exists) {
console.log("the document exists");
}
หลัง: โมดูล
if (snapshot.exists()) {
console.log("the document exists");
}
ตัวอย่างที่ 3: การรวมรูปแบบโค้ดที่มีเนมสเปซและโมดูล
การใช้ไลบรารี compat ระหว่างการอัปเกรดจะช่วยให้คุณใช้โค้ดที่มีเนมสเปซต่อไปได้ควบคู่ไปกับโค้ดที่ผ่านการรีแฟกทอริงสำหรับ API แบบโมดูล ซึ่งหมายความว่าคุณจะเก็บโค้ดที่มีเนมสเปซที่มีอยู่ของ Cloud Firestore ไว้ได้ขณะที่รีแฟกทอริง Authentication หรือโค้ด Firebase SDK อื่นๆ เป็นรูปแบบโมดูล และยังคงคอมไพล์แอปด้วยโค้ดทั้ง 2 รูปแบบได้สําเร็จ เช่นเดียวกับโค้ด API ที่มีเนมสเปซและแบบโมดูลภายในผลิตภัณฑ์ เช่น Cloud Firestore โค้ดรูปแบบใหม่และเก่าสามารถอยู่ร่วมกันได้ ตราบใดที่คุณนําเข้าแพ็กเกจที่เข้ากันได้ ดังนี้
import firebase from 'firebase/compat/app';
import 'firebase/compat/firestore';
import { getDoc } from 'firebase/firestore'
const docRef = firebase.firestore().doc();
getDoc(docRef);
โปรดทราบว่าแม้ว่าแอปจะคอมไพล์ได้ แต่คุณจะไม่ได้รับการลดขนาดแอปจากโค้ดแบบโมดูลจนกว่าจะนำคำสั่งและโค้ด compat ออกจากแอปโดยสมบูรณ์
อัปเดตโค้ดการเริ่มต้น
อัปเดตโค้ดเริ่มต้นของแอปให้ใช้ไวยากรณ์แบบโมดูล คุณควรอัปเดตโค้ดนี้หลังจากทำการรีแฟกทอริงโค้ดทั้งหมดในแอปเสร็จแล้ว เนื่องจาก firebase.initializeApp()
จะเริ่มต้นสถานะส่วนกลางสําหรับทั้ง API เวอร์ชันเก่าและเวอร์ชันโมดูล ในขณะที่ฟังก์ชัน initializeApp()
เวอร์ชันโมดูลจะเริ่มต้นเฉพาะสถานะสําหรับเวอร์ชันโมดูล
Before: compat
import firebase from "firebase/compat/app"
firebase.initializeApp({ /* config */ });
หลัง: โมดูล
import { initializeApp } from "firebase/app"
const firebaseApp = initializeApp({ /* config */ });
นำรหัสความเข้ากันได้ออก
หากต้องการใช้ประโยชน์จากขนาดของ API แบบโมดูล คุณควรแปลงการเรียกใช้ทั้งหมดเป็นสไตล์โมดูลที่แสดงด้านบนและนําคำสั่ง import "firebase/compat/*
ทั้งหมดออกจากโค้ด เมื่อดำเนินการเสร็จแล้ว ไม่ควรมีการอ้างอิงถึงfirebase.*
เนมสเปซส่วนกลางหรือโค้ดอื่นๆ ในสไตล์ API ที่มีเนมสเปซอีก
การใช้ไลบรารี compat จากหน้าต่าง
API แบบโมดูลได้รับการเพิ่มประสิทธิภาพให้ทำงานร่วมกับโมดูลแทนออบเจ็กต์ของเบราว์เซอร์
window
ไลบรารีเวอร์ชันก่อนหน้านี้อนุญาตให้โหลดและจัดการ Firebase โดยใช้เนมสเปซ window.firebase
เราไม่แนะนําให้ใช้วิธีนี้นับจากนี้เป็นต้นไปเนื่องจากไม่อนุญาตให้นําโค้ดที่ไม่ได้ใช้ออก
อย่างไรก็ตาม SDK ของ JavaScript เวอร์ชันที่เข้ากันได้จะทํางานกับ window
สําหรับนักพัฒนาแอปที่ไม่ต้องการเริ่มเส้นทางการอัปเกรดแบบโมดูลทันที
<script src="https://www.gstatic.com/firebasejs/11.3.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/11.3.0/firebase-firestore-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/11.3.0/firebase-auth-compat.js"></script>
<script>
const firebaseApp = firebase.initializeApp({ /* Firebase config */ });
const db = firebaseApp.firestore();
const auth = firebaseApp.auth();
</script>
ไลบรารีความเข้ากันได้ใช้โค้ดโมดูลในเบื้องหลังและให้บริการ API เดียวกันกับ API ที่มีเนมสเปซ ซึ่งหมายความว่าคุณสามารถดูรายละเอียดได้จากข้อมูลอ้างอิง API ที่มีเนมสเปซและข้อมูลโค้ดที่มีเนมสเปซ เราไม่แนะนําให้ใช้วิธีการนี้ในระยะยาว แต่ใช้เป็นวิธีเริ่มต้นในการอัปเกรดเป็นไลบรารีแบบโมดูลทั้งหมด
ประโยชน์และข้อจํากัดของ SDK แบบแยกส่วน
SDK แบบโมดูลทั้งหมดมีข้อดีเหนือกว่าเวอร์ชันก่อนหน้าดังนี้
- SDK แบบแยกส่วนช่วยให้แอปมีขนาดเล็กลงอย่างมาก รูปแบบนี้ใช้รูปแบบโมดูล JavaScript สมัยใหม่ ซึ่งช่วยให้ใช้แนวทาง "Tree Shaking" ในการนําเข้าเฉพาะอาร์ติแฟกต์ที่แอปจําเป็น การตัดต้นไม้ด้วย SDK แบบโมดูลอาจทำให้แอปมีขนาดเล็กลง 80% เมื่อเทียบกับแอปที่เปรียบเทียบได้ซึ่งสร้างขึ้นโดยใช้ API ที่มีเนมสเปซ ทั้งนี้ขึ้นอยู่กับแอปของคุณ
- SDK แบบโมดูลจะยังคงได้รับประโยชน์จากการพัฒนาฟีเจอร์อย่างต่อเนื่อง ในขณะที่ API ที่มีเนมสเปซจะไม่ได้รับประโยชน์ดังกล่าว