Как развернуть приложение React с помощью PostgreSQL?
 
 PostgreSQL – это передовая система управления реляционными базами данных корпоративного уровня, имеющая множество вариантов использования. В настоящее время она является второй по популярности базой данных SQL, сразу после MySQL.
В этой статье мы вникнем в суть PostgreSQL, рассмотрим различия между базами данных SQL и NoSQL, а также предоставим пошаговое руководство по развертыванию веб-приложения на базе PostgreSQL.
Contents
Что такое PostgreSQL?
PostgreSQL – это бесплатная объектно-реляционная база данных с открытым исходным кодом, поддерживающая SQL и JSON.
Она была выпущена в 1996 году, поэтому считается зрелой, надежной и безопасной системой управления реляционными базами данных (RDBMS).
Postgres может использоваться как база данных общего назначения для транзакций, геопространственная база данных, база данных динамических веб-приложений, федеративная база данных и многое другое.
По сравнению с другими популярными базами данных, такими как MySQL, она поддерживает наследование таблиц, пользовательские типы, асинхронную репликацию и многоверсионный контроль параллелизма (MVCC).
Она известна своей производительностью, масштабируемостью, расширяемостью, отказоустойчивостью и соответствием стандарту ACID.
СУБД поддерживается на большинстве основных операционных систем, включая Windows, Linux и macOS.
Кроме того, он поддерживает большинство популярных языков программирования, таких как Java, Python, C, Go, Perl и JavaScript.
SQL против баз данных NoSQL
Базы данных можно разделить на две категории по структуре данных:
- Реляционные базы данных (SQL)
- Нереляционные базы данных (NoSQL)
Реляционные базы данных (SQL)
Реляционные базы данных используют язык SQL или структурированный язык запросов. SQL – это специфический язык, используемый для запросов и манипулирования данными.
Язык поддерживает простые команды, транзакции и встроенные процедуры, такие как хранимые функции или представления.
Базы данных SQL основаны на предопределенных схемах. Они состоят из таблиц с набором столбцов, каждый из которых имеет свой тип данных. Обычно они обладают свойствами ACID:
- Атомарность
- Последовательность
- Изоляция
- Долговечность
Базы данных SQL широко используются с 1970-х годов.
Наиболее популярными базами данных SQL являются MySQL, PostgreSQL, SQLite и Oracle Database.
Нереляционные базы данных (NoSQL)
Нереляционные базы данных, или базы данных не-SQL, не имеют строгой схемы. Они идеально подходят для хранения огромных объемов неструктурированных или динамических данных, чаще всего JSON.
Существует множество типов баз данных NoSQL, включая:
- Базы данных документов
- Базы данных с ключами-значениями
- Графовые базы данных
В последние годы базы данных NoSQL становятся все более популярными благодаря наличию больших объемов неструктурированных данных.
К наиболее используемым базам данных NoSQL относятся Redis, Cassandra и AWS DynamoDB.
Что лучше – SQL или NoSQL?
Выбор между базами данных SQL и NoSQL зависит от вашего сценария использования и данных.
Если вы имеете дело с огромными объемами неструктурированных данных, однозначно выбирайте NoSQL. С другой стороны, если ваши данные в основном структурированы, лучше выбрать SQL.
Еще два фактора, которые следует учитывать, – это производительность и масштабирование. Базы данных NoSQL, как правило, работают быстрее, чем базы данных SQL. Базы данных SQL могут масштабироваться только по вертикали, а базы данных NoSQL – по горизонтали.
Наконец, некоторые веб-фреймворки поддерживают только базы данных SQL, а другие – только NoSQL.
Как развернуть приложение React с помощью PostgreSQL?
В этом разделе статьи вы узнаете, как развернуть веб-приложение с поддержкой Postgres на Back4app.
Пререквизиты
- Опыт работы с JavaScript ES6, React и Next.js
- Базовое понимание Docker, а также облачной модели BaaS и CaaS.
- На вашем компьютере установлены JavaScript IDE и Docker Desktop
- Бесплатная учетная запись Back4app и GitHub
Что такое стек Back4app?
Прежде чем перейти к процессу развертывания, давайте вкратце обсудим, какие решения предлагает Back4app.
- Back4app (BaaS) – это полноценное бэкенд-решение. Оно включает в себя управление пользователями, аутентификацию, базы данных в реальном времени (NoSQL или PostgreSQL), выполнение пользовательского кода, автоматически генерируемые API, SDK, push-уведомления и многое другое.
- Back4app Containers (CaaS) – это платформа для управления и развертывания контейнеров на базе Docker. Она позволяет создавать контейнеры Docker в несколько кликов!
- Back4app AI-agent – это совершенно новый агент, работающий на основе искусственного интеллекта. Он позволяет выполнять все задачи, связанные с облаком, с помощью общения. Агент тесно интегрируется с двумя другими решениями Back4app.
На протяжении всей статьи мы будем использовать Back4app BaaS и Back4app Containers. Тем не менее, вам стоит прочитать статью “Как использовать искусственный интеллект для веб-разработки? “, чтобы узнать, как использовать искусственный интеллект для ускорения процесса разработки.
Обзор проекта
Мы создадим простое веб-приложение для отслеживания бюджета. Веб-приложение позволит пользователям добавлять расходы, удалять их и подсчитывать различную статистику (например, потраченную сумму, процент от бюджета).
Приложение будет разделено на бэкенд и фронтенд. Бэкенд будет построен на Back4app (с поддержкой PostgreSQL), а фронтенд – на React (с использованием Next.js).
Мы соединим их с помощью Parse SDK и развернем фронтенд в контейнерах Back4app.
Бэкэнд
Начнем с бэкэнда.
Создать приложение Back4app
Чтобы создать приложение Back4app, сначала перейдите на свою панель Back4app и нажмите “Создать новое приложение”.

