AngularInDepth уходит от Medium. Более свежие статьи размещаются на новой платформе inDepth.dev. Спасибо за то, что участвуете в глубоком движении!

В этом посте я буду создавать API с Google Firebase. Я буду создавать серверную часть с помощью Firebase Cloud Functions и ExpressJS.

Прежде чем я начну, я рекомендую вам выполнить следующую настройку:

  1. Настройка терминала на компьютере под управлением Windows, Linux или Mac (OSX)
  2. Узел 10.10 установлен
  3. NVM установил по инструкции здесь
  4. Аккаунт Google
  5. Почтальон установлен
  6. Firebase CLI устанавливается с помощью терминальной команды npm install -g firebase-tools

Я буду иметь в виду код, доступный в этом репозитории GitHub. Репозиторий GitHub также содержит коллекцию Postman - я рекомендую импортировать эту коллекцию и использовать ее для тестирования вашего проекта. Обратите внимание, что app id в путях URL относится к моему развернутому проекту. Вам нужно будет изменить app id в соответствии с проектом, который вы будете создавать в консоли Firebase. Если вы этого еще не понимаете, ничего страшного - я буду обсуждать это подробнее после того, как начальный проект будет настроен.

Основы

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

API означает интерфейс прикладного программирования и относится к методу, который компьютерные системы используют для связи друг с другом. Если вы запустите это в Google, Google определяет API как:

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

По сути, вы создаете API, чтобы ваша система могла взаимодействовать с тем, что вы создаете. API-интерфейсы могут включать базовые конечные точки REST для веб-сайта или даже методы, определяющие созданную вами программную библиотеку. Это приводит к следующему важному вопросу: Службы RESTful.

Службы RESTful относятся к передаче репрезентативного состояния и используют протокол HTTP для передачи данных (через API). Протокол HTTP - это то, что мы используем каждый день на веб-сайтах и ​​в интернет-приложениях. Службы RESTful используют разные HTTP-команды (или методы) для передачи данных между разными системами. Типичные HTTP-глаголы, которые вы будете использовать, включают следующее:

  • GET = получение данных
  • POST = создание или обновление данных
  • PUT = обновление данных
  • DELETE = удаление данных

Я также упоминал конечные точки ранее, это как раз то, что я буду иметь в виду, когда буду упоминать веб-сайт или услугу, на которую мне нужно попасть. Конечная точка - это просто причудливый способ описать адрес, по которому моя система будет обращаться с HTTP-запросом. Для получения дополнительной информации о HTTP-запросах, пожалуйста, обратитесь к странице википедии.

Firebase

Я использую платформу Google Firebase для того, что собираюсь создать в этой публикации. Firebase - очень мощная платформа, которую разработчики могут использовать для быстрого создания приложений. Firebase предоставляет общие услуги, в том числе:

Чтобы использовать Firebase, вам просто понадобится учетная запись Google. Вот почему я попросил вас настроить учетную запись Google во вводном разделе.

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

Начальная настройка

Для начала перейдите в Консоль Firebase, нажав на ссылку здесь. Вы должны увидеть что-то вроде следующего:

Нажмите кнопку «Добавить проект» и дайте вашему проекту имя. Я рекомендую принять шаги аналитики, поскольку они помогают вам и Google. Вы можете обратиться к аналитической информации позже в консоли (после создания вашего проекта).

После создания проекта откройте его в консоли и щелкните «база данных» в левой навигационной панели, чтобы увидеть следующее:

Нажмите Создать базу данных в разделе Cloud Firestore, чтобы создать исходную базу данных. Выберите тестовый режим, чтобы разрешить все операции чтения и записи. Вы можете создать правила, чтобы указать безопасность в своей базе данных, чтобы заблокировать ее в дальнейшем. Пожалуйста, обратитесь к документации firebase здесь, чтобы узнать больше о блокировке экземпляров вашей базы данных. Вам также будет предложено указать местоположение; все, что он делает по умолчанию, должно быть хорошо, но вы также можете попробовать выбрать центр обработки данных ближе к вам. Оформить заказ на этой странице для получения дополнительной информации о местонахождении центров обработки данных.

