1. Прежде чем начать
В этом практическом занятии вы узнаете, как интегрировать Firebase с веб-приложением на Next.js под названием Friendly Eats, которое представляет собой сайт для отзывов о ресторанах.

Готовое веб-приложение предлагает полезные функции, демонстрирующие, как Firebase может помочь вам в создании приложений на Next.js. Эти функции включают в себя следующее:
- Автоматическая сборка и развертывание: В этом практическом занятии используется Firebase App Hosting для автоматической сборки и развертывания вашего кода Next.js каждый раз, когда вы отправляете изменения в настроенную ветку.
- Вход и выход: готовое веб-приложение позволяет входить и выходить из системы с помощью Google. Вход и сохранение данных пользователя полностью управляются через Firebase Authentication .
- Изображения: Готовое веб-приложение позволяет авторизованным пользователям загружать изображения ресторанов. Изображения хранятся в Cloud Storage for Firebase . SDK Firebase JavaScript предоставляет общедоступный URL-адрес для загруженных изображений. Этот общедоступный URL-адрес затем сохраняется в соответствующем документе ресторана в Cloud Firestore .
- Отзывы: Завершенное веб-приложение позволяет авторизованным пользователям оставлять отзывы о ресторанах, состоящие из звездного рейтинга и текстового сообщения. Информация об отзывах хранится в Cloud Firestore.
- Фильтры: Готовое веб-приложение позволяет авторизованным пользователям фильтровать список ресторанов по категории, местоположению и цене. Также можно настроить используемый метод сортировки. Доступ к данным осуществляется из Cloud Firestore, а запросы Firestore применяются на основе используемых фильтров.
Предварительные требования
- Аккаунт на GitHub
- Знание Next.js и JavaScript.
Что вы узнаете
- Как использовать Firebase с маршрутизатором приложения Next.js и рендерингом на стороне сервера.
- Как сохранить изображения в Cloud Storage для Firebase .
- Как читать и записывать данные в базу данных Cloud Firestore .
- Как использовать вход через Google с помощью Firebase JavaScript SDK.
Что вам понадобится
- Гит
- Последняя стабильная версия Node.js
- Любой браузер на ваш выбор, например, Google Chrome.
- Среда разработки с редактором кода и терминалом.
- Учетная запись Google для создания и управления вашим проектом Firebase.
- Возможность перевести ваш проект Firebase на тарифный план Blaze.
2. Настройте среду разработки и репозиторий GitHub.
Данный практический урок предоставляет базовый код приложения и основан на использовании Firebase CLI.
Создайте репозиторий GitHub.
Исходный код для этого практического занятия можно найти по адресу https://github.com/firebase/friendlyeats-web . В репозитории содержатся примеры проектов для различных платформ. Однако в этом практическом занятии используется только директория nextjs-start . Обратите внимание на следующие директории:
* `nextjs-start`: contains the starter code upon which you build.
* `nextjs-end`: contains the solution code for the finished web app.
Скопируйте папку nextjs-start в свой репозиторий:
- С помощью терминала создайте на компьютере новую папку и перейдите в неё:
mkdir codelab-friendlyeats-web cd codelab-friendlyeats-web - Используйте npm-пакет giget , чтобы загрузить только папку
nextjs-start:npx giget@latest "gh:firebase/friendlyeats-web/nextjs-start#master" . --install - Отслеживайте изменения локально с помощью Git:
git init git add . git commit -m "Codelab starting point" git branch -M main - Создайте новый репозиторий GitHub: https://github.com/new . Назовите его как угодно.
- В зависимости от способа аутентификации в GitHub (HTTPS или SSH), скопируйте новый URL-адрес, который создаст для вас GitHub:
-
https://github.com/<USER_NAME>/<REPOSITORY_NAME>.gitили -
git@github.com:<USER_NAME>/<REPOSITORY_NAME>.git
-
- Отправьте локальные изменения в свой новый репозиторий GitHub, выполнив следующую команду. Замените URL-адрес вашего репозитория на URL-адрес заполнителя
<REPOSITORY_URL>.git remote add origin <REPOSITORY_URL> git push -u origin main - Теперь вы должны увидеть стартовый код в своем репозитории GitHub.
Установите или обновите Firebase CLI.
Выполните следующую команду, чтобы убедиться, что у вас установлен Firebase CLI и что его версия не ниже 14.1.0:
firebase --version
Если вы видите более старую версию или у вас не установлен Firebase CLI, выполните команду установки:
npm install -g firebase-tools@latest
Если вам не удаётся установить Firebase CLI из-за ошибок доступа, обратитесь к документации npm или воспользуйтесь другим вариантом установки .
Войдите в Firebase
- Для входа в Firebase CLI выполните следующую команду:
firebase login
- В зависимости от того, хотите ли вы, чтобы Firebase собирал данные, введите
YилиN - В браузере выберите свой аккаунт Google, а затем нажмите «Разрешить» .
3. Настройте свой проект Firebase.
В этом разделе вы создадите проект Firebase и свяжете с ним веб-приложение Firebase. Вы также настроите сервисы Firebase, используемые в примере веб-приложения.
Создайте проект Firebase.
- Войдите в консоль Firebase, используя ту же учетную запись Google, которую вы использовали на предыдущем шаге.
- Нажмите кнопку, чтобы создать новый проект, а затем введите название проекта (например,
FriendlyEats Codelab). - Нажмите «Продолжить» .
- Если появится запрос, ознакомьтесь с условиями использования Firebase и примите их, после чего нажмите «Продолжить» .
- (Необязательно) Включите помощь ИИ в консоли Firebase (в Firebase она называется "Gemini").
- Для этого практического занятия вам не понадобится Google Analytics, поэтому отключите эту опцию.
- Нажмите «Создать проект» , дождитесь завершения подготовки проекта, а затем нажмите «Продолжить» .
Обновите свой тарифный план Firebase.
Для использования Firebase App Hosting и Cloud Storage for Firebase ваш проект Firebase должен быть привязан к тарифному плану с оплатой по мере использования (Blaze) , то есть он должен быть связан с учетной записью Cloud Billing .
- Для использования учетной записи Cloud Billing требуется способ оплаты, например, кредитная карта.
- Если вы новичок в Firebase и Google Cloud, проверьте, имеете ли вы право на получение кредита в размере 300 долларов США и бесплатной пробной версии учетной записи Cloud Billing .
- Если вы выполняете этот практический семинар в рамках мероприятия, уточните у организатора, есть ли возможность получить облачные кредиты.
Чтобы перейти на тарифный план Blaze для вашего проекта, выполните следующие шаги:
- В консоли Firebase выберите вариант обновления вашего тарифного плана .
- Выберите тарифный план Blaze. Следуйте инструкциям на экране, чтобы связать учетную запись Cloud Billing с вашим проектом.
Если в рамках этого обновления вам потребовалось создать учетную запись Cloud Billing, возможно, вам нужно будет вернуться к процессу обновления в консоли Firebase, чтобы завершить обновление.
Добавьте веб-приложение в свой проект Firebase.
- Перейдите в раздел «Обзор проекта» в вашем проекте Firebase, нажмите «Добавить приложение» , а затем — «Веб» .
- В текстовом поле «Псевдоним приложения» введите запоминающийся псевдоним приложения, например,
My Next.js app. - Оставьте флажок «Также настройте Firebase Hosting для этого приложения» снятым.
- Нажмите «Зарегистрировать приложение» > «Продолжить в консоли» .
Настройте службы Firebase в консоли Firebase.
Настройка аутентификации
- В левой панели консоли Firebase разверните раздел «Сборка» , а затем выберите «Аутентификация» .
- Нажмите « Начать» .
- В столбце «Поставщики авторизации» нажмите Google > Включить .
- В текстовом поле «Публичное имя проекта» введите запоминающееся имя, например,
My Next.js app. - В раскрывающемся списке «Адрес электронной почты службы поддержки для проекта» выберите свой адрес электронной почты.
- Нажмите « Сохранить ».
Настройка Cloud Firestore
- В левой панели консоли Firebase разверните раздел «Сборка» , а затем выберите «База данных Firestore» .
- Нажмите «Создать базу данных» .
- Выберите «Стандартная версия» и нажмите «Далее» .
- Не изменяйте идентификатор базы данных , оставьте его значение по
(default). - Выберите местоположение для вашей базы данных, затем нажмите «Далее» .
Для создания настоящего приложения вам следует выбрать местоположение, расположенное недалеко от ваших пользователей. - Нажмите «Пуск» в тестовом режиме . Ознакомьтесь с отказом от ответственности в отношении правил безопасности.
В дальнейшем в этом практическом занятии вы добавите правила безопасности для защиты ваших данных. Не распространяйте и не предоставляйте публичный доступ к приложению, не добавив правила безопасности для вашей базы данных. - Нажмите «Создать» .
Настройка облачного хранилища для Firebase
- В левой панели консоли Firebase разверните раздел «Сборка» , а затем выберите «Хранилище» .
- Нажмите « Начать» .
- Выберите местоположение для вашего хранилища по умолчанию.
Для регионовUS-WEST1,US-CENTRAL1иUS-EAST1доступен тариф "Всегда бесплатно" от Google Cloud Storage. Для регионов во всех остальных регионах действуют тарифные планы и правила использования Google Cloud Storage . - Нажмите «Пуск» в тестовом режиме . Ознакомьтесь с отказом от ответственности в отношении правил безопасности.
В дальнейшем в этом практическом занятии вы добавите правила безопасности для защиты ваших данных. Не распространяйте и не предоставляйте публичный доступ к приложению без добавления правил безопасности для вашего хранилища. - Нажмите «Создать» .
Внедрите правила безопасности.
В коде уже есть наборы правил безопасности для Firestore и для Cloud Storage for Firebase. После развертывания правил безопасности данные в вашей базе данных и вашем хранилище будут лучше защищены от неправомерного использования.
- В терминале настройте CLI для использования созданного ранее проекта Firebase:
Когда появится запрос на ввод псевдонима, введитеfirebase use --add
friendlyeats-codelab. - Для развертывания этих правил безопасности (а также индексов , которые понадобятся позже) выполните следующую команду в терминале:
firebase deploy --only firestore,storage
- Если вас спросят:
"Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?", нажмитеEnterи выберите «Да» .
4. Просмотрите исходный код.
В этом разделе вы рассмотрите несколько областей исходного кода приложения, в которые вы добавите функциональность в рамках этого практического занятия.
Структура папок и файлов
В таблице ниже представлен обзор структуры папок и файлов приложения:
Папки и файлы | Описание |
| Компоненты React для фильтров, заголовков, подробной информации о ресторане и отзывов. |
| Вспомогательные функции, которые не обязательно привязаны к React или Next.js. |
| Специфический код Firebase и конфигурация Firebase |
| Статические элементы в веб-приложении, такие как иконки. |
| Маршрутизация с помощью маршрутизатора приложений Next.js |
| Зависимости проекта с помощью npm |
| Конфигурация, специфичная для Next.js (действия сервера включены ). |
| конфигурация языковой службы JavaScript |
Серверные и клиентские компоненты
Приложение представляет собой веб-приложение Next.js, использующее App Router . В приложении используется серверный рендеринг. Например, файл src/app/page.js — это серверный компонент, отвечающий за главную страницу. Файл src/components/RestaurantListings.jsx — это клиентский компонент, обозначенный директивой "use client" в начале файла.
Импорт операторов
Вы можете заметить операторы импорта, подобные следующим:
import RatingPicker from "@/src/components/RatingPicker.jsx";
Приложение использует символ @ , чтобы избежать неудобных относительных путей импорта, что стало возможным благодаря псевдонимам путей .
API, специфичные для Firebase
Весь код API Firebase находится в директории src/lib/firebase . Затем отдельные компоненты React импортируют обернутые функции из директории src/lib/firebase , а не напрямую импортируют функции Firebase.
Имитационные данные
Имитация данных о ресторанах и отзывах содержится в файле src/lib/randomData.js . Данные из этого файла собираются в коде в файле src/lib/fakeRestaurants.js .
5. Создайте бэкэнд для размещения приложений.
В этом разделе вы настроите бэкэнд для размещения приложений , чтобы отслеживать ветку в вашем репозитории Git.
К концу этого раздела у вас будет бэкэнд для размещения приложений, подключенный к вашему репозиторию в GitHub, который будет автоматически пересобирать и выпускать новую версию вашего приложения всякий раз, когда вы отправляете новый коммит в main ветку.
Создайте бэкэнд.
- Перейдите на страницу «Размещение приложений» в консоли Firebase.
- Нажмите « Начать» , чтобы запустить процесс создания административной панели.
- Выберите регион. Для настоящего приложения вы бы выбрали регион, ближайший к вашим пользователям.
- Следуйте инструкциям на шаге «Импорт репозитория GitHub» , чтобы настроить аутентификацию GitHub.
- В разделе «Репозиторий» выберите «Предоставить доступ к новому репозиторию в GitHub» и следуйте инструкциям, чтобы включить доступ к созданному ранее репозиторию GitHub.
- Нажмите «Обновить список» , чтобы обновить список, затем выберите свой репозиторий и нажмите «Далее» .
- Настройте параметры развертывания:
- Установите рабочую ветку на
main. - Оставьте корневой каталог в качестве
/. - Включите автоматическое развертывание.
- Установите рабочую ветку на
- Назовите свой бэкэнд
friendlyeats-codelabи нажмите «Далее» . - В разделе «Связать веб-приложение Firebase» выберите «Выбрать существующее веб-приложение Firebase» и выберите добавленное вами приложение из списка.
- Нажмите «Готово» и «Развернуть» . Вы будете перенаправлены на новую страницу, где сможете увидеть статус вашей новой серверной части для размещения приложений!
- Нажмите «Просмотреть» , чтобы увидеть дополнительную информацию о развертывании вашего приложения, включая статус развертывания, журналы и сведения об использовании.
- После завершения развертывания нажмите, чтобы открыть URL-адрес вашего сайта в разделе «Домены» . Для начала работы может потребоваться несколько минут из-за распространения DNS-записей.
- Ой-ой! При загрузке страницы вы увидите сообщение об ошибке: «Ошибка приложения: произошла ошибка на стороне сервера (подробнее см. в журналах сервера)».
- В консоли Firebase проверьте вкладку « Журналы» в бэкэнде вашего приложения. Вы увидите запись «Ошибка: не реализовано». Мы исправим это на следующем шаге, когда добавим аутентификацию.
Вы успешно развернули исходное веб-приложение! Каждый раз, когда вы отправляете новый коммит в main ветку вашего репозитория GitHub, в консоли Firebase начинается новая сборка и развертывание, и ваш сайт автоматически обновляется после завершения развертывания.
6. Добавьте аутентификацию в веб-приложение.
В этом разделе вы добавляете аутентификацию в веб-приложение, чтобы иметь возможность входить в него.
Добавить авторизованный домен
Аутентификация Firebase принимает запросы на вход только с разрешенных вами доменов. Здесь мы добавим домен вашего бэкенда App Hosting в список разрешенных доменов в вашем проекте.
- Откройте страницу «Хостинг приложений» и нажмите «Просмотреть» под развернутым сайтом, чтобы перейти на страницу «Обзор» . Скопируйте доменное имя вашей серверной части хостинга приложений.
- Перейдите на вкладку «Настройки аутентификации» и выберите проект, к которому хотите добавить авторизованный домен. Затем найдите раздел «Авторизованные домены» и нажмите на него.
- Нажмите кнопку «Добавить домен» .
- Введите домен вашей административной панели хостинга приложений.
- Нажмите «Добавить» .
Реализуйте функции входа и выхода из системы.
В файле src/lib/firebase/auth.js замените функции onAuthStateChanged , onIdTokenChanged , signInWithGoogle и signOut следующим кодом:
export function onAuthStateChanged(cb) {
return _onAuthStateChanged(auth, cb);
}
export function onIdTokenChanged(cb) {
return _onIdTokenChanged(auth, cb);
}
export async function signInWithGoogle() {
const provider = new GoogleAuthProvider();
try {
await signInWithPopup(auth, provider);
} catch (error) {
console.error("Error signing in with Google", error);
}
}
export async function signOut() {
try {
return auth.signOut();
} catch (error) {
console.error("Error signing out with Google", error);
}
}
В этом коде используются следующие API Firebase:
API Firebase | Описание |
Добавляет наблюдателя для отслеживания изменений состояния авторизации пользователя. | |
Добавляет наблюдателя для отслеживания изменений токена идентификации пользователя. | |
Создает экземпляр поставщика аутентификации Google. | |
Запускает процесс аутентификации на основе диалога. | |
Выводит пользователя из системы. |
В файле src/components/Header.jsx код уже вызывает функции signInWithGoogle и signOut .
Передайте состояние аутентификации на сервер.
Для передачи состояния аутентификации на сервер мы будем использовать cookie-файлы. При каждом изменении состояния аутентификации на стороне клиента мы будем обновлять cookie-файл __session .
В src/components/Header.jsx замените функцию useUserSession следующим кодом:
function useUserSession(initialUser) {
useEffect(() => {
return onIdTokenChanged(async (user) => {
if (user) {
const idToken = await user.getIdToken();
await setCookie("__session", idToken);
} else {
await deleteCookie("__session");
}
if (initialUser?.uid === user?.uid) {
return;
}
window.location.reload();
});
}, [initialUser]);
return initialUser;
}
Прочитать состояние аутентификации на сервере
Мы будем использовать FirebaseServerApp для зеркалирования состояния аутентификации клиента на сервере.
Откройте src/lib/firebase/serverApp.js и замените функцию getAuthenticatedAppForUser :
export async function getAuthenticatedAppForUser() {
const authIdToken = (await cookies()).get("__session")?.value;
// Firebase Server App is a new feature in the JS SDK that allows you to
// instantiate the SDK with credentials retrieved from the client & has
// other affordances for use in server environments.
const firebaseServerApp = initializeServerApp(
// https://github.com/firebase/firebase-js-sdk/issues/8863#issuecomment-2751401913
initializeApp(),
{
authIdToken,
}
);
const auth = getAuth(firebaseServerApp);
await auth.authStateReady();
return { firebaseServerApp, currentUser: auth.currentUser };
}
Проверить изменения
Основной макет в файле src/app/layout.js отображает заголовок и передает пользователя, если он доступен, в качестве свойства.
<Header initialUser={currentUser?.toJSON()} />
Это означает, что компонент <Header> отображает данные пользователя, если они доступны, во время работы сервера. Если после первоначальной загрузки страницы в течение жизненного цикла страницы происходят какие-либо обновления аутентификации, их обрабатывает обработчик onAuthStateChanged .
Теперь пришло время развернуть новую сборку и проверить, что вы создали.
- Создайте коммит с сообщением "Добавить аутентификацию" и отправьте его в свой репозиторий GitHub.
git add . git commit -m "Add authentication" git push - Откройте страницу «Размещение приложений» и, когда развертывание будет завершено, щелкните URL-адрес сайта, чтобы открыть его.
- Проверка аутентификации:
- Войдите в систему, используя свою учетную запись Google, и убедитесь, что ваше отображаемое имя отображается в заголовке после входа.
- Выйдите из системы и войдите снова. Вы можете повторить этот шаг с разными пользователями.
- Необязательно: Щелкните правой кнопкой мыши веб-приложение, выберите «Просмотреть исходный код страницы» и найдите отображаемое имя. Оно отображается в исходном HTML-коде, возвращаемом сервером.
7. Просмотреть информацию о ресторане
Веб-приложение включает в себя тестовые данные для ресторанов и отзывов.
Добавить один или несколько ресторанов
Чтобы добавить фиктивные данные о ресторане в локальную базу данных Cloud Firestore, выполните следующие действия:
- Если вы еще этого не сделали, войдите в веб-приложение. Затем выберите
> Добавьте примеры ресторанов . Обратите внимание, что в веб-приложении Friendly Eats рестораны не отображаются, потому что мы еще не настроили код для получения данных. Мы исправим это на следующем шаге. - В консоли Firebase на странице базы данных Firestore выберите раздел «Рестораны» . Вы увидите документы верхнего уровня в коллекции «Рестораны», каждый из которых представляет собой отдельный ресторан.
- Щелкните по нескольким документам, чтобы изучить свойства документа, относящегося к ресторану.
Отобразить список ресторанов
В вашей базе данных Cloud Firestore теперь есть рестораны, которые может отображать веб-приложение Next.js.
Для определения кода получения данных выполните следующие шаги:
- В файле
src/app/page.jsнайдите компонент сервера<Home />и изучите вызов функцииgetRestaurants, которая получает список ресторанов во время выполнения на сервере. Реализуйте функциюgetRestaurantsна следующих шагах. - В файле
src/lib/firebase/firestore.jsзамените функцииapplyQueryFiltersиgetRestaurantsследующим кодом:
function applyQueryFilters(q, { category, city, price, sort }) {
if (category) {
q = query(q, where("category", "==", category));
}
if (city) {
q = query(q, where("city", "==", city));
}
if (price) {
q = query(q, where("price", "==", price.length));
}
if (sort === "Rating" || !sort) {
q = query(q, orderBy("avgRating", "desc"));
} else if (sort === "Review") {
q = query(q, orderBy("numRatings", "desc"));
}
return q;
}
export async function getRestaurants(db = db, filters = {}) {
let q = query(collection(db, "restaurants"));
q = applyQueryFilters(q, filters);
const results = await getDocs(q);
return results.docs.map((doc) => {
return {
id: doc.id,
...doc.data(),
// Only plain objects can be passed to Client Components from Server Components
timestamp: doc.data().timestamp.toDate(),
};
});
}
- Создайте коммит с сообщением "Прочитать список ресторанов из Firestore" и отправьте его в свой репозиторий GitHub.
git add . git commit -m "Read the list of restaurants from Firestore" git push - Откройте страницу «Размещение приложений» в консоли Firebase и дождитесь завершения развертывания.
- В веб-приложении обновите страницу. Изображения ресторанов отобразятся на странице в виде плиток.
Убедитесь, что список ресторанов загружается во время работы сервера.
При использовании фреймворка Next.js может быть неочевидно, когда данные загружаются во время выполнения на стороне сервера, а когда — на стороне клиента.
Чтобы убедиться, что списки ресторанов загружаются во время работы сервера, выполните следующие действия:
- В веб-приложении откройте инструменты разработчика и отключите JavaScript .

