Сборка приложений на NestJS и Angular и запуск их в двух вариантах: через PM2 и через "Docker Compose"
Для запуска собранных приложений в режиме PM2 фронтенд будет встроен в бэкенд в виде статичных файлов.
Для запуска в режиме "Docker Compose" бэкенд будет собран в виде Docker образа, а собранная статика фронтенда будет отдаваться через и Nginx.
База данных запускается через "Docker Compose".
1. Устанавливаем все необходимые пакеты и перегенерируем клиентов Prisma
После установки пакетов сгенерированные клиенты Prisma удаляются, поэтому нужно повторно прогонять генерацию.
Команды
# Install all need dependencies
npm install --save @nestjs/serve-static dotenv wait-on
# After installing the packages, the generated Prisma clients are deleted, so you need to run their generation again
npm i && npm run generate
Вывод консоли
npm install --save @nestjs/serve-static dotenv wait-on
added 3 packages, and audited 2770 packages in 11s
331 packages are looking for funding
run `npm fund` for details
18 vulnerabilities (6 moderate, 12 high)
To address issues that do not require attention, run:
npm audit fix
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
2. Добавляем модуль для подключения статики в NestJS-приложение
Приложение NestJS-mod имеет специальную секцию для подключения такого вида модулей Core-модули, но на данном этапе для упрощения понимания такие глобальные вещи будут подключатся на уровне AppModule
.
Обновленный файл apps/server/src/app/app.module.ts
import { createNestModule, NestModuleCategory } from '@nestjs-mod/common';
import { PrismaModule } from '@nestjs-mod/prisma';
import { ServeStaticModule } from '@nestjs/serve-static';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { join } from 'path';
export const { AppModule } = createNestModule({
moduleName: 'AppModule',
moduleCategory: NestModuleCategory.feature,
imports: [
PrismaModule.forFeature({ featureModuleName: 'app' }),
ServeStaticModule.forRoot({
rootPath: join(__dirname, 'assets', 'client'),
}),
],
controllers: [AppController],
providers: [AppService],
});
3. Добавляем новый конфигурационный файл PM2 для запуска собранного бэкенд и фронтенд приложения
Приложение будет только одно, так как статика фронтенд-приложения ложится рядом с собранным бэкенд-приложением.
Создаем файл ecosystem-prod.config.json
{
"apps": [
{
"name": "nestjs-mod-fullstack",
"script": "node dist/apps/server/main.js",
"node_args": "-r dotenv/config"
}
]
}
4. Добавляем новые скрипты и обновляем существующие
Скриптов получается очень много, но они все нужны для различных режимов запуска приложений.
Группы схожих по области применения скриптов объединены в некий заголовок _____group name_____
.
Обновляем секцию с скриптами в файле package.json
{
"scripts": {
"_____pm2-full dev infra_____": "_____pm2-full dev infra_____",
"pm2-full:dev:start": "npm run generate && npm run docker-compose:start-prod:server && npm run db:create && npm run flyway:migrate && npm run pm2:dev:start",
"pm2-full:dev:stop": "npm run docker-compose:stop-prod:server && npm run pm2:dev:stop",
"_____dev infra_____": "_____dev infra_____",
"serve:dev": "./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=serve",
"serve:dev:server": "./node_modules/.bin/nx serve server --host=0.0.0.0",
"_____pm2 dev infra_____": "_____pm2 dev infra_____",
"pm2:dev:start": "./node_modules/.bin/pm2 start ./ecosystem.config.json && npm run wait-on -- --log http://localhost:3000/api/health --log http://localhost:4200",
"pm2:dev:stop": "./node_modules/.bin/pm2 delete all",
"_____pm2-full prod infra_____": "_____pm2-full prod infra_____",
"pm2-full:prod:start": "npm run generate && npm run build -- -c production && npm run copy-front-to-backend && npm run docker-compose:start-prod:server && npm run db:create && npm run flyway:migrate && npm run pm2:start",
"pm2-full:prod:stop": "npm run docker-compose:stop-prod:server && npm run pm2:stop",
"_____prod infra_____": "_____prod infra_____",
"start": "./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=start",
"build": "npm run generate && npm run tsc:lint && ./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=build --skip-nx-cache=true",
"start:prod:server": "./node_modules/.bin/nx start server",
"_____pm2 prod infra_____": "_____pm2 prod infra_____",
"pm2:start": "./node_modules/.bin/pm2 start ./ecosystem-prod.config.json && npm run wait-on -- --log http://localhost:3000/api/health --log http://localhost:3000",
"pm2:stop": "./node_modules/.bin/pm2 delete all",
"_____docker-compose-full prod infra_____": "_____docker-compose-full prod infra_____",
"docker-compose-full:prod:start": "npm run generate && npm run build -- -c production && npm run docker:build:server:latest && export COMPOSE_INTERACTIVE_NO_CLI=1 && docker-compose -f ./.docker/docker-compose-full.yml --env-file ./.docker/docker-compose-full.env --compatibility up -d",
"docker-compose-full:prod:stop": "export COMPOSE_INTERACTIVE_NO_CLI=1 && docker-compose -f ./.docker/docker-compose-full.yml --env-file ./.docker/docker-compose-full.env --compatibility down",
"docker-compose-full:prod:only-start": "export COMPOSE_INTERACTIVE_NO_CLI=1 && docker-compose -f ./.docker/docker-compose-full.yml --env-file ./.docker/docker-compose-full.env --compatibility up -d",
"docker-compose-full:prod:test:e2e": "export BASE_URL=http://localhost:8080 && npm run test:e2e",
"_____docs_____": "_____docs_____",
"docs:infrastructure": "export NESTJS_MODE=infrastructure && ./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source,client* --all -t=serve --parallel=1 -- --watch=false --inspect=false",
"_____docker-compose infra_____": "_____docker-compose infra_____",
"docker-compose:start:server": "export COMPOSE_INTERACTIVE_NO_CLI=1 && docker compose -f ./apps/server/docker-compose.yml --compatibility up -d",
"docker-compose:stop:server": "export COMPOSE_INTERACTIVE_NO_CLI=1 && docker compose -f ./apps/server/docker-compose.yml down",
"_____docker-compose prod-infra_____": "_____docker-compose prod-infra_____",
"docker-compose:start-prod:server": "export COMPOSE_INTERACTIVE_NO_CLI=1 && docker-compose -f ./apps/server/docker-compose-prod.yml --env-file ./apps/server/docker-compose-prod.env --compatibility up -d",
"docker-compose:stop-prod:server": "export COMPOSE_INTERACTIVE_NO_CLI=1 && docker-compose -f ./apps/server/docker-compose-prod.yml --env-file ./apps/server/docker-compose-prod.env down",
"_____docker_____": "_____docker_____",
"docker:build:server:latest": "docker build -t nestjs-mod-fullstack-server:latest -f ./.docker/server.Dockerfile . --progress=plain",
"_____tests_____": "_____tests_____",
"test": "./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=test --skip-nx-cache=true --passWithNoTests --output-style=stream-without-prefixes",
"test:e2e": "./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=e2e --skip-nx-cache=true --output-style=stream-without-prefixes",
"test:server": "./node_modules/.bin/nx test server --skip-nx-cache=true --passWithNoTests --output-style=stream-without-prefixes",
"_____lint_____": "_____lint_____",
"lint": "npm run tsc:lint && ./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=lint",
"lint:fix": "npm run tsc:lint && ./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=lint --fix",
"tsc:lint": "./node_modules/.bin/tsc --noEmit -p tsconfig.base.json",
"_____db_____": "_____db_____",
"db:create": "./node_modules/.bin/nx run-many -t=db-create",
"_____flyway_____": "_____flyway_____",
"flyway:create:server": "./node_modules/.bin/nx run server:flyway-create-migration",
"flyway:migrate:server": "./node_modules/.bin/nx run server:flyway-migrate",
"flyway:migrate": "./node_modules/.bin/nx run-many -t=flyway-migrate",
"_____prisma_____": "_____prisma_____",
"prisma:pull:server": "./node_modules/.bin/nx run server:prisma-pull",
"prisma:pull": "./node_modules/.bin/nx run-many -t=prisma-pull",
"prisma:generate": "./node_modules/.bin/nx run-many -t=prisma-generate",
"_____utils_____": "_____utils_____",
"copy-front-to-backend": "rm -rf dist/apps/server/assets/client && cp -r dist/apps/client/browser dist/apps/server/assets/client",
"generate": "./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=generate --skip-nx-cache=true && npm run make-ts-list && npm run lint:fix",
"tsc": "tsc",
"nx": "nx",
"dep-graph": "./node_modules/.bin/nx dep-graph",
"make-ts-list": "./node_modules/.bin/rucken make-ts-list",
"manual:prepare": "npm run generate && npm run docs:infrastructure && npm run test",
"update:nestjs-mod-versions": "npx -y npm-check-updates @nestjs-mod/* nestjs-mod -u",
"rucken": "rucken",
"wait-on": "./node_modules/.bin/wait-on --timeout=240000 --interval=1000 --window --verbose"
},
"scriptsComments": {
"pm2-full:dev:start": ["Запуск инфраструктуры и всех приложений в режиме watch через PM2"],
"pm2-full:dev:stop": ["Остановка инфраструктуры и всех приложений в режиме watch через PM2"],
"pm2:dev:start": ["Запуск всех приложений в режиме watch через PM2"],
"pm2:dev:stop": ["Остановка всех приложений в режиме watch через PM2"],
"pm2-full:prod:start": ["Запуск инфраструктуры и сборка всех приложений с последующим запуском их через PM2"],
"pm2-full:prod:stop": ["Остановка инфраструктуры и всех приложений запущенных через PM2"],
"test:e2e": ["Запуск E2E-тестов для всех пприложений"],
"copy-dist-front-to-dist-backend": ["Копирование собранного фронтенд приложения в собранный бэкенд"],
"wait-on": ["Утилита для проверки и ожидания доступности сайта"],
"docker-compose-full:prod:start": ["Билд и запуск Docker Compose инфраструктуры с бэкендом в виде Docker контейнера и статикой фронтенда отдающуюся через Nginx"],
"docker-compose-full:prod:stop": ["Остановка Docker Compose инфраструктуры и всех приложений"],
"docker-compose-full:prod:only-start": ["Запуск Docker Compose инфраструктуры с бэкендом в виде Docker контейнера и статикой фронтенда отдающуюся через Nginx"],
"docker-compose-full:prod:test:e2e": ["Запуск E2E-тестов на приложение запущенное через Docker Compose"],
"docker:build:server:latest": ["Сборка Docker образа бэкенда"]
}
}
Описания новых скриптов
Script | Comment |
---|---|
pm2-full:dev:start | Запуск инфраструктуры и всех приложений в режиме watch через PM2 |
pm2-full:dev:stop | Остановка инфраструктуры и всех приложений в режиме watch через PM2 |
pm2:dev:start | Запуск всех приложений в режиме watch через PM2 |
pm2:dev:stop | Остановка всех приложений в режиме watch через PM2 |
pm2-full:prod:start | Запуск инфраструктуры и сборка всех приложений с последующим запуском их через PM2 |
pm2-full:prod:stop | Остановка инфраструктуры и всех приложений запущенных через PM2 |
test:e2e | Запуск E2E-тестов для всех пприложений |
copy-dist-front-to-dist-backend | Копирование собранного фронтенд приложения в собранный бэкенд |
wait-on | Утилита для проверки и ожидания доступности сайта |
docker-compose-full:prod:start | Билд и запуск "Docker Compose" инфраструктуры с бэкендом в виде Docker контейнера и статикой фронтенда отдающуюся через Nginx |
docker-compose-full:prod:stop | Остановка "Docker Compose" инфраструктуры и всех приложений |
docker-compose-full:prod:only-start | Запуск "Docker Compose" инфраструктуры с бэкендом в виде Docker контейнера и статикой фронтенда отдающуюся через Nginx |
docker-compose-full:prod:test:e2e | Запуск E2E-тестов на приложение запущенное через "Docker Compose" |
docker:build:server:latest | Сборка Docker образа бэкенда |