Теперь, когда у нас есть основные настройки проекта в консоли, давайте переключимся на ваш компьютер, чтобы настроить код.

Написание кода

На этом этапе мы предполагаем, что у вас уже есть интерфейс командной строки Firebase на вашем компьютере. Я рекомендую следовать инструкциям здесь, чтобы получить эту настройку, если вы еще этого не сделали.

Затем перейдите в свой терминал и создайте папку для вашего проекта с mkdir my-project

Затем cd в эту папку и запустите firebase init, и вы должны увидеть что-то вроде следующего:

Выберите «Функции» в меню параметров. Затем выберите приложение Firebase, которое вы создали ранее, в списке, отображаемом в следующем выводе терминала.

Следующий набор параметров довольно прост.

  • Выберите JavaScript.
  • Выберите да для линтинга.
  • выберите да, чтобы установить зависимости
  • и тебе хорошо!

Затем cd в созданную папку functions. Когда вы запускаете команду init, она создает папку функций, с которой вы можете работать. В папке functions должны быть следующие файлы:

  • index.js
  • папка node_modules
  • пакет-lock.json
  • package.json

Откройте для себя выбранный вами редактор терминала (настоятельно рекомендуется VSCode) и сначала посмотрите index.js.

Бессерверные API и ваша первая конечная точка

Firebase Functions позволяет использовать библиотеку ExpressJS для размещения бессерверного API. Бессерверная - это просто термин для системы, которая работает без физических серверов. Это немного неправильное название, потому что технически он работает на сервере, однако вы позволяете провайдеру обрабатывать аспект хостинга. Традиционные API-интерфейсы потребуют от вас установки сервера в облаке или локально, на котором можно разместить ваше приложение. Это означает, что разработчики должны нести ответственность за исправления ОС, оповещения и т. Д. В мире бессерверного режима вам не нужно беспокоиться ни о чем, кроме своего кода. Это одна из самых крутых частей Firebase!

Итак, чтобы использовать ExpressJS в своем проекте, сотрите файл index.js и вставьте туда следующие строки:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors({ origin: true }));

app.get('/hello-world', (req, res) => {
  return res.status(200).send('Hello World!');
});

exports.app = functions.https.onRequest(app);

Первые строки, в которых используется require, извлекают зависимости. У нас еще нет express или cors, поэтому давайте установим их в терминал с помощью следующих двух команд:

npm i express
npm i cors

Начальные строки со значением require импортируют библиотеки, которые мы собираемся использовать. Вот библиотеки более подробно:

  • firebase-functions - это модуль npm, который позволяет создавать функции
  • firebase-admin - это административный SDK firebase, который позволяет вашим функциям контролировать все ваши серверные службы Firebase.
  • express - это библиотека ExpressJS, позволяющая создать экземпляр сервера.
  • cors - это модуль npm, который позволяет вашим функциям работать где-то отдельно от вашего клиента. app.use просто включает CORS для вашего экземпляра экспресс-сервера.

Раздел кода с app.get создает конечную точку hello world. Здесь мы используем экспресс-маршрутизацию. Есть много способов сделать это. Я явно определяю маршруты просто для простоты. В корпоративной среде вы, вероятно, будете использовать экспресс-маршрутизатор, и код, вероятно, будет выглядеть немного менее подробным. Для более подробного погружения в экспресс-маршрутизацию я рекомендую ознакомиться с руководством здесь.

Для наших целей app.get просто выполняет вызов HTTP GET и фиксирует запрос в req и ответ в res. Когда конечная точка вызывается, она вернет "Hello World!" строка с кодом состояния HTTP 200. Коды состояния в HTTP используются для определения ответов. Их много, но для целей данного руководства 200 означает успех, а 500 вернет ошибку.

Раздел кода с exports.app = functions.https.onRequest(app); предоставляет доступ к вашему экспресс-приложению. Если у вас нет раздела exports, ваше приложение не запустится правильно.

Установив пакеты и начальную настройку кода, мы можем продолжить и запустить наш проект с npm run serve. Это обеспечит локальный сервер ваших функций и должен привести к следующему выводу:

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

