Введение
В этой небольшой статье мне бы хотелось рассказать о такой концепции как 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