- Обновите веб-приложение. Список ресторанов по-прежнему загружается. Информация о ресторане возвращается в ответе сервера. Если JavaScript включен, информация о ресторане заполняется с помощью клиентского JavaScript-кода.
- В инструментах разработчика повторно включите JavaScript .
Отслеживайте обновления ресторанов с помощью слушателей снимков Cloud Firestore.
В предыдущем разделе вы видели, как загружается начальный набор ресторанов из файла src/app/page.js . Файл src/app/page.js является серверным компонентом и отображается на сервере, включая код получения данных из Firebase.
Файл src/components/RestaurantListings.jsx является клиентским компонентом и может быть настроен для обработки разметки, генерируемой на сервере.
Чтобы настроить файл src/components/RestaurantListings.jsx для обработки разметки, генерируемой сервером, выполните следующие действия:
- В файле
src/components/RestaurantListings.jsxобратите внимание на следующий код, который уже написан за вас:
useEffect(() => {
return getRestaurantsSnapshot((data) => {
setRestaurants(data);
}, filters);
}, [filters]);
Этот код вызывает функцию getRestaurantsSnapshot() , которая аналогична функции getRestaurants() , реализованной вами на предыдущем шаге. Однако эта функция создания снимка предоставляет механизм обратного вызова, благодаря которому функция обратного вызова вызывается каждый раз, когда в коллекцию ресторанов вносятся изменения.
- В файле
src/lib/firebase/firestore.jsзамените функциюgetRestaurantsSnapshot()следующим кодом:
export function getRestaurantsSnapshot(cb, filters = {}) {
if (typeof cb !== "function") {
console.log("Error: The callback parameter is not a function");
return;
}
let q = query(collection(db, "restaurants"));
q = applyQueryFilters(q, filters);
return onSnapshot(q, (querySnapshot) => {
const results = querySnapshot.docs.map((doc) => {
return {
id: doc.id,
...doc.data(),
// Only plain objects can be passed to Client Components from Server Components
timestamp: doc.data().timestamp.toDate(),
};
});
cb(results);
});
}
- В файле
src/lib/firebase/firestore.jsзамените функциюgetRestaurantSnapshotById()следующим кодом:
export function getRestaurantSnapshotById(restaurantId, cb) {
if (!restaurantId) {
console.log("Error: Invalid ID received: ", restaurantId);
return;
}
if (typeof cb !== "function") {
console.log("Error: The callback parameter is not a function");
return;
}
const docRef = doc(db, "restaurants", restaurantId);
return onSnapshot(docRef, (docSnap) => {
cb({
...docSnap.data(),
timestamp: docSnap.data().timestamp.toDate(),
});
});
}
Изменения, внесенные через страницу базы данных Firestore , теперь отображаются в веб-приложении в режиме реального времени.
- Создайте коммит с сообщением "Следите за обновлениями ресторана в режиме реального времени" и отправьте его в свой репозиторий GitHub.
git add . git commit -m "Listen for realtime restaurant updates" git push - Откройте страницу «Размещение приложений» в консоли Firebase и дождитесь завершения развертывания.
- В веб-приложении выберите
> Добавьте примеры ресторанов . Если функция создания снимков реализована правильно, рестораны отображаются в режиме реального времени без перезагрузки страницы.
8. Сохраняйте отзывы пользователей из веб-приложения.
- В файле
src/lib/firebase/firestore.jsзамените функциюupdateWithRating()следующим кодом:
const updateWithRating = async (
transaction,
docRef,
newRatingDocument,
review
) => {
const restaurant = await transaction.get(docRef);
const data = restaurant.data();
const newNumRatings = data?.numRatings ? data.numRatings + 1 : 1;
const newSumRating = (data?.sumRating || 0) + Number(review.rating);
const newAverage = newSumRating / newNumRatings;
transaction.update(docRef, {
numRatings: newNumRatings,
sumRating: newSumRating,
avgRating: newAverage,
});
transaction.set(newRatingDocument, {
...review,
timestamp: Timestamp.fromDate(new Date()),
});
};
Этот код вставляет новый документ Firestore, представляющий новый отзыв. Код также обновляет существующий документ Firestore, представляющий ресторан, добавляя обновленные данные о количестве оценок и среднем рассчитанном рейтинге.
- Замените функцию
addReviewToRestaurant()следующим кодом:
export async function addReviewToRestaurant(db, restaurantId, review) {
if (!restaurantId) {
throw new Error("No restaurant ID has been provided.");
}
if (!review) {
throw new Error("A valid review has not been provided.");
}
try {
const docRef = doc(collection(db, "restaurants"), restaurantId);
const newRatingDocument = doc(
collection(db, `restaurants/${restaurantId}/ratings`),
);
// corrected line
await runTransaction(db, (transaction) =>
updateWithRating(transaction, docRef, newRatingDocument, review),
);
} catch (error) {
console.error(
"There was an error adding the rating to the restaurant",
error,
);
throw error;
}
}
Реализуйте серверное действие Next.js.
Действие сервера Next.js предоставляет удобный API для доступа к данным формы, например, data.get("text") для получения текстового значения из данных, отправленных через форму.
Чтобы использовать действие Next.js Server Action для обработки отправки формы отзыва, выполните следующие шаги:
- В файле
src/components/ReviewDialog.jsxнайдите атрибутactionв элементе<form>.
<form
action={handleReviewFormSubmission}
onSubmit={() => {
handleClose();
}}
>
Значение атрибута action указывает на функцию, которую вы реализуете на следующем шаге.
- В файле
src/app/actions.jsзамените функциюhandleReviewFormSubmission()следующим кодом:
export async function handleReviewFormSubmission(data) {
const { firebaseServerApp } = await getAuthenticatedAppForUser();
const db = getFirestore(firebaseServerApp);
await addReviewToRestaurant(db, data.get("restaurantId"), {
text: data.get("text"),
rating: data.get("rating"),
// This came from a hidden form field.
userId: data.get("userId"),
});
}
Добавить отзывы о ресторане
Вы добавили поддержку отправки отзывов, поэтому теперь можете убедиться, что ваши отзывы корректно вставляются в Cloud Firestore.
Чтобы добавить отзыв и убедиться, что он добавлен в Cloud Firestore, выполните следующие действия:
- Создайте коммит с сообщением "Разрешить пользователям оставлять отзывы о ресторанах" и отправьте его в свой репозиторий GitHub.
git add . git commit -m "Allow users to submit restaurant reviews" git push - Откройте страницу «Размещение приложений» в консоли Firebase и дождитесь завершения развертывания.
- Обновите веб-приложение и выберите ресторан на главной странице.
- На странице ресторана нажмите
. - Выберите оценку в виде звезд.
- Напишите отзыв.
- Нажмите «Отправить» . Ваш отзыв появится вверху списка отзывов.
- В Cloud Firestore найдите в панели «Добавить документ» документ ресторана, который вы оценили, и выберите его.
- В панели «Начало коллекции» выберите «Рейтинги» .
- В панели «Добавить документ» найдите документ для проверки, чтобы убедиться, что он был вставлен должным образом.
9. Сохраняйте файлы, загруженные пользователем из веб-приложения.
В этом разделе вы добавляете функциональность, позволяющую заменять изображение, связанное с рестораном, при авторизации. Вы загружаете изображение в Firebase Storage и обновляете URL-адрес изображения в документе Cloud Firestore, представляющем ресторан.
Чтобы сохранить файлы, загруженные пользователем из веб-приложения, выполните следующие действия:
- В файле
src/components/Restaurant.jsxобратите внимание на код, который выполняется, когда пользователь загружает файл:
async function handleRestaurantImage(target) {
const image = target.files ? target.files[0] : null;
if (!image) {
return;
}
const imageURL = await updateRestaurantImage(id, image);
setRestaurantDetails({ ...restaurantDetails, photo: imageURL });
}
Вносить изменения в эту функцию не требуется, но на следующих шагах вам нужно будет реализовать поведение функции updateRestaurantImage() .
- В файле
src/lib/firebase/storage.jsзамените функцииupdateRestaurantImage()иuploadImage()следующим кодом:
export async function updateRestaurantImage(restaurantId, image) {
try {
if (!restaurantId) {
throw new Error("No restaurant ID has been provided.");
}
if (!image || !image.name) {
throw new Error("A valid image has not been provided.");
}
const publicImageUrl = await uploadImage(restaurantId, image);
await updateRestaurantImageReference(restaurantId, publicImageUrl);
return publicImageUrl;
} catch (error) {
console.error("Error processing request:", error);
}
}
async function uploadImage(restaurantId, image) {
const filePath = `images/${restaurantId}/${image.name}`;
const newImageRef = ref(storage, filePath);
await uploadBytesResumable(newImageRef, image);
return await getDownloadURL(newImageRef);
}
Функция updateRestaurantImageReference() уже реализована. Эта функция обновляет существующий документ ресторана в Cloud Firestore, добавляя обновленный URL изображения.
Проверьте работоспособность функции загрузки изображений.
Чтобы убедиться, что изображение загружается должным образом, выполните следующие действия:
- Создайте коммит с сообщением "Разрешить пользователям изменять фотографии каждого ресторана" и отправьте его в свой репозиторий GitHub.
git add . git commit -m "Allow users to change each restaurants' photo" git push - Откройте страницу «Размещение приложений» в консоли Firebase и дождитесь завершения развертывания.
- В веб-приложении убедитесь, что вы вошли в систему, и выберите ресторан.
- Нажмите
и загрузите изображение из вашей файловой системы. Ваше изображение покинет локальную среду и будет загружено в облачное хранилище. Изображение появится сразу после загрузки. - Перейдите в раздел «Облачное хранилище для Firebase».
- Перейдите в папку, соответствующую ресторану. Загруженное вами изображение находится в этой папке.

