Навигация

Nuxt Layers: переиспользование конфигурации и кода между проектами

Nuxt Layers — механизм для переиспользования компонентов, composables, middleware, серверных роутов и конфигурации между проектами. В отличие от модулей, layers имеют структуру, идентичную обычному Nuxt-приложению, что делает их простыми в создании и сопровождении. Этот механизм особенно полезен для монорепозиториев, тем, библиотек компонентов и шаблонов проектов.

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

Содержание

  1. Что такое Nuxt Layers
  2. Структура layer
  3. Подключение layers
  4. Наследование и приоритеты
  5. Именованные алиасы layers
  6. Переопределение конфигурации
  7. Паттерны использования
  8. Layers vs Modules
  9. Лучшие практики и антипаттерны
  10. Ключевые тезисы для интервью
  11. Заключение
  12. Полезные ссылки

Что такое Nuxt Layers

Nuxt Layers — это способ организации переиспользуемого кода в виде мини-приложений, которые подключаются к основному проекту через extends в nuxt.config.ts. Каждый layer имеет структуру, аналогичную обычному Nuxt-приложению: свои компоненты, composables, middleware, плагины, серверные роуты и конфигурацию.

Основные сценарии использования:

  • Переиспользование конфигурации (nuxt.config, app.config) между проектами.
  • Создание библиотек компонентов через директорию components/.
  • Построение утилит и composables через composables/ и utils/.
  • Формирование шаблонов проектов и тем.
  • Организация кода в монорепозиториях.

Структура layer

Минимальный layer — это директория с файлом nuxt.config.ts. Nuxt автоматически сканирует определённые директории и файлы, если они присутствуют в layer:

my-layer/
├── nuxt.config.ts      # Обязательный файл
├── components/         # Компоненты
├── composables/        # Composables
├── utils/              # Утилиты
├── layouts/            # Layouts
├── middleware/         # Middleware
├── pages/              # Страницы
├── plugins/            # Плагины
├── server/             # Серверные роуты и middleware
├── public/             # Статические файлы
└── app.config.ts       # Конфигурация приложения

Пример базового layer

// my-layer/nuxt.config.ts
export default defineNuxtConfig({})
<!-- my-layer/components/Button.vue -->
<template>
  <button class="layer-button">
    <slot />
  </button>
</template>

<style scoped>
.layer-button {
  padding: 8px 16px;
  border-radius: 4px;
  background: #3b82f6;
  color: white;
  border: none;
  cursor: pointer;
}
</style>
// my-layer/composables/useTheme.ts
export const useTheme = () => {
  const color = useState('theme-color', () => '#3b82f6');
  return { color };
};

Подключение layers

Локальные layers

Layers в директории ~/layers/ автоматически регистрируются начиная с Nuxt 3.12.0:

project/
├── layers/
│   ├── base/
│   │   └── nuxt.config.ts
│   └── theme/
│       └── nuxt.config.ts
├── nuxt.config.ts
└── pages/

Для подключения layer из другой директории используйте extends:

// nuxt.config.ts
export default defineNuxtConfig({
  extends: [
    './layers/base',
    '../shared-theme',
  ],
});

npm-пакеты

export default defineNuxtConfig({
  extends: [
    '@my-org/nuxt-layer',
    '@my-org/nuxt-admin-theme',
  ],
});

Git-репозитории

export default defineNuxtConfig({
  extends: [
    'github:my-org/my-theme',
    'github:my-org/my-theme#v1.0.0',
  ],
});

Для приватных репозиториев с токеном:

export default defineNuxtConfig({
  extends: [
    ['github:my-org/private-theme', { auth: process.env.GITHUB_TOKEN }],
  ],
});

Наследование и приоритеты

При подключении нескольких layers Nuxt объединяет их файлы с учётом приоритетов. Приоритет от наибольшего к наименьшему:

  1. Файлы проекта (наивысший приоритет)
  2. Layers в ~/layers/ (в алфавитном порядке)
  3. Layers из extends (в порядке объявления)

Пример конфликта компонентов

layers/
├── 1.base/
│   └── components/
│       └── Button.vue     # Базовый стиль
├── 2.theme/
│   └── components/
│       └── Button.vue     # Стиль темы (переопределяет base)
app/
└── components/
    └── Button.vue           # Проектный компонент (переопределяет всё)
  • Если есть только layers, используется 2.theme/Button.vue (выше по алфавиту).
  • Если Button.vue есть в проекте, он переопределяет все layers.

Именованные алиасы layers

Начиная с Nuxt 3.16.0, каждый layer в ~/layers/ получает именованный алиас через #layers/имя:

// Доступ к composables из слоя theme
import { useTheme } from '#layers/theme/composables/useTheme';
<script setup>
// Доступ к компонентам из слоя base
import BaseButton from '#layers/base/components/Button.vue';
</script>

Алиасы упрощают обращение к конкретным слоям, особенно когда в проекте подключено несколько layers с похожими файлами.


Переопределение конфигурации

Layers могут расширять и переопределять конфигурацию проекта.

Расширение nuxt.config

Layer может добавить свой заголовок, мета-теги или настройки:

// my-theme/nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      title: 'My Theme',
      meta: [
        { name: 'description', content: 'Nuxt theme with custom styling' },
      ],
    },
  },
  css: ['~/assets/css/theme.css'],
});

Расширение app.config

// my-theme/app.config.ts
export default defineAppConfig({
  ui: {
    primary: '#3b82f6',
    borderRadius: '8px',
  },
});
// nuxt.config.ts — переопределение значений из layer
export default defineNuxtConfig({
  extends: ['./my-theme'],
  appConfig: {
    ui: {
      primary: '#10b981', // Переопределяет цвет из layer
    },
  },
});

Отключение модулей из layer

export default defineNuxtConfig({
  extends: ['./my-theme'],
  // Отключаем модуль, который подключил layer
  modules: [],
  // Или переопределяем конфиг модуля
  image: {
    quality: 80,
  },
});

Паттерны использования

Библиотека компонентов

Создайте layer с готовыми компонентами и используйте его в нескольких проектах:

ui-lib/
├── nuxt.config.ts
├── components/
│   ├── Button.vue
│   ├── Modal.vue
│   └── Card.vue
└── composables/
    └── useModal.ts

Тема для приложения

Layer может содержать layouts, стили и компоненты для оформления:

admin-theme/
├── nuxt.config.ts
├── layouts/
│   └── default.vue
├── components/
│   ├── Sidebar.vue
│   └── Header.vue
├── assets/
│   └── css/
│       └── admin.css
└── middleware/
    └── auth.ts

Монорепозиторий с общим кодом

monorepo/
├── packages/
│   ├── shared-nuxt-layer/
│   │   ├── nuxt.config.ts
│   │   ├── composables/
│   │   └── components/
│   ├── app-1/
│   │   ├── nuxt.config.ts   # extends: ['../packages/shared-nuxt-layer']
│   │   └── pages/
│   └── app-2/
│       ├── nuxt.config.ts   # extends: ['../packages/shared-nuxt-layer']
│       └── pages/
└── package.json

Layers vs Modules

КритерийLayersModules
СтруктураИдентична Nuxt-приложениюПрограмматический API
Подключениеextends в nuxt.configmodules в nuxt.config
СкоупФайлы и директорииХуки и API модулей
ПереопределениеАвтоматическое через приоритетРучное через API
ИспользованиеБиблиотеки, темы, шаблоныРасширение функционала Nuxt
СложностьНизкаяСредняя–высокая

Layers подходят для переиспользования файлов (компоненты, страницы, стили). Modules — для программного расширения возможностей Nuxt (добавление хуков, генерация файлов, интеграция с сервисами).


Лучшие практики и антипаттерны

✅ Делайте

  • Храните переиспользуемые компоненты и composables в отдельных layers.
  • Используйте app.config для конфигурации тем и стилей, чтобы проекты могли переопределять значения.
  • Задавайте имена слоям через meta.name для удобства в логах и отладке.
  • Используйте #layers/имя для явного обращения к конкретному layer.
  • Тестируйте layer изолированно перед подключением к проекту.
  • В документации layer указывайте, какие файлы и конфигурации он предоставляет.

❌ Не делайте

  • Не размещайте бизнес-логику проекта в layer — layer должен быть переиспользуемым.
  • Не полагайтесь на алиасы ~/ и @/ внутри layer — они резолвятся относительно проекта, а не layer. Используйте относительные импорты или #layers/имя.
  • Не создавайте глубокую вложенность layers — это затрудняет понимание приоритетов.
  • Не подключайте один и тот же layer несколько раз — это приведёт к дублированию кода.
  • Не переопределяйте файлы layer напрямую — вместо этого создайте файл с тем же именем в проекте.

Ключевые тезисы для интервью

  • Nuxt Layers — механизм переиспользования компонентов, composables, middleware и конфигурации между проектами.
  • Структура layer идентична Nuxt-приложению: components/, composables/, pages/, server/, layouts/, middleware/, plugins/, app.config.ts.
  • Подключение через extends в nuxt.config.ts или автоматически из ~/layers/.
  • Приоритет: проект > ~/layers/ (алфавитно) > extends (по порядку объявления).
  • Именованные алиасы #layers/имя (с Nuxt 3.16.0) позволяют явно обращаться к конкретному layer.
  • Layers могут подключаться из локальных директорий, npm-пакетов и git-репозиториев.
  • app.config в layer расширяется проектом, что удобно для тем и конфигурации стилей.
  • Layers vs Modules: layers — для файлов и структуры, modules — для программного расширения Nuxt.
  • Слой должен быть самодостаточным и переиспользуемым — без привязки к конкретному проекту.
  • Алиасы ~/ и @/ внутри layer резолвятся относительно проекта, а не source-директории layer.

Заключение

Nuxt Layers — это элегантное решение для переиспользования кода между проектами. Они позволяют создавать библиотеки компонентов, темы и шаблоны с минимальным количеством boilerplate. Понимание приоритетов наследования, правильное использование алиасов и разделение ответственности между layers и modules — ключ к масштабируемой архитектуре Nuxt-приложений.

Начните с выделения общих компонентов и composables в отдельный layer, подключите его к нескольким проектам и убедитесь, что переопределение конфигурации работает через app.config. Это первый шаг к единообразию и поддерживаемости кодовой базы.


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