Nâng cấp từ API không gian tên lên API mô-đun

Các ứng dụng hiện đang sử dụng bất kỳ API Web Firebase nào có không gian tên, từ các thư viện compat trở về phiên bản 8 trở xuống, nên cân nhắc việc di chuyển sang API mô-đun theo các hướng dẫn trong hướng dẫn này.

Hướng dẫn này giả định rằng bạn đã quen thuộc với API không gian tên và bạn sẽ tận dụng bộ gói mô-đun như webpack hoặc Rollup để nâng cấp và liên tục phát triển ứng dụng theo mô-đun.

Bạn nên sử dụng trình gói mô-đun trong môi trường phát triển. Nếu không sử dụng API mô-đun, bạn sẽ không thể tận dụng những lợi ích chính của API mô-đun trong việc giảm kích thước ứng dụng. Bạn sẽ cần npm hoặc sợi để cài đặt SDK.

Các bước nâng cấp trong hướng dẫn này sẽ dựa trên một ứng dụng web ảo sử dụng SDK Xác thực và Cloud Firestore. Bằng cách xem qua các ví dụ, bạn có thể nắm vững các khái niệm và các bước thực tế cần thiết để nâng cấp tất cả các SDK web của Firebase được hỗ trợ.

Giới thiệu về các thư viện (compat) có không gian tên

Hiện có hai loại thư viện cho Firebase Web SDK:

  • Mô-đun – một nền tảng API mới được thiết kế nhằm hỗ trợ việc chống rung cây (xoá mã không sử dụng) để làm cho ứng dụng web của bạn nhỏ và nhanh nhất có thể.
  • Không gian tên (compat) – một nền tảng API quen thuộc, hoàn toàn tương thích với các phiên bản SDK cũ, cho phép bạn nâng cấp mà không cần thay đổi tất cả các mã Firebase cùng một lúc. Thư viện tương thích có ít hoặc không có ưu điểm về kích thước hoặc hiệu suất so với các thư viện có không gian tên tương ứng.

Hướng dẫn này giả định rằng bạn sẽ tận dụng các thư viện khả năng tương thích để hỗ trợ việc nâng cấp. Các thư viện này cho phép bạn tiếp tục sử dụng mã không gian tên cùng với mã được tái cấu trúc cho API mô-đun. Điều này có nghĩa là bạn có thể biên dịch và gỡ lỗi ứng dụng dễ dàng hơn trong quá trình nâng cấp.

Đối với các ứng dụng có mức độ tiếp xúc rất nhỏ với SDK Web của Firebase (ví dụ: một ứng dụng chỉ thực hiện một lệnh gọi đơn giản đến API Xác thực), thì có thể bạn nên tái cấu trúc mã không gian tên cũ hơn mà không cần dùng thư viện khả năng tương thích. Nếu đang nâng cấp một ứng dụng như vậy, bạn có thể làm theo các bước trong hướng dẫn này cho "API mô-đun" mà không cần sử dụng thư viện khả năng tương thích.

Giới thiệu về quá trình nâng cấp

Mỗi bước của quy trình nâng cấp đều có giới hạn để bạn có thể hoàn tất việc chỉnh sửa nguồn cho ứng dụng, sau đó biên dịch và chạy ứng dụng mà không bị gián đoạn. Tóm lại, sau đây là những việc bạn sẽ làm để nâng cấp một ứng dụng:

  1. Thêm thư viện mô-đun và thư viện khả năng tương thích vào ứng dụng.
  2. Cập nhật các câu lệnh nhập trong mã của bạn để tương thích.
  3. Tái cấu trúc mã cho một sản phẩm (ví dụ: Xác thực) thành kiểu mô-đun.
  4. Không bắt buộc: tại thời điểm này, hãy xoá thư viện Khả năng tương thích xác thực và mã khả năng tương thích cho Xác thực để nhận thấy lợi ích về kích thước ứng dụng cho quá trình Xác thực trước khi tiếp tục.
  5. Tái cấu trúc các hàm cho từng sản phẩm (ví dụ: Cloud Firestore, FCM, v.v.) thành kiểu mô-đun, biên dịch và kiểm thử cho đến khi hoàn tất mọi khía cạnh.
  6. Cập nhật mã khởi chạy thành kiểu mô-đun.
  7. Xoá tất cả các câu lệnh về khả năng tương thích còn lại và mã tương thích khỏi ứng dụng.

