# Конфигурация проекта prescriptions-frontend Документ описывает способы конфигурирования микрофронтенда `prescriptions-frontend` (Module Federation `srx_prescriptions`, экспонирует `./PrescriptionsPage`), его переменные сборки/CI и параметры деплоя. ## Способы конфигурирования В отличие от backend-сервисов, у фронтенда **нет рантайм-конфигурации через `.env`**: собранный бандл — статические файлы, которые раздаёт nginx. Всё поведение задаётся **на этапе сборки** одной переменной — `BUILD_ENV`. - `env.js` читает `process.env.BUILD_ENV` и валидирует его против списка `local`/`stage`/`prod`/`contour`/`preprod` (иначе — ошибка сборки `set BUILD_ENV one of ...`); - `webpack.config.js` через `DefinePlugin` внедряет глобальные константы `BUILD_ENV` и `STORYBOOK` в бандл; - `build.config.js` по `BUILD_ENV` выбирает режим сборки (`mode`/`devtool`); - `module/api/hosts.ts` и `module/api/module-hosts.ts` содержат карты хостов по окружениям; SDK (`@sarex-team/sdk-js`) на рантайме выбирает нужный хост по глобальной константе `BUILD_ENV` (по умолчанию `prod`). Отдельного конфиг-файла (yaml/toml) у приложения нет. ### Значения `BUILD_ENV` | `BUILD_ENV` | `mode` | `devtool` | Назначение | | --- | --- | --- | --- | | `local` | `development` | `eval-source-map` | Локальная разработка (dev-server, storybook), `httpService` → `original` | | `stage` | `development` | `eval-source-map` | Стенд stage | | `preprod` | `production` | `source-map` | Предпрод | | `prod` | `production` | `source-map` | Прод | | `contour` | `production` | `source-map` | Изолированный контур (относительные пути хостов) | ## Переменные сборки и CI | Переменная | Где используется | Назначение | | --- | --- | --- | | `BUILD_ENV` | `env.js`, `webpack.config.js`, `Dockerfile` (ARG), `.gitlab-ci.yml` (`--build-arg`) | Целевое окружение сборки. Обязательна | | `NPM_TOKEN` | `.npmrc`, `Dockerfile` (ARG), `.gitlab-ci.yml` (`--build-arg`) | Токен доступа к приватному npm-реестру `nexus.infra.sarex.io` | | `STORYBOOK` | `webpack.config.js` (`DefinePlugin`), `module/pages/index.tsx` | Флаг сборки под Storybook (`"true"`/`"false"`) | Cypress-тесты берут учётные данные из `cypress.env.json` (пример — `cypress.env-example.json`): `SRX_LOGIN`, `SRX_PASSWORD`. Версия Node для разработки — `v20.16.0` (`.nvmrc`). ## Хосты по окружениям Базовые API-хосты подставляются из `module/api/hosts.ts` по `BUILD_ENV` (детальная разбивка по сервисам — в `ENDPOINTS.md`): | Окружение | Базовый API | Пример (`documentations`) | | --- | --- | --- | | `local` / `stage` | `https://stage-api.sarex.io` | `https://stage-api.sarex.io/documentations/api/v1` | | `preprod` | `https://api.preprod.sarex.io` | `https://api.preprod.sarex.io/documentations/api/v1` | | `prod` | `https://api.sarex.io` | `https://api.sarex.io/documentations/api/v1` | | `contour` | относительные пути | `/documentations/api/v1` | Удалённый модуль (Module Federation) `documentations` подключается по `module/api/module-hosts.ts` (`remoteEntry.js`). ## Запуск и скрипты (`package.json`) | Команда | Назначение | | --- | --- | | `npm run serve-module` | Dev-server (`webpack.dev.js`, порт `9001`, https, proxy `/api`, `/admin` на `appUrl`), `BUILD_ENV=local` | | `npm run storybook` | Storybook (порт `9000`, https), `BUILD_ENV=local` | | `npm run start` / `test:dev` | Параллельный запуск serve-module + storybook (+ cypress в `test:dev`) | | `npm run build-module` | Продакшн-сборка модуля (`webpack --config webpack.config.js`) | | `npm run build-storybook` | Сборка статики Storybook | | `npm run cypress:open` | Запуск e2e-тестов Cypress | | `npm run lint` / `lint:ts` | Prettier / проверка типов `tsc --noEmit` | ## Сборка образа (`Dockerfile`) Двухстадийная сборка: 1. `node:15` — установка зависимостей (`npm i --legacy-peer-deps` с `NPM_TOKEN`), `npm run lint`, `BUILD_ENV=$BUILD_ENV npm run build-module` → `/app/dist`; 2. `nginx:mainline-alpine-otel` — копирование `dist` в `/dist` и конфига `nginx/nginx.conf`. Build-args: `BUILD_ENV`, `NPM_TOKEN`. nginx (`nginx/nginx.conf`) раздаёт статику из `/dist`, отдаёт `/ping` → `{"result": "ok"}` (healthcheck) и запрещает кеширование `/module/remoteEntry.js` (`Cache-Control: no-store`). ## CI/CD (`.gitlab-ci.yml`) Пайплайн подключает общие шаблоны `generic/common-ci` (`common-security-scan.yaml`, `universal-pipeline.yaml`, ref `apps-business`). `SERVICE_NAME=prescriptions-frontend`. Окружение переключается по ветке/тегу (`workflow.rules`): | Условие | STAND | NAMESPACE | BUILD_ENV | CHART_VERSION | | --- | --- | --- | --- | --- | | ветка `stage` | `stage` | `proc` | `stage` | `1.0.0-stage` | | ветка `master` | `preprod` | `prescriptions-preprod` | `preprod` | `1.0.0-preprod` | | тег (`CI_COMMIT_TAG`) | `production` | `prescriptions-prod` | `prod` | `1.0.0-prod` | | merge request | — | — | — | сборка образа отключена (`ENABLE_BUILD_IMAGE=false`) | Деплой параметризуется через `HELM_SET_ARGS` (образ, `global.env`, `commitSha`, `gitlabUri`, `gitlabJobUrl`, `owner`). ## Helm-чарт проекта (`.helm`) `Chart.yaml`: зависимость `universal-chart` (`oci://cr.yandex/.../charts`, версия `0.1.7`). `values.yaml` (`universal-chart.services.frontend`): - `deployment.name = prescription-frontend`, `replicaCount = 1`, `port = 80`, `revisionHistoryLimit = 10` (prod — `15`); - `image.name = cr.yandex/crp3ccidau046kdj8g9q/prescription-frontend`, `pullPolicy = IfNotPresent`; - `service.name = prescriptions-frontend-service`, `type = ClusterIP`, `port/targetPort = 80`; - `imagePullSecrets = dockerhub`; - probes (`liveness`/`readiness`) на `/ping:80` заданы, но **выключены** (`enabled: false`); - `envs: []`, `secretEnvs: []` — переменных окружения контейнеру не передаётся; - ресурсы: `requests` `memory 100Mi`, `cpu 100m`. ## Инфраструктура (`iac/apps/prescriptions`) Разворачивается через Kustomize. Состав каталога: | Путь | Назначение | | --- | --- | | `base/namespace.yaml` | Namespace `prescriptions` с `istio-injection: enabled` | | `base/deployment.yaml` | Deployment `frontend`, образ `cr.yandex/.../prescriptions-frontend:production_...`, порт `80`, `requests` `cpu 25m`/`memory 100Mi`, `imagePullSecrets: regcred` | | `base/service.yaml` | Service `frontend-service`, `ClusterIP`, порт `80` | | `base/kustomization.yaml` | Сборка base (namespace + deployment + service) | | `yc-k8s-test/` | Оверлей поверх `../base` (патч `replicas.yaml` закомментирован) | | `brusnika-prod/`, `brusnika-stage/` | Оверлеи (см. замечание ниже) | ## Замечания и потенциальные проблемы - **Оверлеи `brusnika-prod` / `brusnika-stage`** сейчас содержат `HelmRelease` бэкенда `measurements` (namespace `measurements`, образ `documentations`), не относящийся к prescriptions — похоже на копипаст-заготовку, которую нужно заменить на конфигурацию prescriptions-frontend либо удалить. - **Два способа описания деплоя**: helm-чарт в репозитории фронтенда (`.helm`, `universal-chart`) и Kustomize-манифесты в инфраструктуре (`iac/apps/prescriptions`) описывают один и тот же сервис по-разному — стоит зафиксировать единый источник истины. - **Несогласованные имена**: `SERVICE_NAME=prescriptions-frontend` (мн. ч.), а `deployment.name`/`image.name` в `.helm` — `prescription-frontend` (ед. ч.). В инфра-манифестах deployment называется просто `frontend`. - **Версии Node расходятся**: разработка — `v20.16.0` (`.nvmrc`), сборка образа — `node:15` (`Dockerfile`). - **Мёртвая конфигурация**: экспорт `hosts` в `networking.config.js` (внедрение `___host`) и `module/Env` (`IEnv`, `process.env as IEnv`) в коде модуля не используются; `dotenv-webpack` присутствует в devDependencies, но не подключён в `webpack.config.js`. `networking.config.js` реально используется только в `webpack.dev.js` (прокси dev-сервера). ## Минимальный набор для сборки - `BUILD_ENV` — одно из `local`/`stage`/`preprod`/`prod`/`contour` (обязательно); - `NPM_TOKEN` — для установки приватных пакетов `@sarex-team/*` из nexus; - (опционально) `STORYBOOK=true` — при сборке/запуске Storybook; - (для e2e) `SRX_LOGIN`, `SRX_PASSWORD` в `cypress.env.json`.