Архитектура фронтенд приложений на платформе NextJS
Next.js — это платформа React для создания полнофункциональных веб-приложений. Вы используете компоненты React для создания пользовательских интерфейсов и Next.js для дополнительных функций и оптимизации.
Инструментарий¶
В качестве менеджера зависимостей используется стандартная реализация npm.
Основной инструментарий для разработки фронтенд сервисов можно разделить на два условных раздела: для непосредственной работы приложени, а также утилитарный набор инструментов для разработки.
Прежде, чем приступить к разработке необходимо ознакомиться с основным инструментарием, который представлен ниже:
- Основной инструментарий для реализации сервисов:
- React 19+, React Compiler
- NextJs 15+
- MUI 6+
- axios (deprecated), use
fetch - zustand
- react-query
- openapi-typescript-codegen
- sass
- Вспомогательные инструменты разработки
Типовая структура сервиса¶
Ниже представлена типовая структура сервиса, а также описание дирректорий и файлов. Выход за пределы структуры позволяется только с разрегения техлида или лидера компетенций соответствующего направления, а также лидера разработки.
📁 {{ project name }} // Название проекта
| 📁 .vscode // Настройки IDE
| 📁 apps // Список приложений
| | 📁 portal // Проект портала
| | | 📁 public // Общедоступные файлы
| | | 📁 src // Исходных код приложения
| | | | 📁 app // Дирректория app routing nextjs
| | | | | 📁 [lng] // Локализация
| | | | | | 📁 (main) // Группа основных роутов с авторизацией
| | | | | | 📁 auth // Авторизация приложений
| | | | | | layout.tsx // layout
| | | | | | page.tsx // Страница
| | | | | | loading.tsx // Скелетон загрузки
| | | | | 📁 health // Роут для helthcheck
| | | | | | router.ts // Хендлер загрузки
| | | | | fonts.tsx // Настройки шрифтов
| | | | | favicon.ico // Иконка проекта
| | | | | globals.scss // Настройка глобальных css
| | | | | theme.tsx // Настройки темы MUI
| | | | 📁 assets/fonts // Настройка
| | | | 📁 providers // Проект
| | | | | index.ts // Проект
| | | | | query.ts // Проект
| | | | | store.ts // Проект
| | | | | theme.ts // Проект
| | | | 📁 modules // Проект
| | | | | 📁 common // Проект
| | | | | | 📁 widgets // Проект
| | | | | | | 📁 comopnents // Проект
| | | | | | | | index.ts // Проект
| | | | | | | | AppToolBar.tsx // Проект
| | | | | | | | AppSideBar.tsx // Проект
| | | | | | | 📁 hooks // Проект
| | | | | | | | index.ts // Проект
| | | | | | | 📁 queries // Проект
| | | | | | | | index.ts // Проект
| | | | | | | | notification.ts // Проект
| | | | | | | 📁 mutations // Проект
| | | | | | | | index.ts // Проект
| | | | | | | | read-notifications.ts // Проект
| | | | | | | | delete-notifications.ts // Проект
| | | | | | | index.ts // Проект
| | | | | | | types.ts // Проект
| | | | | | 📁 features // Проект
| | | | | | | 📁 comopnents // Проект
| | | | | | | | index.ts // Проект
| | | | | | | | AppToolBar.tsx // Проект
| | | | | | | | AppSideBar.tsx // Проект
| | | | | | | 📁 queries // Проект
| | | | | | | | index.ts // Проект
| | | | | | | | notification.ts // Проект
| | | | | | | 📁 mutations // Проект
| | | | | | | | index.ts // Проект
| | | | | | | | read-notifications.ts // Проект
| | | | | | | | delete-notifications.ts // Проект
| | | | | | | index.ts // Проект
| | | | | | | types.ts // Проект
| | | | | 📁 users // Проект
| | | | | | | 📁 comopnents // Проект
| | | | | | | | index.ts // Проект
| | | | | | | | AppToolBar.tsx // Проект
| | | | | | | | AppSideBar.tsx // Проект
| | | | | | | 📁 queries // Проект
| | | | | | | | index.ts // Проект
| | | | | | | | notification.ts // Проект
| | | | | | | 📁 mutations // Проект
| | | | | | | | index.ts // Проект
| | | | | | | | read-notifications.ts // Проект
| | | | | | | | delete-notifications.ts // Проект
| | | | | | | index.ts // Проект
| | | | | | | types.ts // Проект
| | | | | | | utils.ts // Проект
| | | | | | 📁 features // Проект
| | | | | | | 📁 comopnents // Проект
| | | | | | | | index.ts // Проект
| | | | | | | | ChangeAvatar.tsx // Проект
| | | | | | | | DeleteUserDialog.tsx // Проект
| | | | | | | 📁 queries // Проект
| | | | | | | | index.ts // Проект
| | | | | | | | me.ts // Проект
| | | | | | | 📁 mutations // Проект
| | | | | | | | index.ts // Проект
| | | | | | | | change-avatar.ts // Проект
| | | | | | | index.ts // Проект
| | | | | | | types.ts // Проект
| | | | | | | utils.ts // Проект
| | | | | 📁 companies // Проект
| | | | middleware.ts
| | | .env.example // Проект
| | | .eslintrc.js // Проект
| | | nuxt-env.d.ts // Проект
| | | package.json // Проект
| | | postcss.config.js // Проект
| | | readme.md // Проект
| | | tsconfig.json // Проект
| | 📁 portal-e2e // Проект e2e тестов
| 📁 packages
| | 📁 ui
| | | 📁 .storybook
| | | 📁 public
| | | 📁 src
| | | | 📁 assets
| | | | 📁 comopnents
| | | | 📁 mui
| | | | 📁 stories
| | | | 📁 types
| | | | index.ts
| | | | App.css
| | | | App.tsx
| | | | App.css
| | | package.json
| | | postcss.config.js
| | | readme.md
| | | tsconfig.json
| | | vite.config.ts
| | 📁 eslint-config
| | 📁 i18n
| | 📁 prettier-config
| | 📁 queries
| | | 📁 src
| | | | 📁 generated
| | | | exceptions.ts
| | | | index.ts
| | | | request-client.ts
| | | | request.hbs
| | | .eslintignore
| | | .eslintrc.cjs
| | | package.json
| | | tsconfig.json
| | 📁 typescript-config
| .dockerignore
| .eslintrc.js
| .npmrc
| .nvmrc
| .prettierrc.json
| Dockerfile
| Makefile
| package-lock.json
| package.json
| readme.md
| tsconfig.json
| turbo.json
В связи с представленной структурой проекта можно вывести правила названия файлов, а также содержащих их классов и других сущностей.
- Название файлов
Название компонентов tsx назвается в нотации CamelCase:
Название компонентов ts пишется в нотации kebab-case:
- Постфикс
В папках, которые однозначно определяют сущность, например, queries, providers
и т.д.
Запуск приложения в режиме разработки¶
Принципы Solid¶
- S — принцип единственной ответственности (Single Responsibility Principle). Каждый класс или модуль должен иметь одну и только одну причину для изменения, то есть отвечать за выполнение лишь одной определённой функциональности.
- O — принцип открытости/закрытости (Open/Closed Principle). Программные сущности должны быть открыты для расширения, но закрыты для изменения.
- L — Принцип подстановки Лисков (Liskov Substitution Principle). Объекты должны быть заменяемы экземплярами их подтипов без нарушения корректности работы программы.
- I — Принцип разделения интерфейса (Interface Segregation Principle). Не следует заставлять клиентов зависеть от интерфейсов, которые они не используют.
- D — Принцип инверсии зависимостей (Dependency Inversion Principle). Модули верхнего уровня не должны зависеть от модулей нижнего уровня; оба должны зависеть от абстракций.
Применение принципов SOLID способствует созданию устойчивой, масштабируемой и легко поддерживаемой программной системы, что особенно важно в условиях динамично меняющихся требований и технологий.
Feature Oriented подход¶
Текущий подход можно назвать feature oriented, однако в кажой feature реализован
подход fsd.
В папке проекта, например, {{ project name }}/apps/portalсоздается дирректория
modules, которая представляет из себя набор модулей, слабо связанных, которые должны быть независимы. Типовая схема модуля выглядит следующим образом:
📁 modules
| 📁 common
| | 📁 widgets
| | | 📁 comopnents
| | | | index.ts
| | | | AppToolBar.tsx
| | | | AppSideBar.tsx
| | | 📁 hooks
| | | | index.ts
| | | 📁 queries
| | | | index.ts
| | | | notification.ts
| | | 📁 mutations
| | | | index.ts
| | | | read-notifications.ts
| | | | delete-notifications.ts
| | | index.ts
| | | types.ts
| | 📁 features
| | | 📁 comopnents
| | | | index.ts
| | | | Notification.tsx
| | | 📁 queries
| | | | index.ts
| | | | notification.ts
| | | 📁 mutations
| | | | index.ts
| | | | read-notifications.ts
| | | | delete-notifications.ts
| | | index.ts
| | | types.ts
| | | utils.ts
В примере представлен пример модуля common, модуль, который предподалагает,
что его модули могут использоваться на всем сайте. Основные сущности модулей
следующие:
- widgets - объединения функционала, связанного с конкретной областью приложения, и обеспечивают его отображение;
- features - это минимальная, независимая единица функционала для совершения действия;
- entities - это минимальная единица, которая изолирует бизнес-логику и данные от внешнего интерфейса.
Правило использования иерархии остается также, как и в fsd: - widgets; - features; - entities.
Аналогичному shared слою методологии fsd служит раздел packages проекта, основанного на
монорепе turborepo.
Каждый из сервисов может содержать следующие компоненты: - components - компоненты модуля, каждый из которых содержит один компонент; - queries - список react-query запросов; - mutations - список reqct-query мутаций; - hooks - реализация кастомных хуков; - utils - описание утилит предметной области, тех, в которых нет нужды в других модулях.
Правила импорта¶
Импорты packages¶
Дирректория packages представляет собой shared слой всего приложения.
Из этого следует, что:
- внутри пакета импорт должен быть относительный,
- вну пакета импорт должен быть абсолютный и имплементировать только
доступные кспортные сущности.
Импорты modules¶
Внутри каждого модуля лежат доменные области, а внутри доменных областей лежат сущности, аналогичные сущностям методологии fsd. Из чего следует правило: - импорт доменных областей должен быть относительный; - импорт из вне текущих доменных областей должен быть абсолютный.
Импорт между модулями не запрещен, однако, должен быть абсолютный и подчиняется правилам импорта как и внутри модуля, например: - в модуле users сущность фичи users/features может экспортировать модуль common/features и common/entities, однако не может импортировать common/widgets; - в модуле users сущность entities можнт экспортировать только сущность common/entities.
Стили¶
Основной набор стилей наследуется путем указания темы из библиотеки MUI 6+](https://mui.com).
Нативное преопределение стилей¶
CSS Modules¶
Никаких других способов преопределения стилей, включая styled-components непридусмотрено.