อัปเกรดจาก Namespaced API เป็น Modular API

แอปที่ใช้ Firebase Web API แบบมีเนมสเปซอยู่ในขณะนี้ จากไลบรารี compat ย้อนกลับไปจนถึงเวอร์ชัน 8 หรือเวอร์ชันก่อนหน้า ควรพิจารณาย้ายข้อมูลไปยัง Modular API ตามวิธีการในคู่มือนี้

คู่มือนี้จะสมมติว่าคุณคุ้นเคยกับ API ที่ใช้เนมสเปซ และจะใช้ประโยชน์จาก Bundler โมดูล เช่น webpack หรือ Rollup สำหรับการอัปเกรดและพัฒนาแอปโมดูลอย่างต่อเนื่อง

เราขอแนะนำให้ใช้ Bundler โมดูลในสภาพแวดล้อมการพัฒนาของคุณ หากไม่ได้ใช้ API ดังกล่าว คุณจะไม่สามารถใช้ประโยชน์จาก ข้อดีหลักของ API แบบแยกส่วนในแง่ของขนาดแอปที่ลดขนาดลง คุณจะต้องมี npm หรือyarn เพื่อติดตั้ง SDK

ขั้นตอนการอัปเกรดในคู่มือนี้จะอิงตามเว็บแอปสมมติที่ใช้การตรวจสอบสิทธิ์และ Cloud Firestore SDK เมื่อลองดูตัวอย่างแล้ว คุณจะทำความเข้าใจแนวคิดและขั้นตอนที่นำไปใช้ได้จริงในการอัปเกรด Firebase Web SDK ที่รองรับทั้งหมด

เกี่ยวกับไลบรารีที่ใช้เนมสเปซ (compat)

Firebase Web SDK มีไลบรารีอยู่ 2 ประเภท ได้แก่

  • โมดูลาร์ - แพลตฟอร์ม API ใหม่ที่ออกแบบมาเพื่ออำนวยความสะดวกในการเขย่าต้นไม้ (นำโค้ดที่ไม่ได้ใช้ออก) เพื่อให้เว็บแอปมีขนาดเล็กและเร็วที่สุด
  • เนมสเปซ (compat) - แพลตฟอร์ม API ที่คุ้นเคยซึ่งทำงานร่วมกับ SDK เวอร์ชันก่อนหน้านี้ได้อย่างสมบูรณ์ คุณจึงอัปเกรดได้โดยไม่ต้องเปลี่ยนโค้ด Firebase ทั้งหมดพร้อมกัน ไลบรารี Compat มีข้อได้เปรียบด้านประสิทธิภาพหรือขนาด เพียงเล็กน้อยหรือไม่มีเลยเมื่อเทียบกับคู่ที่ใช้เนมสเปซ

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

สำหรับแอปที่มีจำนวนผู้ที่เห็น Firebase Web SDK น้อยมาก เช่น แอปที่มีเพียงการเรียก API การตรวจสอบสิทธิ์แบบง่ายๆ นั้น อาจเป็นประโยชน์ในการเปลี่ยนโครงสร้างโค้ดเนมสเปซเก่าโดยไม่ต้องใช้ไลบรารี Compat หากกำลังอัปเกรดแอปเช่นนี้ คุณทำตามวิธีการในคู่มือสำหรับ "modular API" ได้โดยไม่ต้องใช้ไลบรารีความเข้ากันได้

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

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

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

ดาวน์โหลด SDK เวอร์ชันล่าสุด

ในการเริ่มต้นใช้งาน ให้เรียกไลบรารีโมดูลและไลบรารีที่ใช้ร่วมกันโดยใช้ npm ดังนี้

npm i firebase@10.12.2

# OR

yarn add firebase@10.12.2

อัปเดตการนำเข้าไปยังการจับคู่

เพื่อให้โค้ดทำงานได้ต่อไปหลังจากอัปเดตทรัพยากร Dependency แล้ว ให้เปลี่ยนคำสั่งการนำเข้าเพื่อใช้เวอร์ชัน "compat" ของการนำเข้าแต่ละครั้ง เช่น

ก่อน: เวอร์ชัน 8 หรือเวอร์ชันก่อนหน้า

import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';

หลัง: การจับคู่

// 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 การตรวจสอบสิทธิ์และ Cloud Firestore API ใหม่กัน

ตัวอย่างที่ 1: การเปลี่ยนโครงสร้างภายในฟังก์ชันการตรวจสอบสิทธิ์

ก่อน: ความเข้ากันได้

รหัสการจับคู่จะเหมือนกับรหัสเนมสเปซ แต่การนำเข้ามีการเปลี่ยนแปลง

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 เมื่อไม่มีการเรียกใช้การดำเนินการเปลี่ยนเส้นทาง API โมดูลนี้จะแสดงผล null แทนที่จะเป็น Namespaced API ซึ่งแสดงผล UserCredential ที่มีผู้ใช้ null

