Обновление API с пространством имен до модульного API.

Приложениям, которые в настоящее время используют любые веб-API Firebase с пространством имен, начиная с compat библиотек до версии 8 или более ранней, следует рассмотреть возможность перехода на модульный API, следуя инструкциям в этом руководстве.

В этом руководстве предполагается, что вы знакомы с API пространства имен и воспользуетесь преимуществами сборщика модулей, такого как Webpack или Rollup , для обновления и постоянной разработки модульных приложений.

Настоятельно рекомендуется использовать сборщик модулей в вашей среде разработки. Если вы его не используете, вы не сможете воспользоваться основными преимуществами модульного API, заключающимися в уменьшении размера приложения. Для установки SDK вам понадобится npm или Yarn .

Шаги по обновлению, описанные в этом руководстве, будут основаны на воображаемом веб-приложении, которое использует SDK для аутентификации и Cloud Firestore. Работая с примерами, вы сможете освоить концепции и практические шаги, необходимые для обновления всех поддерживаемых веб-SDK Firebase.

О библиотеках пространства имен ( compat )

Для Firebase Web SDK доступны два типа библиотек:

  • Модульность — новая поверхность API, предназначенная для облегчения встряхивания дерева (удаления неиспользуемого кода), чтобы сделать ваше веб-приложение как можно меньшим и быстрым.
  • Namespaced ( compat ) — знакомая поверхность API, полностью совместимая с более ранними версиями SDK, позволяющая выполнять обновление без изменения всего кода Firebase одновременно. Библиотеки совместимости практически не имеют преимуществ по размеру или производительности по сравнению со своими аналогами в пространстве имен.

В этом руководстве предполагается, что вы воспользуетесь преимуществами совместимых библиотек для облегчения обновления. Эти библиотеки позволяют вам продолжать использовать код с пространством имен наряду с кодом, реорганизованным для модульного API. Это означает, что вам будет проще компилировать и отлаживать приложение во время процесса обновления.

Для приложений с очень небольшим использованием Firebase Web SDK — например, приложения, которое выполняет только простой вызов API-интерфейсов аутентификации — может оказаться целесообразным провести рефакторинг старого кода с пространством имен без использования совместимых библиотек. Если вы обновляете такое приложение, вы можете следовать инструкциям в этом руководстве для «модульного API», не используя совместимые библиотеки.

О процессе обновления

Каждый шаг процесса обновления ограничен таким образом, чтобы вы могли завершить редактирование исходного кода своего приложения, а затем скомпилировать и запустить его без сбоев. Подводя итог, вот что вам нужно сделать, чтобы обновить приложение:

  1. Добавьте в свое приложение модульные библиотеки и совместимые библиотеки.
  2. Обновите операторы импорта в своем коде для обеспечения совместимости.
  3. Рефакторинг кода для одного продукта (например, Аутентификация) в модульном стиле.
  4. Необязательно: на этом этапе удалите библиотеку совместимости аутентификации и код совместимости для аутентификации, чтобы реализовать преимущество размера приложения для аутентификации, прежде чем продолжить.
  5. Рефакторинг функций для каждого продукта (например, Cloud Firestore, FCM и т. д.) в модульном стиле, компилируя и тестируя до тех пор, пока все области не будут завершены.
  6. Обновите код инициализации до модульного стиля.
  7. Удалите все оставшиеся операторы совместимости и код совместимости из вашего приложения.

Получите последнюю версию SDK

Для начала получите модульные и совместимые библиотеки с помощью npm:

npm i firebase@10.11.0

# OR

yarn add firebase@10.11.0

Обновить импорт для совместимости

Чтобы ваш код продолжал работать после обновления зависимостей, измените операторы импорта, чтобы использовать «совместимую» версию каждого импорта. Например:

До: версия 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 службы передаются в качестве первого аргумента, а затем функция использует сведения об услуге, чтобы сделать все остальное. Давайте рассмотрим, как это работает, на двух примерах рефакторинга вызовов API-интерфейсов аутентификации и Cloud Firestore.

Пример 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 , как это было бы в 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() инициализирует только состояние для модульных API.

До: совместимость

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/10.11.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/10.11.0/firebase-firestore-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/10.11.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 с пространством имен — нет.