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