Также обратите внимание, что терминал выводит локальный адрес вашего API, который работает локально. Вы собираетесь вызвать это напрямую из Postman, так как это «адрес» вашего API. При запуске на локальном хосте URL-адреса вашего приложения будут выглядеть следующим образом:

[<------domain---->]/[<-app id--->]/[<-zone-->]/app/[<-endpoint->]
http://localhost:5000/fir-api-9a206/us-central1/app/create

Когда мы перейдем к развертыванию, единственная разница в URL-адресе будет заключаться в том, что http://localhost:500 будет заменен на зону + идентификатор приложения + 'cloudfunctions.net', как показано ниже:

[<--zone + app id + cloudfunctions.net--->] / app / [<--endpoint-->]
https://us-central1-fir-api-9a206.cloudfunctions.net/app/hello-world

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

После этого будет указан идентификатор проекта (и некоторые другие настройки). На этом скриншоте я обведен кружком:

Откройте коллекцию почтальонов и отредактируйте запрос «hello-world localhost» в папке «localhost».

Если у вас по-прежнему возникают проблемы с Postman, ознакомьтесь с инструкциями здесь.

Как я уже упоминал, измените значение id в соответствии с вашим проектом. Адрес, который был указан в терминале при запуске npm run serve, также должен содержать эту информацию. Когда вы закончите, запустите запрос от почтальона, и вы должны увидеть следующее:

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

Вызовы базы данных

Для API, который мы создаем, это просто операции со списком элементов. Мы просто собираемся настроить функции создания, чтения, обновления и удаления (или CRUD) для этого списка элементов.

В Firebase у вас есть два варианта использования базы данных. Вы можете использовать традиционную базу данных или облачное хранилище данных. В этом руководстве мы воспользуемся облачным хранилищем огня, потому что с ним проще работать и он более универсален. Cloud firestore - это база данных NoSQL, что означает, что ваши данные хранятся как документы в коллекциях. Это очень похоже на то, как данные хранятся в строках в таблицах в базе данных SQL. Базы данных NoSQL обычно работают лучше и их легче масштабировать из-за характера доступа к данным и их хранения.

В разделе настройки мы добавили в наш проект экземпляр облачного хранилища данных. Теперь мы собираемся получить к нему доступ. Чтобы взаимодействовать с облачным хранилищем хранилищ с помощью admin SDK локально, вам потребуется получить к нему доступ через учетную запись службы. У служебных учетных записей есть ключи, которые они используют, вы запускаете эти разрешения, загружая файл ключа. Для этого сделайте следующее:

Перейдите в консоль Firebase и откройте свое приложение. Затем щелкните маленькую шестеренку и «Пользователи и разрешения», как вы видите здесь:

Затем щелкните вкладку «Учетные записи служб», и вы должны увидеть что-то вроде следующего:

Если вы заметили, внизу экрана они предоставляют вам код для запуска в вашем проекте. Единственное, что вам понадобится, это файл разрешений, на который нужно ссылаться. Идите вперед и нажмите «Создать новый закрытый ключ», чтобы установить его в свой проект. Затем сохраните его рядом с файлом index.js в папке functions, с которой мы только что работали. Вы можете называть его как хотите, я назвал свой permissions.json, а затем добавил следующее в начало вашего index.js файла:

var serviceAccount = require("./permissions.json");
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://fir-api-9a206..firebaseio.com"
});
const db = admin.firestore();

Эти строки (1) загружают ваш файл разрешений, а затем (2) используют его для инициализации вашего приложения. Я также создал переменную db для представления нашего экземпляра firestore. В этом нет необходимости, но в дальнейшем код становится чище.

После загрузки этих значений давайте добавим create конечную точку в наше приложение. Под конечной точкой hello-world добавьте следующее:

// create
app.post('/api/create', (req, res) => {
    (async () => {
        try {
          await db.collection('items').doc('/' + req.body.id + '/')
              .create({item: req.body.item});
          return res.status(200).send();
        } catch (error) {
          console.log(error);
          return res.status(500).send(error);
        }
      })();
  });