Далее выберите “Backend as a Service”, поскольку мы создаем бэкенд.

Дайте приложению описательное имя, выберите “PostgreSQL” в качестве базы данных и нажмите “Создать”.

На момент написания статьи с точки зрения разработчика разница между этими двумя типами баз данных невелика. Одни и те же методы Parse SDK применимы к обоим типам.
Back4app потребуется некоторое время, чтобы подготовить все необходимое для вашего приложения. Это включает в себя базу данных, уровень приложений, автомасштабирование, авторезервное копирование и настройки безопасности.
Как только ваше приложение будет готово, вы будете перенаправлены на просмотр базы данных приложения в режиме реального времени.

Архитектура баз данных
Продолжаем, давайте спроектируем базу данных.
Поскольку наше приложение относительно простое, нам понадобится только один класс. Назовем его Expense.
Чтобы создать новый класс базы данных, нажмите “Создать класс”, назовите его Expense и убедитесь, что установлен флажок “Public Read and Write enabled”.

Включение публичного чтения и записи считается плохой практикой, поскольку это позволяет любому выполнять CRUD-операции над вашими классами. Вопросы безопасности выходят за рамки этой статьи. Тем не менее, будет полезно ознакомиться с разделом “Безопасность сервера Parse“.
По умолчанию классы баз данных содержат следующие четыре поля:
+-----------+------------------------------------------------------------------------+
| Name      | Explanation                                                            |
+-----------+------------------------------------------------------------------------+
| objectId  | Object's unique identifier                                             |
+-----------+------------------------------------------------------------------------+
| updatedAt | Date time of the object's last update.                                 |
+-----------+------------------------------------------------------------------------+
| createdAt | Date time of object's creation.                                        |
+-----------+------------------------------------------------------------------------+
| ACLs      | Allow you to control the access to the object (e.g. read, update).     |
+-----------+------------------------------------------------------------------------+Ознакомьтесь с ними вкратце, поскольку мы будем использовать их при создании фронтенда.
Затем добавьте следующие поля в класс "Расходы":
+-----------+-------------+--------------------+----------+
| Data type | Name        | Default value      | Required |
+-----------+-------------+--------------------+----------+
| String    | name        | <leave blank>      | yes      |
+-----------+-------------+--------------------+----------+
| String    | description | <leave blank>      | no       |
+-----------+-------------+--------------------+----------+
| Number    | price       | 0                  | yes      |
+-----------+-------------+--------------------+----------+После этого заполните базу данных примерами данных.
Создайте несколько товаров, указав их названия, описания и цены. Кроме того, можно импортировать этот дамп данных.

