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