Введение
В этой небольшой статье мне бы хотелось рассказать о такой концепции как Layers в Nuxt 3, как её реализовываю я в своих проектах и почему я считаю это важным. Я покажу два примера: один демонстрирует разделение проекта на несколько слоев, а другой – разделение нескольких фронтендов по разным слоям. Желание написать статью об этом возникло после того как я не нашёл достаточное количество реальных примеров и статей на русском языке по использованию слоев.
Проблема, которая привела меня к Layers
Изначально я знал о концепции Layers в Nuxt 3, но не использовал её, считая излишней и не особо понятной. Но однажды, обнаружив себя копающимся в папке components
, в которой было не менее шести подпапок, каждая с 10-30 компонентами, я понял, что что-то явно пошло не так. Я решил разбить свой проект на несколько слоев, но так чтобы избежать зависимости одного слоя от другого. Спустя некоторое время я пришёл к такой структуре:
Base: В этом слое находятся общие компоненты сайта, такие как шапка, футер, лэйауты, композаблы и утилиты, используемые по всему проекту, а так же главная страница, страница пользовательского соглашения и т.д.
User: Слой, отвечающий за работу с авторизацией, профилем пользователя и всем, что касается пользователя напрямую.
Order: Всё, что касается заказов на сайте: страница создания заказов, список заказов пользователя, список всех заказов на сайте и т.д.
Chat: Страница чата между пользователями. На этом же слое реализована логика работы с вебсокетом.
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