Итак, в прошлый раз мы говорили о развертывании хостинга в Firebase с помощью cli firebase-tools. Чтобы иметь действительно потрясающее приложение, нам нужен какой-то бэкенд, который будет состоять из места для размещения некоторых данных, некоторых пользовательских функций для выполнения некоторых полезных действий с нашими данными и, возможно, системы для аутентификации пользователей.

Вы можете выполнять все эти задачи в рамках семейства Firebase с помощью Cloud Functions, Cloud Firestore и аутентификации Firebase!

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

С самого начала у нас есть 3 основные части почти всех приложений, готовых к работе прямо сейчас, с простыми в использовании клиентскими библиотеками. Как это помогает? Во-первых, наличие этих сервисов значительно сокращает объем кода, который нам приходится писать. По сути, мы можем больше сосредоточиться на функциях нашего приложения, а не пытаться выяснить систему аутентификации пользователя или базу данных, которую вы собираетесь использовать, и т. д.

С чего начать? Первое, что нам нужно сделать, это перейти на вкладку «Аутентификация» на панели инструментов Firebase. Затем мы перейдем на вкладку «Метод входа» и включим аутентификацию по электронной почте/паролю. Если вы хотите, вы можете включить столько функций входа, сколько хотите, если вы хотите, чтобы люди могли использовать o-auth, все, что вам нужно сделать, это предоставить Firebase ключ API для службы, которую вы включаете. (кроме Google o-auth, они позаботятся об этом за вас). Следующее, что мы собираемся сделать, это перейти на вкладку «База данных», выбрать Cloud Firestore и включить Cloud Firestore для нашего проекта. На данный момент весь процесс создания проекта Firebase и включения всех функций, которые мы хотим использовать, занял всего несколько минут, и теперь у нас есть полная система, готовая к работе, чтобы мы могли сразу начать кодирование.

Для тех, кто не знаком с Firestore, это хранилище данных (во многом похожее на MongoDB), но оно использует WebSockets для динамического обновления данных на любом клиенте, который у вас есть (например, javascript, приложение для Android, приложение для iOS и т. д.). Используя Firestore, вы также избавляетесь от необходимости кэшировать данные локально, потому что Firestore позаботится об этом за вас. Если клиент каким-то образом потеряет подключение к Интернету, Firestore будет поддерживать локальный кеш данных, чтобы пользователь мог добавлять и обновлять данные. Как только пользователь повторно подключится к Интернету, Firestore синхронизирует все данные. Все это происходит автоматически под капотом, поэтому вам не нужно об этом беспокоиться.

Давайте посмотрим, как легко начать создавать некоторые функции. Первое, о чем я хочу поговорить, это насколько хорошо Firebase Auth и Firestore взаимодействуют с нашими облачными функциями. Давайте посмотрим на пример кода (пример написан на Typescript):

// index.ts
import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';
admin.initializeApp();
/**
 * This will be triggered when a user signs up and a record is inserted in the Firebase Auth system
 */
export const OnUserCreated = functions.auth.user().onCreate((user, context) => {  
    const link = admin.auth().generateEmailVerificationLink(user.email);
/*
You can use something like Sengrid or Mailgun to send email verification link, OR the firebase client library for javascript has a method that will send emails automatically. This method will give your more flexibility over how you want the email to look
If we want to bill users we can create the user here as well
*/
const stripeUser = //create stripe user
    return admin.firestore().collection('Users').doc(user.uid).create({Email: user.email, EmailVerified: user.emailVerified, StripeId: stripeUser.id });
});
/**
 * This will be triggered when a user is deleted from the Firebase Auth system
 */
export const OnUserDeleted = functions.auth.user().onDelete((user, context) => {
    return admin.firestore().collection('Users').doc(user.uid).delete()
});
export const OnUserUpdated = functions.firestore.document('Users/{UserId}').onUpdate((change, context) => {
/*
Whenever an update operation occurs you will get both the before and after so you can compare them, and react to specific fields that changed.
*/
const before = change.before.data()
const after = change.after.data()
/*
Now you can update pertinent information in stripe or wherever else you may have user data you want to update automatically
*/ 
});

