แอปที่ใช้ Firebase Web API ที่มีเนมสเปซใดๆ จากไลบรารี compat ย้อนกลับไปจนถึงเวอร์ชัน 8 หรือก่อนหน้า ควรพิจารณาการย้ายข้อมูลไปยัง Modular API โดยใช้คำแนะนำในคู่มือนี้
คู่มือนี้ถือว่าคุณคุ้นเคยกับ Namespaced API และจะใช้ประโยชน์จาก Module Bundler เช่น Webpack หรือ Rollup สำหรับการอัปเกรดและการพัฒนาแอปแบบแยกส่วนอย่างต่อเนื่อง
เราขอแนะนำอย่างยิ่งให้ใช้ Module Bundler ในสภาพแวดล้อมในการพัฒนาซอฟต์แวร์ หากไม่ใช้ คุณจะใช้ประโยชน์หลักของ Modular API ในการลดขนาดแอปไม่ได้ คุณจะต้องใช้ npm หรือ yarn เพื่อติดตั้ง SDK
ขั้นตอนการอัปเกรดในคู่มือนี้จะอิงตามเว็บแอปสมมติที่ ใช้ SDK ของ Authentication และ Cloud Firestore เมื่อศึกษาตัวอย่าง คุณจะเข้าใจแนวคิดและขั้นตอนการปฏิบัติที่จำเป็นในการอัปเกรด Firebase Web SDK ที่รองรับทั้งหมด
เกี่ยวกับไลบรารีที่มี Namespace (compat)
Firebase Web SDK มีไลบรารี 2 ประเภทดังนี้
- แบบแยกส่วน - พื้นผิว API ใหม่ที่ออกแบบมาเพื่อช่วยในการทำ Tree-Shaking (การนำโค้ดที่ไม่ได้ใช้ออก) เพื่อให้เว็บแอปมีขนาดเล็กและทำงานได้เร็วที่สุด
- ที่มี Namespace (
compat) - พื้นผิว API ที่คุ้นเคยซึ่งเข้ากันได้กับ SDK เวอร์ชันก่อนหน้าอย่างสมบูรณ์ ทำให้คุณอัปเกรดได้โดยไม่ต้องเปลี่ยนโค้ด Firebase ทั้งหมดพร้อมกัน ไลบรารี Compat มีข้อได้เปรียบด้านขนาดหรือประสิทธิภาพเล็กน้อยหรือไม่มีเลยเมื่อเทียบกับไลบรารีที่มี Namespace
คู่มือนี้ถือว่าคุณจะใช้ประโยชน์จากไลบรารี Compat เพื่อช่วยในการอัปเกรด ไลบรารีเหล่านี้ช่วยให้คุณใช้โค้ดที่มีเนมสเปซควบคู่ไปกับโค้ดที่ปรับโครงสร้างใหม่สำหรับ Modular API ได้ ซึ่งหมายความว่าคุณจะคอมไพล์และแก้ไขข้อบกพร่องของแอปได้ง่ายขึ้นเมื่อทำตามขั้นตอนการอัปเกรด
สำหรับแอปที่ใช้ Firebase Web SDK น้อยมาก เช่น แอปที่เรียกใช้ API ของ Authentication แบบง่ายๆ เพียงครั้งเดียว การปรับโครงสร้างโค้ดที่มี Namespace เวอร์ชันเก่าโดยไม่ใช้ไลบรารี Compat อาจเป็นวิธีที่เหมาะสม หากกำลังอัปเกรดแอปดังกล่าว คุณสามารถทำตามคำแนะนำในคู่มือนี้สำหรับ "Modular API" โดยไม่ต้องใช้ไลบรารี Compat
เกี่ยวกับการอัปเกรด
แต่ละขั้นตอนของกระบวนการอัปเกรดมีขอบเขตเพื่อให้คุณแก้ไขซอร์สโค้ดของแอปให้เสร็จสมบูรณ์ แล้วคอมไพล์และดำเนินการได้โดยไม่มีปัญหา โดยสรุป สิ่งที่คุณต้องทำเพื่ออัปเกรดแอปมีดังนี้
- เพิ่มไลบรารีแบบแยกส่วนและไลบรารี Compat ลงในแอป
- อัปเดตคำสั่งนำเข้าในโค้ดเป็น Compat
- ปรับโครงสร้างโค้ดสำหรับผลิตภัณฑ์เดียว (เช่น Authentication) เป็น สไตล์แบบแยกส่วน
- ไม่บังคับ: ในขั้นตอนนี้ ให้นำไลบรารี Compat ของ Authentication และโค้ด Compat สำหรับ Authentication ออกเพื่อ รับประโยชน์ด้านขนาดแอปสำหรับ Authentication ก่อนที่จะดำเนินการต่อ
- ปรับโครงสร้างฟังก์ชันสำหรับแต่ละผลิตภัณฑ์ (เช่น Cloud Firestore, FCM, ฯลฯ) เป็นสไตล์แบบแยกส่วน โดยคอมไพล์และ ทดสอบจนกว่าทุกส่วนจะเสร็จสมบูรณ์
- อัปเดตโค้ดการเริ่มต้นเป็นสไตล์แบบแยกส่วน
- นำคำสั่ง Compat และโค้ด Compat ที่เหลือทั้งหมดออกจากแอป
ดาวน์โหลด SDK เวอร์ชันล่าสุด
หากต้องการเริ่มต้นใช้งาน ให้ดาวน์โหลดไลบรารีแบบแยกส่วนและไลบรารี Compat โดยใช้ npm ดังนี้
npm i firebase@12.13.0 # OR yarn add firebase@12.13.0
อัปเดตการนำเข้าเป็น Compat
หากต้องการให้โค้ดทำงานได้ต่อไปหลังจากอัปเดตการขึ้นต่อกัน ให้เปลี่ยนคำสั่งนำเข้าให้ใช้เวอร์ชัน "compat" ของการนำเข้าแต่ละรายการ เช่น
ก่อน: เวอร์ชัน 8 หรือก่อนหน้า
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
หลัง: compat
// compat packages are API compatible with namespaced code
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
ปรับโครงสร้างเป็นสไตล์แบบแยกส่วน
แม้ว่า API ที่มี Namespace จะอิงตาม Namespace ที่เชื่อมต่อด้วยจุดและรูปแบบบริการ แต่แนวทางแบบแยกส่วนหมายความว่าโค้ดของคุณจะจัดระเบียบโดยหลักๆ แล้วจะอิงตามฟังก์ชัน ใน Modular API แพ็กเกจ firebase/app และแพ็กเกจอื่นๆ จะไม่แสดงการส่งออกที่ครอบคลุมซึ่งมีเมธอดทั้งหมดจากแพ็กเกจ แต่แพ็กเกจจะส่งออกฟังก์ชันแต่ละรายการแทน
ใน Modular API ระบบจะส่งบริการเป็นอาร์กิวเมนต์แรก จากนั้นฟังก์ชันจะใช้รายละเอียดของบริการเพื่อดำเนินการที่เหลือ มาดูวิธีการทำงานนี้ใน 2 ตัวอย่างที่ปรับโครงสร้างการเรียกใช้ API ของ Authentication และ Cloud Firestore
ตัวอย่างที่ 1: การปรับโครงสร้างฟังก์ชัน Authentication
ก่อน: compat
โค้ด Compat เหมือนกับโค้ดที่มี Namespace แต่การนำเข้ามีการเปลี่ยนแปลง
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 เหมือนกับใน Namespaced API แต่เป็นฟังก์ชันอิสระที่ใช้ auth เป็นพารามิเตอร์แรก
import { getAuth, onAuthStateChanged } from "firebase/auth";
const auth = getAuth(firebaseApp);
onAuthStateChanged(auth, user => {
// Check for user status
});
อัปเดตการจัดการเมธอด getRedirectResult ของการตรวจสอบสิทธิ์
Modular API มีการเปลี่ยนแปลงที่ทำให้เกิดข้อผิดพลาดใน getRedirectResult เมื่อไม่มีการเรียกใช้การดำเนินการเปลี่ยนเส้นทาง Modular API จะแสดงผล null ซึ่งแตกต่างจาก Namespaced API ซึ่งแสดงผล UserCredential ที่มีผู้ใช้ null
ก่อน: 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
ก่อน: 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 ในตัวอย่างก่อนหน้า โปรดสังเกตว่าโค้ดสำหรับสร้างคิวรีแตกต่างกันมากใน Modular 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());
});
อัปเดตการอ้างอิง DocumentSnapshot.exists ของ Firestore
Modular API มีการเปลี่ยนแปลงที่ทำให้เกิดข้อผิดพลาด โดยพร็อพเพอร์ตี้ firestore.DocumentSnapshot.exists เปลี่ยนเป็น เมธอด ฟังก์ชันการทำงานโดยพื้นฐานแล้วจะเหมือนกัน (การทดสอบว่ามีเอกสารอยู่หรือไม่) แต่คุณต้องปรับโครงสร้างโค้ดเพื่อใช้เมธอดใหม่กว่าดังที่แสดง
ก่อน:compat
if (snapshot.exists) {
console.log("the document exists");
}
หลัง: แบบแยกส่วน
if (snapshot.exists()) {
console.log("the document exists");
}
ตัวอย่างที่ 3: การรวมสไตล์โค้ดที่มี Namespace และแบบแยกส่วน
การใช้ไลบรารี Compat ระหว่างการอัปเกรดช่วยให้คุณใช้โค้ดที่มีเนมสเปซควบคู่ไปกับโค้ดที่ปรับโครงสร้างใหม่สำหรับ Modular API ได้ ซึ่งหมายความว่าคุณสามารถเก็บ โค้ดที่มี Namespace ที่มีอยู่สำหรับ Cloud Firestore ไว้ขณะที่ปรับโครงสร้าง Authentication หรือโค้ด Firebase SDK อื่นๆ เป็น สไตล์แบบแยกส่วน และยังคงคอมไพล์แอปด้วยโค้ดทั้ง 2 สไตล์ได้สำเร็จ เช่นเดียวกันกับโค้ด Modular API ที่มี Namespace และแบบแยกส่วน ภายใน ผลิตภัณฑ์ เช่น Cloud Firestore โดยโค้ดสไตล์ใหม่และเก่าสามารถอยู่ร่วมกันได้ ตราบใดที่คุณนำเข้าแพ็กเกจ Compat
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 แบบ Compat และแบบแยกส่วน ในขณะที่ ฟังก์ชันinitializeApp()แบบแยกส่วนจะเริ่มต้นสถานะสำหรับแบบแยกส่วนเท่านั้น
ก่อน: compat
import firebase from "firebase/compat/app"
firebase.initializeApp({ /* config */ });
หลัง: แบบแยกส่วน
import { initializeApp } from "firebase/app"
const firebaseApp = initializeApp({ /* config */ });
นำโค้ด Compat ออก
หากต้องการรับประโยชน์ด้านขนาดจาก Modular API คุณควรแปลงการเรียกใช้ทั้งหมดเป็นสไตล์แบบแยกส่วนที่แสดงด้านบน และนำคำสั่ง
import "firebase/compat/* ทั้งหมดออกจากโค้ด เมื่อดำเนินการเสร็จแล้ว จะต้องไม่มีการอ้างอิง Namespace ส่วนกลาง firebase.* หรือโค้ดอื่นๆ ในสไตล์ Namespaced API อีกต่อไป
การใช้ไลบรารี Compat จากหน้าต่าง
Modular API ได้รับการเพิ่มประสิทธิภาพให้ทำงานกับโมดูลแทนออบเจ็กต์ window ของเบราว์เซอร์ ไลบรารีเวอร์ชันก่อนหน้าอนุญาตให้โหลดและจัดการ Firebase ได้โดยใช้ Namespace window.firebase เราไม่แนะนำให้ใช้วิธีนี้ต่อไปเนื่องจากไม่สามารถกำจัดโค้ดที่ไม่ได้ใช้ออกได้
อย่างไรก็ตาม JavaScript SDK เวอร์ชัน Compat จะทำงานกับ window สำหรับนักพัฒนาแอปที่ไม่ต้องการเริ่มเส้นทางการอัปเกรดแบบแยกส่วนทันที
<script src="https://www.gstatic.com/firebasejs/12.13.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/12.13.0/firebase-firestore-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/12.13.0/firebase-auth-compat.js"></script>
<script>
const firebaseApp = firebase.initializeApp({ /* Firebase config */ });
const db = firebaseApp.firestore();
const auth = firebaseApp.auth();
</script>
ไลบรารีความเข้ากันได้ใช้โค้ดแบบแยกส่วนเบื้องหลังและ มี API เดียวกันกับ Namespaced API ซึ่งหมายความว่าคุณสามารถ ดูรายละเอียดได้จากเอกสารอ้างอิง Namespaced API และข้อมูลโค้ดที่มี Namespace เราไม่แนะนำให้ใช้วิธีนี้ในระยะยาว แต่ใช้เป็นจุดเริ่มต้นในการอัปเกรดเป็นไลบรารีแบบแยกส่วนอย่างสมบูรณ์
ข้อดีและข้อจำกัดของ SDK แบบแยกส่วน
SDK ที่แยกส่วนอย่างสมบูรณ์มีข้อดีดังต่อไปนี้เมื่อเทียบกับเวอร์ชันก่อนหน้า
- SDK แบบแยกส่วนช่วยลดขนาดแอปได้อย่างมาก โดยใช้รูปแบบโมดูล JavaScript ที่ทันสมัย ซึ่งช่วยให้สามารถใช้แนวทางปฏิบัติ "Tree-Shaking" ที่คุณนำเข้าเฉพาะอาร์ติแฟกต์ที่แอปต้องการ การทำ Tree-Shaking ด้วย SDK แบบแยกส่วนอาจทำให้แอปมีขนาดเล็กลงถึง 80% เมื่อเทียบกับแอปที่เทียบเคียงกันซึ่งสร้างขึ้นโดยใช้ Namespaced API ทั้งนี้ขึ้นอยู่กับแอปของคุณ
- SDK แบบแยกส่วนจะได้รับประโยชน์จากการพัฒนาฟีเจอร์อย่างต่อเนื่อง ในขณะที่ Namespaced API จะไม่ได้รับประโยชน์ดังกล่าว