Если в вашем приложении используются веб-API Firebase с пространствами имен из библиотек compat, версии 8 или более ранних, рекомендуем перейти на модульный API, следуя инструкциям в этом руководстве.
В этом руководстве предполагается, что вы знакомы с API с пространством имен и будете использовать сборщик модулей, например webpack или Rollup, для обновления и дальнейшей разработки модульного приложения.
Настоятельно рекомендуем использовать сборщик модулей в среде разработки. Если вы не используете сборщик модулей, то не сможете воспользоваться основным преимуществом модульного API – уменьшением размера приложения. Для установки SDK вам понадобится npm или yarn.
В этом руководстве мы будем использовать в качестве примера воображаемое веб-приложение, в котором используются SDK Authentication и Cloud Firestore. Выполняя примеры, вы сможете освоить концепции и практические шаги, необходимые для обновления всех поддерживаемых веб-SDK Firebase.
О библиотеках с пространством имен (compat)
Для Firebase Web SDK доступны два типа библиотек:
- Модульный. Новый API, предназначенный для упрощения удаления неиспользуемого кода, чтобы сделать ваше веб-приложение как можно меньше и быстрее.
- Пространство имен (
compat). Знакомый API, полностью совместимый с более ранними версиями SDK. Позволяет выполнить обновление, не меняя весь код Firebase сразу. Библиотеки совместимости практически не имеют преимуществ в размере или производительности по сравнению с аналогами с пространствами имен.
В этом руководстве предполагается, что вы будете использовать библиотеки совместимости, чтобы упростить обновление. Эти библиотеки позволяют использовать код с пространствами имен наряду с кодом, рефакторинг которого выполнен для модульного API. Это упростит компиляцию и отладку приложения в процессе обновления.
Для приложений, которые мало взаимодействуют с веб-SDK Firebase (например, только выполняют простой вызов API Authentication), может быть целесообразно провести рефакторинг старого кода с пространствами имен без использования библиотек совместимости. Если вы обновляете такое приложение, следуйте инструкциям в этом руководстве для модульного API, не используя библиотеки совместимости.
Как будет проходить обновление
Каждый этап обновления ограничен, чтобы вы могли завершить редактирование исходного кода приложения, а затем скомпилировать и запустить его без сбоев. Подводя итог, вот что вы сделаете, чтобы обновить приложение:
- Добавьте в приложение модульные библиотеки и библиотеки совместимости.
- Обновите операторы импорта в коде, чтобы обеспечить совместимость.
- Проведите рефакторинг кода для одного продукта (например, Authentication) в модульном стиле.
- Необязательно. На этом этапе удалите библиотеку совместимости Authentication и код совместимости для Authentication, чтобы уменьшить размер приложения для Authentication.
- Проведите рефакторинг функций для каждого продукта (например, Cloud Firestore, FCM и т. д.) в модульном стиле, компилируя и тестируя до тех пор, пока все области не будут завершены.
- Обновите код инициализации до модульного стиля.
- Удалите из приложения все оставшиеся операторы и код совместимости.
Получите последнюю версию SDK
Для начала получите модульные библиотеки и библиотеки совместимости с помощью npm:
npm i firebase@13.2.0 # OR yarn add firebase@13.2.0
Обновить импорт для совместимости
Чтобы код работал после обновления зависимостей, измените операторы импорта так, чтобы они использовали совместимую версию каждого импорта. Пример:
До: версия 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';
Рефакторинг в модульный стиль
В то время как API с пространством имен основаны на шаблоне сервиса и пространства имен с точкой, модульный подход означает, что ваш код будет организован в основном вокруг функций. В модульном API пакет firebase/app и другие пакеты не возвращают полный экспорт, содержащий все методы из пакета. Вместо этого пакеты экспортируют отдельные функции.
В модульном API сервисы передаются в качестве первого аргумента, а затем функция использует сведения о сервисе для выполнения остальных действий. Давайте рассмотрим, как это работает, на двух примерах, в которых рефакторинг вызовов выполняется для API Authentication и Cloud Firestore.
Пример 1. Рефакторинг функции Authentication
До: 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, как это было бы в 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.
До: 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 в предыдущем примере. Обратите внимание, что код для формирования запроса в модульном 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 заменено на метод. Функциональность по сути та же (проверка существования документа), но вам нужно провести рефакторинг кода, чтобы использовать новый метод, как показано ниже:
Before:compat
if (snapshot.exists) {
console.log("the document exists");
}
После: модульный подход
if (snapshot.exists()) {
console.log("the document exists");
}
Пример 3. Сочетание стилей кода с пространствами имен и модулями
Используя библиотеки совместимости во время обновления, вы можете продолжать использовать код с пространствами имен наряду с кодом, рефакторинг которого выполнен для модульного API. Это значит, что вы можете сохранить существующий код с пространствами имен для Cloud Firestore, пока проводите рефакторинг Authentication или другого кода Firebase SDK в модульном стиле, и при этом успешно компилировать приложение с обоими стилями кода. То же самое относится к коду API с пространством имен и модульному коду 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() инициализирует только состояние для модульных API.
До: compat
import firebase from "firebase/compat/app"
firebase.initializeApp({ /* config */ });
После: модульный подход
import { initializeApp } from "firebase/app"
const firebaseApp = initializeApp({ /* config */ });
Удалить код совместимости
Чтобы воспользоваться преимуществами модульного API, вам нужно преобразовать все вызовы в модульный стиль, как показано выше, и удалить все операторы import "firebase/compat/* из кода. После этого в коде не должно остаться ссылок на глобальное пространство имен firebase.* или другой код в стиле API с пространством имен.
Использование библиотеки совместимости из окна
Модульный 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, что и API с пространством имен. Это означает, что вы можете обратиться к документации по API с пространством имен и фрагментам кода с пространством имен, чтобы узнать больше. Этот метод не рекомендуется для долгосрочного использования, но подходит для начала перехода на полностью модульную библиотеку.
Преимущества и ограничения модульного SDK
Полностью модульный SDK имеет следующие преимущества по сравнению с более ранними версиями:
- Модульный SDK позволяет значительно уменьшить размер приложения. В нем используется современный формат модулей JavaScript, позволяющий импортировать только те артефакты, которые нужны вашему приложению. В зависимости от приложения, удаление неиспользуемого кода с помощью модульного SDK может привести к уменьшению размера на 80 % по сравнению с аналогичным приложением, созданным с использованием API с пространством имен.
- Модульный SDK будет и дальше получать новые функции, а API с пространством имен – нет.