Друзья, всем привет! Меня зовут Игорь Карелин, я frontend-разработчик в компании Домклик. В серии статей мы поэтапно разработаем продвинутое приложение-планировщик. Сначала создадим и настроим монорепозиторий c помощью NX, разработаем интерфейс с помощью React, добавим backend на основе NestJS, и, наконец, подключим базу данных MongoDB.
Будем использовать такие технологии:
NodeJS — программная платформа на движке V8 (компилирующем JavaScript в машинный код), которая превращает JavaScript из узкоспециализированного языка в язык общего назначения.
NX — система инструментов, позволяющая создавать монорепозитории для JavaScript-приложений.
TypeScript — язык программирования для разработки современных веб-приложений, расширяющий возможности традиционного JavaScript.
React — одна из самых популярных JavaScript-библиотек для создания пользовательских интерфейсов.
NestJS — фреймворк, который ускоряет и упрощает разработку масштабируемых серверных приложений на основе программной платформы NodeJS.
MongoDB — документоориентированная система управления базами данных, не требующая описания схемы таблиц. Считается одним из классических примеров NoSQL-систем, использует JSON-подобные документы и схему базы данных.
Docker — контейнеризатор приложений: программное обеспечение для автоматизации развёртывания и управления приложениями в средах с поддержкой контейнеризации.
Сначала установим NodeJs с официального сайта и редактор кода, я буду использовать Visual Studio Code.
Почему монорепозиторий?
Что такое монорепозиторий и для чего он нужен? Монорепозиторий — это стратегия разработки, при которой код нескольких приложений находится в одном репозитории. Это даёт ряд преимуществ:
Упрощённое управление зависимостями, в монорепозитории сборку легко оптимизировать, поскольку все зависимые компоненты находятся в одной и той же кодовой базе.
Сотрудничество между командами.
Я выбрал монорепозиторий, чтобы не усложнять настройку проекта и иметь возможность легко переиспользовать различные компоненты, интерфейсы и типы. Создадим его с помощью NX — эта технология обеспечивает готовую структуру проекта и продвинутую работу с CLI для лёгкого создания и внедрения приложений. Ознакомиться с NX и узнать о нём подробнее вы можете по этой ссылке.
Создание и настройка проекта
Для создания проекта нам потребуется терминал, я работаю со штатным инструментом MacOS; в зависимости от операционной системы команды могут отличаться. Установите проект NX, в котором сразу будет присутствовать React, далее выберите директорию и выполните команду npx create-nx-workspace@latest —preset=react.
В ходе установки нужно ответить на несколько пунктов:
Выберите любые названия проекта, приложений и препроцессор.
Название проекта: todo-app.
Название React-приложения: frontend.
Я выбрал SASS(.scss)
Готово! Мы только что создали проект NX с приложением React. Теперь установим NestJS. Сначала добавьте плагин Nest в существующую рабочую область. Перейдите в папку проекта и выполните команду npm install -D @nrwl/nest.
Теперь создадим приложение Nest с помощью команды nx g @nrwl/nest:app backend —frontendProject frontend. Мы сгенерировали приложение с названием “backend” и сообщили, что хотим связать его с “frontend”. Благодаря NX нам не нужно вручную настраивать порты, всё будет сделано автоматически.
В файле proxy.conf.json NX сам добавил пути для работы с API. Теперь для получения данных из backend достаточно просто перейти на /api:
proxy.conf.json { «/api»: { «target»: «http://localhost:3333», «secure»: false } }
Давайте коротко обсудим некоторые папки, которые сгенерировал для нас NX:
/apps — папка, в которой хранятся наши сгенерированые приложения frontend и backend;
/libs — здесь будут храниться части приложения, которые мы можем переиспользовать внутри монорепозитория (ведь одно из преимуществ — это упрощённое управление зависимостями и переиспользование кода между приложениями);
/tools — эта папка используется для различных правил или настроек. Например, правил EsLint, работы с автоматизацией и т.д.
Поговорив о создании и структуре проекта, самое время запустить его! И снова идём в терминал: nx run-many —parallel —target=serve —projects=backend,frontend. Мы запустили параллельно несколько проектов без дополнительных настроек. Откройте браузер и проверьте, для этого перейдите по адресу localhost:4200:
и по адресу localhost:4200/api:
Отлично, всё работает!
Установка и подключение к базе данных
Сначала хочу предупредить вас: не стоит хранить в репозиториях файлы *.env и Docker-файлы с секретами! В статье я так делаю для ознакомительных целей.
Мы будем использовать MongoDB, её я выбрал исходя из простоты использования. Подробнее ознакомиться с этой базой данных вы можете на официальном сайте.
Использовать MongoDB можно несколькими способами:
Создать удалённую БД на серверах Mongo.
Установить MongoDB на свой компьютер.
Использовать Docker — этот способ мы и рассмотрим.
Для начала установите Docker на свой компьютер, инструкцию можете посмотреть на официальном сайте. После этого создайте в корне проекта файл docker-compose.yml с такой структурой:
version: ‘3’ services: mongo: image: mongo container_name: mongo restart: always environment: — MONGO_INITDB_ROOT_USERNAME=admin — MONGO_INITDB_ROOT_PASSWORD=admin ports: — 27017:27017 volumes: — ./mongo-data:/data/db
Подробно не буду останавливаться, про Docker написано множество статей и есть подробная официальная документация. Теперь запустите Docker Compose командой docker-compose up -d. Docker скачает необходимые файлы для правильной работы и в корне проекта появится папка mongo-data, в которой хранятся данные MongoDB, я добавил её в gitignore.
Следующим шагом нужно подключиться к БД из NestJS. Сначала установите необходимые зависимости: библиотеку mongoose для работы с БД и Nest config, который обеспечит работу с файлами *.env: npm install —save mongoose @nestjs/mongoose @nestjs/config.
Я создал папку envs и добавил файл .backend.env, в котором объявил переменные:
DB_LOGIN=admin DB_PASSWORD=admin DB_HOST=localhost DB_PORT=27017 DB_AUTHDATABASE=admin
Теперь создайте конфигурационный файл, который поможет генерировать ссылку для подключения к БД:
db-connect.config.ts import { ConfigService } from ‘@nestjs/config’; import { MongooseModuleOptions } from ‘@nestjs/mongoose’; const getMongoString = (configService: ConfigService) => ‘mongodb://’ + configService.get(‘DB_LOGIN’) + ‘:’ + configService.get(‘DB_PASSWORD’) + ‘@’ + configService.get(‘DB_HOST’) + ‘:’ + configService.get(‘DB_PORT’) + ‘/’ + configService.get(‘DB_AUTHDATABASE’); const getMongoOptions = () => ({ useNewUrlParser: true, useUnifiedTopology: true, }); export const getMongoConfig = async ( configService: ConfigService ): Promise<MongooseModuleOptions> => { console.log(getMongoString(configService)); return { uri: getMongoString(configService), …getMongoOptions(), }; };
Далее перейдите в app.module.ts и импортируйте в него ConfigModule и MongooseModule. Пара слов о модулях в NestJS: это классы с декоратором Module(), предоставляющим метаданные, которые Nest использует для организации структуры приложения.
В конечном счёте файл будет выглядеть так:
app.module.ts import { Module } from ‘@nestjs/common’; import { ConfigModule, ConfigService } from ‘@nestjs/config’; import { MongooseModule } from ‘@nestjs/mongoose’; import { getMongoConfig } from ‘../config/db-connect.config’; import { AppController } from ‘./app.controller’; import { AppService } from ‘./app.service’; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, // Позволяет обратиться к env во всем приложении envFilePath: ‘envs/.backend.env’, // Указываем путь до env файла }), MongooseModule.forRootAsync({ // Модуль для работы с mongo imports: [ConfigModule], inject: [ConfigService], useFactory: getMongoConfig, // добавляем созданную ранее функцию подключения к БД }), ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
На этом пока остановимся. Мы разобрали настройку проекта и подключение к базе данных для дальнейшей работы. В следующих частях напишем логику работы с базой данных, добавим регистрацию пользователей и т.д. Спасибо за внимание!
Исходный код доступен по ссылке.