Как развернуть приложение 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.