Tải SDK phiên bản mới nhất

Để bắt đầu, hãy tải thư viện mô-đun và thư viện khả năng tương thích bằng npm:

npm i firebase@10.12.2

# OR

yarn add firebase@10.12.2

Cập nhật dữ liệu nhập để tương thích

Để mã của bạn tiếp tục hoạt động sau khi cập nhật các phần phụ thuộc, hãy thay đổi câu lệnh nhập để sử dụng phiên bản "tương thích" của mỗi lần nhập. Ví dụ:

Trước: phiên bản 8 trở xuống

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

Sau: khả năng tương thích

// compat packages are API compatible with namespaced code
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';

Tái cấu trúc theo kiểu mô-đun

Mặc dù các API không gian tên dựa trên mẫu không gian tên và mẫu dịch vụ theo chuỗi dấu chấm, nhưng cách tiếp cận theo mô-đun có nghĩa là mã của bạn sẽ được sắp xếp chủ yếu xoay quanh các hàm. Trong API mô-đun, gói firebase/app và các gói khác không trả về dữ liệu xuất toàn diện chứa tất cả các phương thức từ gói đó. Thay vào đó, các gói này sẽ xuất các hàm riêng lẻ.

Trong API mô-đun, các dịch vụ được truyền làm đối số đầu tiên, sau đó hàm này sử dụng thông tin chi tiết của dịch vụ để thực hiện phần còn lại. Hãy cùng tìm hiểu cách hoạt động của tính năng này trong 2 ví dụ về việc tái cấu trúc các lệnh gọi đến API Xác thực và API Cloud Firestore.

Ví dụ 1: tái cấu trúc chức năng Xác thực

Trước: khả năng tương thích

Mã khả năng tương thích giống với mã có không gian tên, nhưng quy trình nhập đã thay đổi.

import firebase from "firebase/compat/app";
import "firebase/compat/auth";

const auth = firebase.auth();
auth.onAuthStateChanged(user => { 
  // Check for user status
});

Sau: Mô-đun

Hàm getAuth lấy firebaseApp làm tham số đầu tiên. Hàm onAuthStateChanged không được xâu chuỗi từ thực thể auth như trong API không gian tên; thay vào đó, đây là một hàm miễn phí, lấy auth làm tham số đầu tiên.

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

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

Cập nhật hoạt động xử lý của phương thức xác thực getRedirectResult

API mô-đun gây ra một thay đổi có thể gây lỗi trong getRedirectResult. Khi không có hoạt động chuyển hướng nào được gọi, API mô-đun sẽ trả về null trái ngược với API không gian tên (đã trả về một UserCredential với một người dùng null).

Trước: khả năng tương thích

const result = await auth.getRedirectResult()
if (result.user === null && result.credential === null) {
  return null;
}
return result;

Sau: Mô-đun

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;

Ví dụ 2: Tái cấu trúc hàm trên Cloud Firestore

Trước: khả năng tương thích

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);
    });

Sau: Mô-đun

Hàm getFirestore lấy firebaseApp làm tham số đầu tiên, được trả về từ initializeApp trong một ví dụ trước. Hãy lưu ý rằng cách mã để tạo truy vấn trong API mô-đun rất khác; không có chuỗi và các phương thức như query hoặc where hiện được hiển thị dưới dạng hàm miễn phí.

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());
});

Cập nhật các tham chiếu đến DocumentSnapshot.exists của Firestore

API mô-đun đưa ra một thay đổi có thể gây lỗi, trong đó thuộc tính firestore.DocumentSnapshot.exists được thay đổi thành một phương thức. Về cơ bản, chức năng này giống nhau (kiểm thử xem tài liệu có tồn tại hay không) nhưng bạn phải tái cấu trúc mã để sử dụng phương thức mới hơn như sau:

Trước:khả năng tương thích

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

Sau: Mô-đun

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

Ví dụ 3: kết hợp kiểu mã không gian tên và kiểu mã mô-đun