Этот код создает конечную точку «/ api / create-item», к которой вы выполняете вызов POST. Когда выполняется вызов POST, он добавляет «элемент» из тела в коллекцию в базе данных, называемую «элементы», с идентификатором переданного вами значения, называемого здесь «id». Коллекции в базе данных NoSQL - это просто сборщик документов. Вы могли бы так же легко сделать это с конкретным документом. Мне нравятся коллекции при использовании firestore, потому что они просты для понимания. Вы также можете думать о коллекциях как о таблицах в базе данных SQL.

Если вы также заметили, я добавил к конечной точке префикс «/ api». Это не обязательно, но обычно используется с любым API, который вы создаете. Значение «id» я также указываю здесь с моими запросами. Firebase сделает это за вас, но я подумал, что будет легче понять, если мы явно определим это в запросах.

Итак, добавив этот код, давайте остановим сервер в терминале (если вы еще этого не сделали) и перезапустим его с новым npm run serve.

В коллекции почтальона подтяните запрос POST «создать локальный хост». Измените значение app id, как вы делали раньше, и попробуйте запрос.

При запуске вы должны увидеть следующую ошибку:

Для административного SDK Firebase требуется версия узла 8.13.0 или 10.10. Поэтому я попросил установить nvm в первый раздел. Это очень легко исправить. nvm позволяет быстро переключать версии узла в локальном терминале. В вашем терминале запустите nvm use 10.10, и вы должны увидеть следующее:

Теперь продолжайте и снова запустите свой сервер с npm run serve и нажмите конечную точку на почтальоне. Вы должны увидеть 200 успех. В терминале вы также можете увидеть, что API был поражен локально.

Если вы столкнулись с ошибкой, связанной с onRequestWithOpts или чем-то подобным, выполните npm i firebase-tools. Недавно в интерфейсе командной строки возникла ошибка, исправленная в версии 7.1.0. Когда я писал этот пост, я обнаружил, что мою версию Firebase CLI необходимо обновить, чтобы исправить это. Оформить заказ подробнее в этом выпуске.

Еще одна интересная функция - вы можете напрямую просматривать свои данные в облачном хранилище. Если вы перейдете на консоль firebase, щелкните ссылку «база данных» в левой навигационной панели, и вы должны увидеть что-то вроде следующего изображения:

Создание конечных точек БД

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

  • /read-item/:item_id = прочитать конкретный элемент (по идентификатору)
  • /read-items = прочитать все элементы (общая коллекция)
  • /update-item/:item_id = обновить элемент
  • delete-item/:item_id = удалить элемент

По большей части все конечные точки будут похожи. Исключение составляет случай, когда я передаю параметры запроса со значением item_id. Все это следует базовой маршрутизации, которую вы можете увидеть в документации ExpressJS. Кроме того, для реального взаимодействия с Firebase Admin SDK я рекомендую проверить Справочник по Firestore API здесь.

Чтобы посмотреть, как эти конечные точки должны выглядеть (после завершения), проверьте файл index.js в репозитории GitHub здесь.

Вот код для остальных конечных точек:

// read item
app.get('/api/read/:item_id', (req, res) => {
    (async () => {
        try {
            const document = db.collection('items').doc(req.params.item_id);
            let item = await document.get();
            let response = item.data();
            return res.status(200).send(response);
        } catch (error) {
            console.log(error);
            return res.status(500).send(error);
        }
        })();
    });

// read all
app.get('/api/read', (req, res) => {
    (async () => {
        try {
            let query = db.collection('items');
            let response = [];
            await query.get().then(querySnapshot => {
            let docs = querySnapshot.docs;
            for (let doc of docs) {
                const selectedItem = {
                    id: doc.id,
                    item: doc.data().item
                };
                response.push(selectedItem);
            }
            });
            return res.status(200).send(response);
        } catch (error) {
            console.log(error);
            return res.status(500).send(error);
        }
        })();
    });

// update
app.put('/api/update/:item_id', (req, res) => {
(async () => {
    try {
        const document = db.collection('items').doc(req.params.item_id);
        await document.update({
            item: req.body.item
        });
        return res.status(200).send();
    } catch (error) {
        console.log(error);
        return res.status(500).send(error);
    }
    })();
});