Выше приведен лишь небольшой фрагмент, который можно сразу развернуть в Cloud Functions с помощью firebase deploy --only functions. Флаг --only является необязательным, но если у вас есть другие функции Firebase в том же проекте, полезно развертывать только те активы, которые вам нужны.

Как только это будет развернуто, ваше приложение будет полностью подключено, и как только вы начнете добавлять пользователей, эти функции будут работать. Чтобы еще раз повторить, насколько это быстро, весь этот процесс действительно займет всего около 10 минут (плюс-минус несколько минут в зависимости от того, сколько логики вам нужно), чтобы перейти от 0 к приложению.

Некоторые из вас могут подумать: «Ну, это здорово, но что, если я хочу получить API из своих облачных функций?». Это отличный вопрос, и на него есть довольно простой ответ. Функции Firebase полностью поддерживают HTTP-запросы с помощью экспресс-фреймворка. Давайте посмотрим на пример:

// index.ts 
export const MyCustomHTTPFunction = functions.https.onRequest((req, res) => {
    //Do something here
})

Как видите, это не более чем простая экспресс-конечная точка, которая действительно полезна и невероятно проста в использовании. Чтобы попасть в эту конечную точку, вы получите примерно такой URL-адрес: https://us-central1-MYAPP.cloudfunctions.net/MyCustomHTTPFunction. Если вам нужно более индивидуальное экспресс-решение, вы можете сделать что-то вроде этого;

// index.ts
import * as express from 'express';
import * as cors from 'cors';
import * as bodyParser from 'body-parser';
import * as admin from 'firebase-admin';
const app = express();
const options: cors.CorsOptions = {
    origin: true
};
app.use(cors(options));
app.disable("x-powered-by");
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use('/api', async (req: express.Request, res: express.Response, next: express.NextFunction) => {
    let token = '';
    if(req.headers.authorization && req.headers.authorization.toString().startsWith("Bearer ")) {
        token = req.headers.authorization.toString().split(' ')[1]
    } else {
        return res.status(401).send('You are not authorized!')
    }
    const decodedToken = await admin.auth().verifyIdToken(token)
    if(decodedToken) {
        req['uid'] = decodedToken.uid;
        next();
        return;    
    } else {
        return res.status(401).send('You are not authorized!')
    }
});
//Add all the routes you want to app
app.use('/api/mycustomroute', MyCustomRouter)
export const ExpressEndpoint = functions.https.onRequest(app);

Итак, здесь много чего происходит, и я добавил немного удивительности Firebase. Вы заметите, что маршрут / проверяет наличие токена Bearer. Клиентские библиотеки Firebase могут генерировать специальный токен JWT для вошедших в систему пользователей. Используя ваш любимый фреймворк, вы можете добавить заголовок авторизации ко всем вашим запросам с токеном, чтобы вы встроили аутентификацию для своего API. Затем вы можете использовать библиотеку администратора firebase, чтобы проверить токен JWT, чтобы убедиться, что он действителен. Это еще один способ получить много абстрагированного кода, о котором вам не нужно беспокоиться, но это не снижает вашей гибкости.

Теперь ваш URL-адрес будет https://us-central1-MYAPP.cloudfunctions.net/ExpressEndpoint, и вы сможете добавить /api/mycustomroute к этой конечной точке и начать использовать свой экспресс-API. Практически без усилий с вашей стороны вы можете иметь собственный экспресс-API в облаке, защищенный пользовательским токеном JWT и сертификатом SSL. Это действительно не намного проще, чем это.

В этой статье мы увидели, насколько легко создавать высоконастраиваемый код и быстро и легко его развертывать. Мы также увидели, насколько простыми и полезными являются сервисы Firebase, когда они работают вместе. Надеюсь, это вдохновило вас взглянуть на Firebase и включить его в свое приложение или использовать для создания своего первого приложения. Я думаю о создании живого примера приложения, исходный код которого вы можете получить на GitHub, дайте мне знать, если вы хотите увидеть полное (но, вероятно, простое) веб-приложение, созданное с помощью Firebase. Увидимся, ребята, в следующий раз!

Если вам понравилась эта статья, я бы хотел, чтобы вы присоединились к моему списку рассылки, куда я отправляю дополнительные советы и рекомендации!

Если вы нашли эту статью полезной, интересной или развлекательной, купите мне кофе, чтобы помочь мне продолжать выпускать контент!