Тестовые данные впоследствии позволят нам протестировать бэкэнд и фронтэнд.
Облачный код
Back4app позволяет выполнять пользовательский JavaScript-код с помощью функций Cloud Code. Функции могут быть запланированы как задания или вызваны с помощью Parse или HTTP-запросов.
Поскольку они работают в управляемой среде, это избавляет вас от необходимости обрабатывать и масштабировать собственные серверы.
Чтобы узнать больше о функциях как услуге (FaaS), прочитайте статью Что такое бессерверные функции?
Для расчета статистики расходов мы воспользуемся функцией Cloud Code.
Чтобы создать его, выберите “Cloud Code > Функции и веб-хостинг” на боковой панели. Затем откройте файл cloud/main.js и вставьте в него следующий код:
// cloud/main.js
const totalBudget = 100;
Parse.Cloud.define("getStatistics", async (request) => {
  const query = new Parse.Query("Expense");
  const totalExpenses = await query.count();
  const results = await query.find();
  const totalSpent = results.reduce(
    (sum, expense) => sum + expense.get("price"), 0);
  const spentPercentage = totalSpent > 0 ? 
    Math.round((totalSpent / totalBudget) * 100) : 0;
  return {
    totalExpenses,
    totalSpent,
    totalBudget,
    spentPercentage
  };
});- Этот код определяет новую функцию Cloud Code под названием getStatistics.
- Функция агрегирует данные и вычисляет totalSpentиspentPercentage.
И наконец, нажмите кнопку “Развернуть”, чтобы развернуть функцию в облаке.
И мы закончили с бэкэндом. Это было легко!
Frontend
В этом разделе статьи мы реализуем фронтенд приложения.
Создать следующее приложение
Самый простой способ загрузить приложение Next.js – это утилита create-next-app. Чтобы воспользоваться ею, откройте терминал и выполните следующую команду:
$ npx create-next-app@latest back4app-postgres
√ Would you like to use TypeScript? ... No
√ Would you like to use ESLint? ... Yes
√ Would you like to use Tailwind CSS? ... Yes
√ Would you like to use `src/` directory? ... Yes
√ Would you like to use App Router? (recommended) ... Yes
√ Would you like to customize the default import alias (@)? ... No
Creating a new Next.js app in /back4app-postgres.Если вы никогда не использовали утилиту
create-next-app, она будет установлена автоматически.
Убедитесь, что вы включили TailwindCSS, поскольку мы будем использовать его вместо библиотеки компонентов.
Затем очистите загруженный проект, удалив содержимое папки public/.
Сохраните только первые три строки src/app/globals.css:
/* app/src/globals.css */
@tailwind base; @tailwind components; @tailwind utilities;И замените app/src/globals.css на следующий код:
// src/app/page.js 
export default function Page() { 
  return ( 
      <p>Back4app rocks!</p> 
  ); 
}Запустите сервер разработки:
$ next devОткройте свой любимый веб-браузер и перейдите на сайт http://localhost:3000/. Если все прошло успешно, вы должны увидеть сообщение “Back4app rocks!”.
Просмотров
Фронтенд будет иметь следующие конечные точки:
- /отображает таблицу расходов и статистику расходов
- /add/отображает форму для добавления нового расхода
- /delete// отображает подтверждение удаления расхода
Чтобы реализовать эти конечные точки, создайте следующую структуру каталогов:
src/
├── add/
│   └── page.js
└── delete/
    └── [objectId]/
        └── page.jsКроме того, создайте папку components с файлами Container.js и Header.js:
src/
└── components/
    ├── Container.js
    └── Header.jsВставьте следующее в файл Container.js:
