อัปเกรดจาก API ที่มีเนมสเปซเป็นแอปพลิเคชันแบบโมดูล

แอปที่ใช้ 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

เกี่ยวกับกระบวนการอัปเกรด

กระบวนการอัปเกรดแต่ละขั้นตอนจะมีการกำหนดขอบเขตเพื่อให้คุณแก้ไขแหล่งที่มาของแอปให้เสร็จสิ้น จากนั้นจึงคอมไพล์และเรียกใช้แอปได้โดยไม่เกิดความเสียหาย โดยสรุปแล้ว สิ่งที่คุณต้องทำเพื่ออัปเกรดแอปมีดังนี้

  1. เพิ่มไลบรารีแบบโมดูลและไลบรารีความเข้ากันได้ลงในแอป
  2. อัปเดตคำสั่งนำเข้าในโค้ดเป็น compat
  3. เปลี่ยนโครงสร้างโค้ดสำหรับผลิตภัณฑ์เดียว (เช่น Authentication) เป็นรูปแบบโมดูลาร์
  4. ไม่บังคับ: ณ จุดนี้ ให้นำไลบรารีความเข้ากันได้ของ Authentication และโค้ดความเข้ากันได้สำหรับ Authentication ออกเพื่อรับประโยชน์ด้านขนาดแอปสำหรับ Authentication ก่อนดำเนินการต่อ
  5. เปลี่ยนโครงสร้างฟังก์ชันสำหรับแต่ละผลิตภัณฑ์ (เช่น Cloud Firestore, FCM ฯลฯ) เป็นรูปแบบโมดูลาร์ โดยคอมไพล์และทดสอบจนกว่าจะเสร็จสมบูรณ์ทุกส่วน
  6. อัปเดตโค้ดการเริ่มต้นเป็นรูปแบบโมดูลาร์
  7. นำคำสั่ง 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 จะไม่ได้รับประโยชน์นี้