// delete
app.delete('/api/delete/:item_id', (req, res) => {
(async () => {
    try {
        const document = db.collection('items').doc(req.params.item_id);
        await document.delete();
        return res.status(200).send();
    } catch (error) {
        console.log(error);
        return res.status(500).send(error);
    }
    })();
});

Развертывание

Итак, теперь у нас есть полностью функциональный CRUD API. Мы готовы к развертыванию! Если вы разрабатываете корпоративное приложение (или приложение, которое вы будете поддерживать), как правило, создается конвейер непрерывной интеграции с непрерывным развертыванием (CICD). По сути, это набор автоматизированных шагов для доставки вашего приложения в производство.

Существует много документации о передовых методах работы CICD. Я рекомендую проверить мой пост в блоге Angular-In-Depth о развертывании приложения с Firebase и CircleCI.

В нашем API нас интересует только фактический этап развертывания. Интерфейс командной строки Firebase позаботится об этом за вас с помощью всего firebase deploy.

Когда вы запускали команду firebase init для первоначальной сборки проекта, интерфейс командной строки Firebase уже установил шаг развертывания как сценарий NPM. Теперь мы можем развернуть созданный проект с npm run deploy из папки functions.

Скрипты npm очень мощные. Большинство современных приложений JavaScript так или иначе их используют. Я рекомендую ознакомиться с документацией по npm.

Когда вы запустите npm run deploy из папки functions, вы должны увидеть что-то вроде следующего вывода:

Строка вывода терминала Function URL обеспечивает конечную точку ваших развернутых функций. Вернитесь в коллекцию почтальонов и проверьте папку deployed для набора запросов, которые будут попадать в ваш развернутый API.

Подключение внешнего интерфейса

Итак, теперь, когда мы создали API, я хотел продемонстрировать, как бы он выглядел, если бы вы использовали его в клиентском приложении.

При обсуждении API обычно используются производитель и потребитель. Производитель - это сам API (или, по крайней мере, то, что предоставляет конечные точки). Потребитель - это все, что использует эти конечные точки. Обычно разработчики приложений создают клиентское приложение, используя такие JavaScript-фреймворки, как Angular, react, emberJS, vue и другие.

Клиентские приложения запускаются в браузере и позволяют интерпретировать код JavaScript на лету. Это особенно полезно, потому что во многих случаях разработчикам просто нужно где-то статически разместить свой «пакет» JavaScript. При этом используются преимущества языка JavaScript, а также многие достижения, которые произошли с браузерами сегодня.

Если вы помните из первых разделов, мы используем код, который я разместил в репозитории GitHub здесь. В этом проекте GitHub есть как наш бэкэнд-код API, так и фронтенд-приложение Angular, которое я создал для взаимодействия с API. Базовое приложение на самом деле состоит только из одной главной страницы и считается одностраничным приложением (SPA). Приложение просто выполняет базовые операции CRUD с элементами списка.

Пока вы запускаете приложение, вы также можете увидеть его в действии в консоли браузера. Если вы откроете консоль (щелкните правой кнопкой мыши «проверить», если вы используете Chrome), вы должны увидеть следующее:

Чтобы использовать созданный мной клиент, сначала cd в папку frontend моего проекта GitHub. Чтобы приложение работало на конечных точках развернутого API, вам просто нужно открыть файл /frontend/src/environments/environment.ts.

В этом файле вы увидите набор конечных точек. Чтобы использовать созданный мной клиент, сначала cd в папку frontend моего проекта GitHub. Чтобы приложение работало на конечных точках развернутого API, вам просто нужно изменить эти значения, чтобы они соответствовали URL-адресам из вашего проекта соответственно.

Если вы помните, как только вы развернули свой API, интерфейс командной строки Firebase выводит домен на терминал. Номенклатура размещенных конечных точек интуитивно понятна и выглядит следующим образом:

[<--zone + app id + cloudfunctions.net-->] / app / [<--endpoint-->]
https://us-central1-fir-api-9a206.cloudfunctions.net/app/hello-world