// src/app/components/Container.js
const Container = ({children}) => {
  return (
    <div className="container mx-auto px-4 sm:px-6 lg:px-8">
      {children}
    </div>
  )
}
export default Container;И сделайте то же самое для Header.js:
// src/app/components/Header.js
import Container from "@/app/components/Container";
import Link from "next/link";
const Header = () => {
  return (
    <Container>
      <div className="py-4">
        <Link href="/">
          <div 
            className="text-2xl font-semibold text-indigo-500 hover:text-indigo-700"
          >
            back4app-postgres
          </div>
        </Link>
      </div>
    </Container>
  )
}
export default Header;Используйте Container.js и Header.js в layout.js следующим образом:
// src/app/layout.js
"use client";
import {Inter} from "next/font/google";
import "./globals.css";
import Header from "@/app/components/Header";
import Container from "@/app/components/Container";
const inter = Inter({ subsets: ["latin"] });
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <Header/>
        <Container>
          {children}
        </Container>
      </body>
    </html>
  );
}Наконец, вставьте код вида в файлы соответствующим образом:
Перезапустите сервер разработки и посетите http://localhost:3000 в браузере. Вы должны увидеть что-то похожее на это:

При нажатии на кнопку “Добавить расход” вы будете перенаправлены на форму добавления расхода.
Parse SDK
Существует несколько способов подключения к бэкенду Back4app:
- RESTful API
- API GraphQL
- Parse SDK
Мы остановимся на последнем варианте, поскольку он наиболее надежен и прост в настройке.
Parse SDK – это набор инструментов, содержащий удобные средства для запросов к данным, управления ими, выполнения функций Cloud Code и многого другого.
Он доступен для многих языков программирования и фреймворков, таких как JavaScript, PHP, Flutter и Objective-C.
Начните с установки Parse через npm:
$ npm install parseЧтобы использовать Parse в наших представлениях React, мы должны сначала инициализировать его. Но перед этим мы создадим контекст React, который позволит нам передавать экземпляр Parse во все наши представления.
Создайте папку context в папке src/app и файл parseContext.js в ней:
import {createContext} from "react";
const ParseContext = createContext();
export default ParseContext;Затем инициализируйте Parse в layout.js и оберните все приложение с помощью ParseContext.Provider, как показано ниже:
// src/app/layout.js
import Parse from "parse/dist/parse";
import ParseContext from "@/app/context/parseContext";
Parse.initialize(
  "<your_parse_application_id>",
  "<your_parse_javascript_key>",
);
Parse.serverURL = "https://parseapi.back4app.com/";
export default function RootLayout({ children }) {
  return (
    <ParseContext.Provider value={Parse}>
      <html lang="en">
        // ...
      </html>
    </ParseContext.Provider>
  );
}Обязательно замените <your_parse_application_id> и <your_parse_javascript_key> настоящими ключами. Чтобы получить их, перейдите на приборную панель Back4app и выберите “Настройки приложения > Безопасность и ключи” на боковой панели.

