Các ứng dụng sử dụng bất kỳ API web Firebase có không gian tên nào, từ các thư viện compat
trở về phiên bản 8 trở về trước, đều nên cân nhắc việc di chuyển sang API mô-đun theo hướng dẫn trong tài liệu này.
Hướng dẫn này giả định rằng bạn đã quen thuộc với API có không gian tên và sẽ tận dụng một trình đóng gói mô-đun như webpack hoặc Rollup để nâng cấp và phát triển ứng dụng mô-đun liên tục.
Bạn nên sử dụng trình kết hợp mô-đun trong môi trường phát triển. Nếu không sử dụng, bạn sẽ không thể tận dụng các lợi ích chính của API theo mô-đun trong việc giảm kích thước ứng dụng. Bạn sẽ cần npm hoặc yarn để 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 Authentication và Cloud Firestore. Bằng cách xem xét các ví dụ, bạn có thể nắm vững các khái niệm và bước thực tế cần thiết để nâng cấp tất cả các SDK web Firebase được hỗ trợ.
Giới thiệu về các thư viện có không gian tên (compat
)
Có 2 loại thư viện dành cho SDK web Firebase:
- Theo mô-đun – một khu vực API mới được thiết kế để hỗ trợ tính năng loại bỏ mã không dùng đến (xoá mã không dùng đến) nhằm giúp ứng dụng web của bạn có kích thước nhỏ và tốc độ nhanh nhất có thể.
- Được đặt tên theo 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 trước của SDK, cho phép bạn nâng cấp mà không cần thay đổi toàn bộ mã Firebase cùng một lúc. Các thư viện tương thích có ít hoặc không có lợi thế về kích thước hoặc hiệu suất so với các thư viện tương ứng có không gian tên.
Hướng dẫn này giả định rằng bạn sẽ tận dụng các thư viện tương thích để hỗ trợ quá trình nâng cấp. Các thư viện này cho phép bạn tiếp tục sử dụng mã có không gian tên cùng với mã được tái cấu trúc cho API theo 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 khi thực hiện quy trình nâng cấp.
Đối với những ứng dụng có mức độ tiếp xúc rất nhỏ với Firebase Web SDK (ví dụ: một ứng dụng chỉ thực hiện một lệnh gọi đơn giản đến các API Authentication), bạn có thể tái cấu trúc mã cũ theo không gian tên mà không cần sử dụng các thư viện 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 hướng dẫn trong hướng dẫn này cho "API theo mô-đun" mà không cần sử dụng các thư viện tương thích.
Giới thiệu về quy trình nâng cấp
Mỗi bước trong quy trình nâng cấp đều được điều chỉnh phạm vi để 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 gặp sự cố. Tóm lại, bạn sẽ làm những việc sau để nâng cấp ứng dụng:
- Thêm các thư viện theo mô-đun và thư viện tương thích vào ứng dụng của bạn.
- Cập nhật câu lệnh nhập trong mã của bạn thành compat.
- Tái cấu trúc mã cho một sản phẩm (ví dụ: Authentication) theo kiểu mô-đun.
- Không bắt buộc: tại thời điểm này, hãy xoá thư viện tương thích Authentication và mã tương thích cho Authentication để nhận được lợi ích về kích thước ứng dụng cho Authentication trước khi tiếp tục.
- Tái cấu trúc các hàm cho từng sản phẩm (ví dụ: Cloud Firestore, FCM, v.v.) theo kiểu mô-đun, biên dịch và kiểm thử cho đến khi hoàn tất tất cả các khu vực.
- Cập nhật mã khởi tạo theo kiểu mô-đun.
- Xoá tất cả các câu lệnh tương thích và mã tương thích còn lại khỏi ứng dụng của bạn.
Tải phiên bản SDK mới nhất
Để bắt đầu, hãy tải các thư viện theo mô-đun và thư viện tương thích bằng npm:
npm i firebase@12.0.0 # OR yarn add firebase@12.0.0
Cập nhật các tệp nhập để tương thích
Để giữ cho mã của bạn 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 "compat" của mỗi lần nhập. Ví dụ:
Trước đây: phiên bản 8 trở về trước
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
Sau: compat
// 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 có không gian tên dựa trên mẫu dịch vụ và không gian tên được liên kết bằng dấu chấm, nhưng phương pháp theo mô-đun có nghĩa là mã của bạn sẽ được sắp xếp chủ yếu xung quanh các hàm. Trong API theo mô-đun, gói firebase/app
và các gói khác không trả về một bản xuất toàn diện chứa tất cả các phương thức trong gói. Thay vào đó, các gói sẽ xuất từng hàm riêng lẻ.
Trong API theo mô-đun, các dịch vụ được truyền dưới dạng đối số đầu tiên và sau đó hàm sẽ sử dụng thông tin chi tiết về dịch vụ để thực hiện phần còn lại. Hãy xem xét cách hoạt động của việc này trong hai ví dụ tái cấu trúc các lệnh gọi đến API Authentication và Cloud Firestore.
Ví dụ 1: tái cấu trúc hàm Authentication
Trước: compat
Mã tương thích giống hệt mã có không gian tên, nhưng các lệ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: theo chủ đề
Hàm getAuth
nhận firebaseApp
làm tham số đầu tiên.
Hàm onAuthStateChanged
không được liên kết từ thực thể auth
như trong API có không gian tên; thay vào đó, đây là một hàm tự do nhận 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 cách xử lý phương thức Xác thực getRedirectResult
API theo mô-đun có một thay đổi có thể gây lỗi trong getRedirectResult
. Khi không có thao tác chuyển hướng nào được gọi, API theo mô-đun sẽ trả về null
thay vì API theo không gian tên, API này sẽ trả về UserCredential
với người dùng null
.
Trước: compat
const result = await auth.getRedirectResult()
if (result.user === null && result.credential === null) {
return null;
}
return result;
Sau: theo chủ đề
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 Cloud Firestore
Trước: 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);
});
Sau: theo chủ đề
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 đó. Lưu ý rằng mã để tạo một truy vấn rất khác nhau trong API theo mô-đun; 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 các 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 Firestore DocumentSnapshot.exists
API theo mô-đun có một thay đổi có thể gây ra lỗi, trong đó thuộc tính firestore.DocumentSnapshot.exists
đã được thay đổi thành một phương thức. Chức năng này về cơ bản là giống nhau (kiểm thử xem một 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ư minh hoạ:
Trước:compat
if (snapshot.exists) {
console.log("the document exists");
}
Sau: theo chủ đề
if (snapshot.exists()) {
console.log("the document exists");
}
Ví dụ 3: kết hợp các kiểu mã theo không gian tên và theo mô-đun
Khi nâng cấp, việc sử dụng các thư viện tương thích cho phép bạn tiếp tục sử dụng mã có không gian tên cùng với mã được tái cấu trúc cho API theo mô-đun. Điều này có nghĩa là bạn có thể giữ lại mã có không gian tên hiện có cho Cloud Firestore trong khi tái cấu trúc Authentication hoặc mã Firebase SDK khác theo kiểu mô-đun và vẫn biên dịch thành công ứng dụng của bạn bằng cả hai kiểu mã. Điều này cũng đúng với mã API theo không gian tên và theo 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 đang 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);
Xin lưu ý rằng mặc dù ứng dụng của bạn sẽ biên dịch, nhưng bạn sẽ không nhận đượ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ác câu lệnh và mã 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 chạy của ứng dụng để sử dụng cú pháp theo mô-đun. Bạn cần cập nhật mã này sau khi hoàn tất việc tái cấu trúc toàn bộ 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 theo mô-đun, trong khi hàm initializeApp()
theo mô-đun chỉ khởi chạy trạng thái cho mô-đun.
Trước: compat
import firebase from "firebase/compat/app"
firebase.initializeApp({ /* config */ });
Sau: theo chủ đề
import { initializeApp } from "firebase/app"
const firebaseApp = initializeApp({ /* config */ });
Xoá mã tương thích
Để nhận ra lợi ích về kích thước của API theo mô-đun, cuối cùng bạn nên chuyển đổi tất cả các lệnh gọi sang kiểu mô-đun như minh hoạ ở trên và xoá tất cả các câu lệnh import "firebase/compat/*
khỏi mã của bạn. Khi bạn hoàn tất, sẽ không còn các tham chiếu đến không gian tên chung firebase.*
hoặc bất kỳ mã nào khác theo kiểu API có không gian tên.
Sử dụng thư viện tương thích trong cửa sổ
API theo 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 trong tương lai vì cách này không cho phép loại bỏ mã không dùng đến.
Tuy nhiên, phiên bản tương thích của JavaScript SDK hoạt động với window
đối với những nhà phát triển không muốn bắt đầu ngay lộ trình nâng cấp theo mô-đun.
<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>
Thư viện tương thích sử dụng mã mô-đun dưới phần nâng cao và cung cấp mã này bằng cùng một API như API có không gian tên; điều này có nghĩa là bạn có thể tham khảo tài liệu tham khảo API có không gian tên và các đoạn mã có không gian 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, nhưng có thể dùng để bắt đầu nâng cấp lên thư viện hoàn toàn theo mô-đun.
Lợi ích và hạn chế của SDK theo mô-đun
SDK được mô-đun hoá hoàn toàn có những ưu điểm sau so với các phiên bản trước:
- SDK theo mô-đun giúp giảm đáng kể kích thước ứng dụng. Nó sử dụng định dạng Mô-đun JavaScript hiện đại, cho phép thực hiện các phương pháp "loại bỏ mã không dùng" trong đó bạn chỉ nhập những cấu phần phần mềm mà ứng dụng của bạn cần. Tuỳ thuộc vào ứng dụng của bạn, việc loại bỏ mã không dùng đến bằng SDK theo mô-đun có thể giúp giảm 80% số kilobyte so với một ứng dụng tương đương được tạo bằng API có không gian tên.
- SDK theo mô-đun sẽ tiếp tục hưởng lợi từ quá trình phát triển tính năng đang diễn ra, trong khi API có không gian tên sẽ không.