10. Обобщите отзывы о ресторанах с помощью генеративного искусственного интеллекта.
В этом разделе вы добавите функцию сводки отзывов, чтобы пользователь мог быстро понять, что все думают о ресторане, не читая каждый отзыв.
Сохраните ключ API Gemini в Cloud Secret Manager.
- Для использования API Gemini вам потребуется ключ API. Зайдите в Google AI Studio и нажмите «Создать ключ API» .
- Назовите ключ как угодно. Если вашего проекта нет в списке « Выберите импортированный проект» , нажмите «Импорт проекта» , отметьте свой проект в списке, а затем нажмите «Импорт» . Наконец, выберите его в списке «Выберите импортированный проект» и нажмите «Создать ключ» .
- Интеграция App Hosting с Cloud Secret Manager позволяет безопасно хранить конфиденциальные данные, такие как ключи API:
- В терминале выполните команду для создания нового секрета:
firebase apphosting:secrets:set GEMINI_API_KEY- Когда система запросит секретное значение, скопируйте и вставьте свой API-ключ Gemini из Google AI Studio.
- Когда вас спросят, предназначен ли новый секрет для использования в производственной среде или для локального тестирования, выберите «Производственная среда».
- Когда вас спросят, хотите ли вы предоставить доступ к секретному ключу учетной записи службы вашего бэкэнда, выберите «Да».
- Когда появится запрос о добавлении нового секретного ключа в файл
apphosting.yaml, введитеYдля подтверждения.
Ваш API-ключ Gemini теперь надежно хранится в Cloud Secret Manager и доступен для бэкэнда вашего хостинга приложений.
Внедрить компонент сводки обзора.
- В
src/components/Reviews/ReviewSummary.jsxзамените функциюGeminiSummaryследующим кодом:export async function GeminiSummary({ restaurantId }) { const { firebaseServerApp } = await getAuthenticatedAppForUser(); const reviews = await getReviewsByRestaurantId( getFirestore(firebaseServerApp), restaurantId ); const reviewSeparator = "@"; const prompt = ` Based on the following restaurant reviews, where each review is separated by a '${reviewSeparator}' character, create a one-sentence summary of what people think of the restaurant. Here are the reviews: ${reviews.map((review) => review.text).join(reviewSeparator)} `; try { if (!process.env.GEMINI_API_KEY) { // Make sure GEMINI_API_KEY environment variable is set: // https://genkit.dev/docs/get-started/ throw new Error( 'GEMINI_API_KEY not set. Set it with "firebase apphosting:secrets:set GEMINI_API_KEY"' ); } // Configure a Genkit instance. const ai = genkit({ plugins: [googleAI()], model: gemini20Flash, // set default model }); const { text } = await ai.generate(prompt); return ( <div className="restaurant__review_summary"> <p>{text}</p> <p>✨ Summarized with Gemini</p> </div> ); } catch (e) { console.error(e); return <p>Error summarizing reviews.</p>; } } - Создайте коммит с сообщением "Используйте ИИ для обобщения отзывов" и отправьте его в свой репозиторий GitHub.
git add . git commit -m "Use AI to summarize reviews" git push - Откройте страницу «Размещение приложений» в консоли Firebase и дождитесь завершения развертывания.
- Откройте страницу ресторана. Вверху вы увидите краткое описание всех отзывов на странице, состоящее из одного предложения.
- Добавьте новый отзыв и обновите страницу. Вы должны увидеть изменения в сводке.
11. Снимите свою учетную запись хостинга приложений с публикации.
После завершения этого практического занятия, если вы не собираетесь продолжать использовать приложение, вы можете удалить его из публикации, чтобы никто не получил доступ к вашим ресурсам Firestore, Storage и Gemini. Вы можете повторно опубликовать его в любое время.
Чтобы снять сайт с хостинга приложений с публикации:
- Откройте раздел «Хостинг приложений» в консоли Firebase .
- Найдите бэкэнд вашего приложения и нажмите «Просмотреть» .
- В разделе «Информация в административной панели» рядом с пунктом «Домены» нажмите «Управление» . Откроется страница «Домены» .
- Рядом с вашим доменом нажмите значок «Дополнительно» (три вертикальные точки), выберите «Отключить домен» , а затем нажмите «Отключить» для подтверждения.
12. Заключение
Поздравляем! Вы научились использовать Firebase для добавления новых функций и возможностей в приложение Next.js. В частности, вы использовали следующее:
- Firebase App Hosting позволяет автоматически собирать и развертывать ваш код Next.js каждый раз, когда вы отправляете изменения в настроенную ветку.
- Аутентификация Firebase обеспечивает возможность входа и выхода из системы.
- Cloud Firestore для хранения данных о ресторанах и отзывов о них.
- Облачное хранилище Firebase для изображений ресторанов.