Теперь мы можем получить экземпляр Parse в наших представлениях следующим образом:
const parse = useContext(ParseContext);Затем слегка измените представления, чтобы они вызывали методы Parse.
src/app/page.js:
// src/app/page.js
export default function Page() {
  // ...
  const parse = useContext(ParseContext);
  const fetchExpenses = () => {
    const query = new parse.Query("Expense");
    query.find().then((fetchedExpenses) => {
      const expenses = fetchedExpenses.map(expense => ({
        objectId: expense.id,
        name: expense.get("name"),
        description: expense.get("description"),
        price: expense.get("price"),
        createdAt: expense.get("createdAt"),
      }));
      setExpenses(expenses);
      console.log("Expenses fetched successfully.");
    }).catch((error) => {
      console.error("Error while fetching expenses:", error);
    });
  }
  const fetchStatistics = () => {
    parse.Cloud.run("getStatistics").then((statistics) => {
      setStatistics(statistics);
      console.log("Statistics fetched successfully.");
    }).catch((error) => {
      console.error("Error while fetching statistics:", error);
    });
  }
  // ...
}src/app/add/page.js:
// src/app/add/page.js
export default function Page() {
  // ...
  const parse = useContext(ParseContext);
  const onAddClick = () => {
    const Expense = parse.Object.extend("Expense");
    const expense = new Expense();
    expense.set("name", name);
    expense.set("description", description);
    expense.set("price", parseFloat(price));
    expense.save().then((expense) => {
        console.log("Expense created successfully with objectId: ", expense.id);
        router.push("/");
      }, (error) => {
        console.error("Error while creating expense: ", error);
      }
    );
  }
  const onCancelClick = () => {
    router.push("/");
  }
  // ...
}src/app/delete/[objectId]/page.js:
// src/app/delete/[objectId]/page.js
export default function Page() {
  // ...
  const parse = useContext(ParseContext);
  const onDeleteClick = () => {
    const Expense = parse.Object.extend("Expense");
    const query = new parse.Query(Expense);
    query.get(objectId).then((expense) => {
      return expense.destroy();
    }).then((response) => {
      console.log("Expense deleted successfully");
      router.push("/");
    }).catch((error) => {
      console.error("Error while deleting expense: ", error);
    });
  }
  const onCancelClick = () => {
    router.push("/");
  }
  // ...
}Не забудьте про импорт в верхней части файла:
import {useContext} from "react";
import ParseContext from "@/app/context/parseContext";Отлично, вот и все.
Теперь ваш фронтенд подключен к бэкенду. Если вы зайдете в приложение через браузер, то увидите, что данные корректно загружаются из бэкенда. Все изменения на фронтенде теперь отражаются в бэкенде.
Dockerize
Поскольку Back4app Containers является CaaS-платформой, ваш проект должен быть докеризован перед развертыванием. Рекомендуемый способ докеризации проекта – через Dockerfile.
Dockerfile – это сценарий, содержащий инструкции по созданию образа контейнера.
Создайте Dockerfile в корне проекта:
# Dockerfile
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
RUN npm install -g next
EXPOSE 3000
CMD ["next", "start", "-p", "3000"]Этот Dockerfile использует образ node:18-alpine, создает рабочий каталог, управляет зависимостями, копирует проект и собирает приложение.
По завершении он открывает порт 3000 и запускает сервер Next.js для прослушивания этого порта.
Затем создайте файл .dockerignore, чтобы минимизировать размер образа:
# .dockerignore
.idea/
node_modules/
.next/
/out/
build/
.vercelФайлы .dockerignore работают так же, как и файлы .gitignore.
Убедитесь, что все работает, собрав и запустив образ локально:
$ docker build -t back4app-postgres:1.0 .
$ docker run -it -p 3000:3000 back4app-postgres:1.0Откройте веб-браузер и перейдите на сайт http://localhost:3000. Веб-приложение должно оставаться полностью функциональным.
Передача в VCS
Чтобы развернуть свой код в Back4app Containers, вы должны опубликовать его на GitHub.
- Войдите в свою учетную запись GitHub.
- Создайте новый репозиторий.
- Скопируйте URL-адрес удаленного источника – например, [email protected]:duplxey/repo.git.
- Инициализируйте Git-репозиторий: git init
- Добавьте удаленное место: git remote add origin
- Добавьте все файлы: git add .
- Создайте фиксацию: git commit -m "project init".
- Разместите исходный код: git push origin main
Откройте свой любимый веб-браузер и убедитесь, что весь код добавлен в репозиторий.
Развернуть код
Теперь, когда приложение докеризовано и размещено на GitHub, мы можем развернуть его.
Перейдите на приборную панель Back4app и снова нажмите на кнопку “Создать новое приложение”.

Выберите “Контейнеры как сервис”, поскольку мы развертываем приложение с докером.

Если вы впервые работаете с Back4app Containers, вы должны связать свой GitHub с аккаунтом Back4app.
Выбирая, к каким репозиториям Back4app имеет доступ, убедитесь, что разрешили доступ к репозиторию, созданному в предыдущем шаге.
Затем “Выберите” хранилище.

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

Когда вы нажмете кнопку “Создать приложение”, Back4app возьмет код с GitHub, соберет образ Docker, отправит его в реестр контейнеров и развернет.
Через несколько мгновений ваше приложение будет доступно по URL-адресу на боковой панели.

Заключение
Из этой статьи вы узнали, что такое PostgreSQL, чем отличаются базы данных SQL и NoSQL, а также как развернуть веб-приложение с поддержкой Postgres на Back4app.
Чтобы проверить ваше понимание, я предлагаю вам реализовать некоторые из этих идей:
- Аутентификация пользователя
- Вместо того чтобы иметь глобальный бюджет, сделайте его ориентированным на пользователя
- Добавьте пользовательский домен в приложение Back4app Containers
Получите финальный исходный код из репозитория back4app-postgres.

