อัปเกรดจาก namespaced API เป็น modular API

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

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

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

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

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

มีไลบรารีสองประเภทสำหรับ Firebase Web SDK:

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

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

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

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

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

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

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

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

npm i firebase@10.3.1

# OR

yarn add firebase@10.3.1

อัปเดตการนำเข้าให้เข้ากันได้

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

ก่อนหน้า: เวอร์ชัน 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 แบบแยกส่วน บริการจะถูกส่งผ่านเป็นอาร์กิวเมนต์แรก จากนั้นฟังก์ชันจะใช้รายละเอียดของบริการเพื่อดำเนินการส่วนที่เหลือ มาดูวิธีการทำงานในสองตัวอย่างที่รีแฟคเตอร์การเรียกไปยัง Authentication และ Cloud Firestore API

ตัวอย่างที่ 1: refactoring ฟังก์ชันการรับรองความถูกต้อง

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

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

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 แบบเนมสเปซ แต่เป็นฟังก์ชันฟรีที่ใช้ auth เป็นพารามิเตอร์ตัวแรก

import { getAuth, onAuthStateChanged } from "firebase/auth";

const auth = getAuth(firebaseApp);
onAuthStateChanged(auth, user => {
  // Check for user status
});

อัปเดตการจัดการวิธีการรับรองความถูก getRedirectResult

API แบบโมดูลาร์แนะนำการเปลี่ยนแปลงแบบสมบูรณ์ใน getRedirectResult เมื่อไม่มีการเรียกใช้การดำเนินการเปลี่ยนเส้นทาง API แบบโมดูลาร์จะส่งคืน null ซึ่งตรงข้ามกับ 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

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

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

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

หลัง: แบบแยกส่วน

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

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

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

ใช้ไลบรารีที่เข้ากันได้จากหน้าต่าง

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

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