Замените значения для конечных точек в этом environments файле на значения из вашего проекта. Не забывайте всегда заканчивать каждую конечную точку соответствующим путем к конечной точке, например /api/create или /api/read соответственно.

После замены значений cd в каталог frontend и запустите стандартный npm install для установки зависимостей. После завершения установки зависимостей используйте команду Angular CLI, чтобы запустить приложение с ng serve.

Если вы столкнулись с ошибками в CLI, ознакомьтесь с документацией Angular CLI здесь.

После запуска ng serve вы должны увидеть в терминале что-то вроде следующего:

Это сообщение просто означает, что интерфейс командной строки создал приложение (с webpack) и в настоящее время оно работает на порту 4200. Если вы откроете браузер и перейдете к localhost:4200, вы должны увидеть, что приложение запущено.

Если вы посмотрите на компонент приложения проекта, то увидите, что действия просто выполняют fetch вызовы JavaScript к различным конечным точкам из созданного нами API:

async selectAll() {
    try {
      console.log(environment.readAll);
      console.log('calling read all endpoint');

      this.exampleItems = [];
      const output = await fetch(environment.readAll);
      const outputJSON = await output.json();
      this.exampleItems = outputJSON;
      console.log('Success');
      console.log(outputJSON);
    } catch (error) {
      console.log(error);
    }
  }

  // really this is create but the flow is that
  // click the "create item" button which appends a blank value to the array, then click save to actually create it permanently
  async saveItem(item: any) {
    try {
      console.log(environment.create);
      console.log('calling create item endpoint with: ' + item.item);

      const requestBody = {
        id: item.id,
        item: item.item
      };

      const createResponse =
        await fetch(environment.create, {
          method: 'POST',
          body: JSON.stringify(requestBody),
          headers:{
            'Content-Type': 'application/json'
          }
        });
      console.log('Success');
      console.log(createResponse.status);

      // call select all to update the table
      this.selectAll();
    } catch (error) {
      console.log(error);
    }
  }

  async updateItem(item: any) {
    try {
      console.log(environment.update);
      console.log('calling update endpoint with id ' + item.id + ' and value "' + item.item);

      const requestBody = {
        item: item.item
      };

      const updateResponse =
        await fetch(environment.update + item.id, {
          method: 'PUT',
          body: JSON.stringify(requestBody),
          headers:{
            'Content-Type': 'application/json'
          }
        });
      console.log('Success');
      console.log(updateResponse.status);

      // call select all to update the table
      this.selectAll();
    } catch (error) {
      console.log(error);
    }
  }

  async deleteItem(item: any) {
    try {
      console.log(environment.delete);
      console.log('calling delete endpoint with id ' + item.id);

      const deleteResponse =
        await fetch(environment.delete + item.id, {
          method: 'DELETE',
          headers:{
            'Content-Type': 'application/json'
          }
        });

      console.log('Success');
      console.log(deleteResponse.status);

      // call select all to update the table
      this.selectAll();
    } catch (error) {
      console.log(error);
    }
  }

Поскольку основная мысль этой статьи была о создании API, я не буду вдаваться в подробности того, как работает это приложение Angular. Я настоятельно рекомендую вам ознакомиться с Документацией по Angular, а также просмотреть доступные руководства. Если вы немного погуглите, вы найдете много отличных постов для начала работы по основам Angular. Я также очень рекомендую блог Angular-In-Depth для более продвинутого обучения.

Заключительные мысли

Поздравляю! Вы только что развернули API с Firebase. Есть много дополнительных вещей, которые вы делаете с этим API, но он показывает вам основы. Клиентское приложение, которое я продемонстрировал, поможет вам начать работу со способами использования вашего API. Я настоятельно рекомендую ознакомиться с руководствами по сайту ExpressJS, чтобы получить более подробные сведения о способах маршрутизации вызовов и использования промежуточного программного обеспечения. Я также настоятельно рекомендую проверить мои дополнительные сообщения в блоге о Firebase:

Надеюсь, мой пост помог вам начать создавать API с помощью Firebase. Не стесняйтесь оставлять комментарии и благодарим за чтение!

Первоначально опубликовано на https://rhythmandbinary.com 24 июля 2019 г.