Работа со слоями в Nuxt 3

eae750723daf8fdf608f57f8eff44700

Введение

В этой небольшой статье мне бы хотелось рассказать о такой концепции как Layers в Nuxt 3, как её реализовываю я в своих проектах и почему я считаю это важным. Я покажу два примера: один демонстрирует разделение проекта на несколько слоев, а другой — разделение нескольких фронтендов по разным слоям. Желание написать статью об этом возникло после того как я не нашёл достаточное количество реальных примеров и статей на русском языке по использованию слоев.

Проблема, которая привела меня к Layers

Изначально я знал о концепции Layers в Nuxt 3, но не использовал её, считая излишней и не особо понятной. Но однажды, обнаружив себя копающимся в папке components, в которой было не менее шести подпапок, каждая с 10–30 компонентами, я понял, что что-то явно пошло не так. Я решил разбить свой проект на несколько слоев, но так чтобы избежать зависимости одного слоя от другого. Спустя некоторое время я пришёл к такой структуре:

  1. Base: В этом слое находятся общие компоненты сайта, такие как шапка, футер, лэйауты, композаблы и утилиты, используемые по всему проекту, а так же главная страница, страница пользовательского соглашения и т.д.

  2. User: Слой, отвечающий за работу с авторизацией, профилем пользователя и всем, что касается пользователя напрямую.

  3. Order: Всё, что касается заказов на сайте: страница создания заказов, список заказов пользователя, список всех заказов на сайте и т.д.

  4. Chat: Страница чата между пользователями. На этом же слое реализована логика работы с вебсокетом.

  5. UI: Из-за разросшегося Base слоя было принято решение вынести все UI компоненты в отдельный слой. Он нужен для того, чтобы 20 компонентов, касающихся форм, модальных окон и карточек, не засоряли базовый слой, в котором находятся более глобальные части и страницы приложения.

Главные преимущества, которые я ощутил при использовании такого подхода, это, во-первых, удобство работы над конкретной частью приложения. Если мне нужно обновить авторизацию, я не ищу компоненты/страницы/компосаблы по всему проекту, а иду к определённому слою и работаю исключительно в нём, не затрагивая остальные. Во-вторых, каждому слою можно прописать свою конфигурацию.

Cтруктура проекта:

├── layers/
│   ├── base/
│   │   ├── assets/
│   │   │   ├── fonts/
│   │   │   └── styles/
│   │   ├── components/
│   │   ├── composables/
│   │   ├── pages/
│   │   ├── stores/
│   │   ├── utils/
│   │   └── nuxt.config.ts
│   ├── chat/
│   │   ├── components/
│   │   ├── composables/
│   │   ├── pages/
│   │   ├── stores/
│   │   └── nuxt.config.ts
│   ├── order/
│   │   ├── components/
│   │   ├── pages/
│   │   ├── stores/
│   │   ├── specialist/
│   │   └── support/
│   ├── ui/
│   │   ├── components/
│   │   └── nuxt.config.ts
│   └── user/
│       ├── components/
│       ├── composables/
│       ├── middleware/
│       ├── pages/
│       ├── stores/
│       └── nuxt.config.ts
├── app.vue
├── error.vue
├── nuxt.config.ts
└── tsconfig.json

В главном nuxt.config.ts файле у меня прописано следующее:

extends: [
  "./layers/base",
  "./layers/ui",
  "./layers/order",
  "./layers/user",
  "./layers/chat"
],

// Исключительно для удобства при импортировании
alias: {
  "@": "./",
  base: "~/layers/base",
  ui: "~/layers/ui",
  order: "~/layers/order",
  user: "~/layers/user",
  chat: "~/layers/chat",
}

Проблема с которой я столкнулся

Если в двух разных слоях есть компонент с одинаковым названием, то в автоимпорт попадет только один. Это создаёт опасность случайно назвать компонент точно так же, как в другом слое, и не понять, почему всё работает неправильно. В попытках найти решение проблемы я решил отключить автоимпорт во всех слоях, но чтобы не терять преимущество от использования автоимпорта, я сделал в каждом слое внутри папки components папку global. Из неё все компоненты доступны для автоимпорта по всему приложению, а компоненты вне этой папки необходимо импортировать напрямую. Чтобы реализовать такую логику в каждом внутреннем nuxt.config.ts нужно прописать следующее:

components: [
  {
    path: "~/layers/base/components/global",
    pathPrefix: false,
    global: true
  }
]

Несколько сайтов на базе одного API

Перед нашей командой стояла задача сделать несколько сайтов, которые бы обращались к одному API, имели бы общие компоненты, композаблы и утилиты. Реализовать подобное решили через Layers, где каждый слой — отдельный сайт.
Структура следующая:

├── composables/
├── components/
├── services/
├── layers/
│   ├── site-1/
│   ├── site-2/
│   └── site-3/

В .env файле есть параметр, отвечающий за текущий сайт, например VITE_NUXT_LAYER=site-1. Он нужен для того чтобы в nuxt.config.ts прописать путь к необходимому сайту:

extends: ["./layers/" + import.meta.env.VITE_NUXT_LAYER]

После этого каждый разработчик прописывает необходимое ему название сайта и занимается разработкой исключительно внутри одного слоя, не затрагивая работу других.

Заключение

Использование Layers в Nuxt 3 позволяет значительно улучшить структуру и управляемость крупными проектами. Разделение на слои помогает избежать излишних зависимостей и облегчает работу над отдельными частями приложения.

Полезные ссылки

Документация Layers Nuxt

© Habrahabr.ru