ก่อน: ความเข้ากันได้

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

ก่อน: ความเข้ากันได้

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

Modular API มีการเปลี่ยนแปลงที่ส่งผลกับส่วนอื่นในระบบซึ่งมีการเปลี่ยนพร็อพเพอร์ตี้ firestore.DocumentSnapshot.exists เป็นเมธอด โดยพื้นฐานแล้วฟังก์ชันการทำงานจะเหมือนกัน (ทดสอบว่ามีเอกสารอยู่หรือไม่) แต่คุณต้องเปลี่ยนโครงสร้างภายในโค้ดเพื่อใช้วิธีการที่ใหม่กว่าดังที่แสดงไว้

ก่อน:ความเข้ากันได้

if (snapshot.exists) {
  console.log("the document exists");
}

หลัง: โมดูล

if (snapshot.exists()) {
  console.log("the document exists");
}

ตัวอย่างที่ 3: การรวมรูปแบบโค้ดเนมสเปซและโมดูลาร์

การใช้ไลบรารี Compat ระหว่างการอัปเกรดช่วยให้คุณใช้รหัสเนมสเปซต่อไปพร้อมกับการเปลี่ยนโครงสร้างโค้ดใหม่สำหรับ API โมดูล ซึ่งหมายความว่าคุณจะเก็บโค้ดเนมสเปซที่มีอยู่สำหรับ Cloud Firestore ไว้ได้ขณะที่เปลี่ยนโครงสร้างการตรวจสอบสิทธิ์หรือโค้ด 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);

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

อัปเดตโค้ดการเริ่มต้น

อัปเดตโค้ดการเริ่มต้นของแอปให้ใช้ไวยากรณ์โมดูล คุณต้องอัปเดตโค้ดนี้หลังจากที่คุณเปลี่ยนโครงสร้างโค้ดทั้งหมดในแอปเสร็จแล้ว นั่นเป็นเพราะ firebase.initializeApp() เริ่มต้นสถานะสากลสำหรับทั้ง API ที่ใช้ร่วมกันและโมดูลาร์ ในขณะที่ฟังก์ชัน initializeApp() แบบโมดูลจะเริ่มต้นเฉพาะสถานะสำหรับโมดูล

ก่อน: ความเข้ากันได้

import firebase from "firebase/compat/app"

firebase.initializeApp({ /* config */ });

หลัง: โมดูล

import { initializeApp } from "firebase/app"

const firebaseApp = initializeApp({ /* config */ });

นำรหัสความเข้ากันได้ออก

หากต้องการใช้ประโยชน์จากขนาดของ API โมดูล คุณควรแปลงคำขอทั้งหมดเป็นรูปแบบโมดูลที่แสดงด้านบนและนำคำสั่ง import "firebase/compat/* ทั้งหมดออกจากโค้ด เมื่อเสร็จแล้ว ไม่ควรมีการอ้างอิงไปยังเนมสเปซส่วนกลางของ firebase.* หรือโค้ดอื่นใดในรูปแบบ API ที่ใช้เนมสเปซอีก

การใช้ไลบรารีการทำงานร่วมกันจากหน้าต่าง

Modular API ได้รับการเพิ่มประสิทธิภาพให้ทํางานกับโมดูล ไม่ใช่ออบเจ็กต์ window ของเบราว์เซอร์ ไลบรารีเวอร์ชันก่อนหน้าอนุญาตให้โหลดและการจัดการ Firebase โดยใช้เนมสเปซ window.firebase เราไม่แนะนำให้ทำเช่นนี้ต่อไป เนื่องจากไม่อนุญาตให้ลบโค้ดที่ไม่ได้ใช้งาน แต่ JavaScript SDK เวอร์ชันที่เข้ากันได้จะทำงานร่วมกับ window สำหรับนักพัฒนาซอฟต์แวร์ที่ไม่ต้องการเริ่มเส้นทางการอัปเกรดแบบแยกส่วนทันที

<script src="https://www.gstatic.com/firebasejs/10.12.2/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/10.12.2/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 ที่ทันสมัย ทำให้สำหรับการฝึก "เขย่าต้นไม้" ที่คุณนำเข้าเฉพาะอาร์ติแฟกต์ที่แอปต้องการเท่านั้น การเขย่าต้นไม้ด้วย SDK แบบแยกส่วนอาจส่งผลให้มีกิโลไบต์น้อยกว่าแอปที่เทียบกันได้ 80% ซึ่งสร้างขึ้นโดยใช้ Namespaced API ทั้งนี้ขึ้นอยู่กับแอปของคุณ
  • SDK แบบแยกส่วนจะได้รับประโยชน์จากการพัฒนาฟีเจอร์อย่างต่อเนื่อง ในขณะที่ API ที่ใช้เนมสเปซจะไม่ได้รับผลใดๆ