Việc sử dụng các thư viện về khả năng tương thích trong quá trình nâng cấp cho phép bạn tiếp tục sử dụng mã không gian tên cùng với mã được tái cấu trúc cho API mô-đun. Điều này có nghĩa là bạn có thể giữ mã không gian tên hiện có cho Cloud Firestore trong khi tái cấu trúc tính năng Xác thực hoặc mã Firebase SDK khác theo kiểu mô-đun, mà vẫn biên dịch thành công ứng dụng của mình với cả hai kiểu mã. Điều này cũng đúng với mã API không gian tên và mô-đun trong một sản phẩm như Cloud Firestore; các kiểu mã mới và cũ có thể cùng tồn tại, miễn là bạn nhập các gói tương thích:

import firebase from 'firebase/compat/app';
import 'firebase/compat/firestore';
import { getDoc } from 'firebase/firestore'

const docRef = firebase.firestore().doc();
getDoc(docRef);

Lưu ý rằng mặc dù ứng dụng sẽ biên dịch, nhưng bạn sẽ không nhận được các lợi ích về kích thước ứng dụng của mã mô-đun cho đến khi bạn xoá hoàn toàn câu lệnh và mã khả năng tương thích khỏi ứng dụng.

Cập nhật mã khởi chạy

Cập nhật mã khởi tạo của ứng dụng để sử dụng cú pháp mô-đun. Bạn cần phải cập nhật mã này sau khi bạn đã hoàn tất việc tái cấu trúc tất cả mã trong ứng dụng; điều này là do firebase.initializeApp() khởi chạy trạng thái chung cho cả API tương thích và API mô-đun, trong khi hàm initializeApp() mô-đun chỉ khởi tạo trạng thái cho mô-đun.

Trước: khả năng tương thích

import firebase from "firebase/compat/app"

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

Sau: Mô-đun

import { initializeApp } from "firebase/app"

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

Xoá mã tương thích

Để nhận thấy lợi ích về kích thước của API mô-đun, cuối cùng bạn nên chuyển đổi tất cả lệnh gọi sang kiểu mô-đun như trên và xoá tất cả câu lệnh import "firebase/compat/* khỏi mã của bạn. Khi hoàn tất, bạn sẽ không còn tham chiếu đến không gian tên chung firebase.* hay bất kỳ mã nào khác trong kiểu API không gian tên.

Sử dụng thư viện khả năng tương thích từ cửa sổ

API mô-đun được tối ưu hoá để hoạt động với các mô-đun thay vì đối tượng window của trình duyệt. Các phiên bản trước của thư viện đã cho phép tải và quản lý Firebase bằng cách sử dụng không gian tên window.firebase. Bạn không nên sử dụng cách này từ giờ trở đi vì cách này không cho phép loại bỏ mã không sử dụng. Tuy nhiên, phiên bản SDK JavaScript có khả năng tương thích vẫn hoạt động với window đối với các nhà phát triển không muốn bắt đầu lộ trình nâng cấp mô-đun ngay lập tức.

<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>

Thư viện tương thích sử dụng mã mô-đun nâng cao và cung cấp mã đó cùng với API được đặt tên theo vùng chứa tên; tức là bạn có thể tham khảo tài liệu tham khảo API chưa được đặt tên và các đoạn mã không được đặt tên để biết thông tin chi tiết. Bạn không nên sử dụng phương thức này trong thời gian dài, mà hãy dùng phương thức này để bắt đầu nâng cấp lên thư viện mô-đun đầy đủ.

Lợi ích và hạn chế của SDK mô-đun

So với các phiên bản trước đó, SDK được mô-đun hoá hoàn toàn có những ưu điểm sau:

  • SDK mô-đun cho phép giảm đáng kể kích thước ứng dụng. Thư viện này áp dụng định dạng Mô-đun JavaScript hiện đại, cho phép các phương pháp "rung cây" mà bạn chỉ nhập các cấu phần phần mềm mà ứng dụng cần. Tuỳ thuộc vào ứng dụng, việc hiệu ứng rung cây với SDK mô-đun có thể làm giảm 80% số kilobyte so với một ứng dụng tương đương được tạo bằng API không gian tên.
  • SDK mô-đun sẽ tiếp tục hưởng lợi từ quá trình phát triển tính năng liên tục, trong khi API có vùng chứa tên thì không.