Создание авторских слоёв Nuxt

Nuxt предоставляет мощную систему, которая позволяет расширять файлы по умолчанию, конфигурации и многое другое.

Слои Nuxt — это мощная возможность, которую вы можете использовать для совместного использования и переиспользования частичных приложений Nuxt в монорепозитории или из git-репозитория или пакета npm. Структура слоёв практически идентична стандартному приложению Nuxt, что упрощает их создание и поддержку.

Узнать больше Docs > 3 X > Getting Started > Layers.

Базовая директория слоя Nuxt должна содержать файл nuxt.config.ts, указывающий на то, что это слой.

base/nuxt.config.ts
export default defineNuxtConfig({})

Кроме того, некоторые другие файлы в директории слоя будут автоматически сканироваться и использоваться Nuxt для проекта, расширяющего этот слой.

  • components/* — расширение компонентов по умолчанию
  • composables/* — расширение композаблов по умолчанию
  • layouts/* — расширение лейаутов по умолчанию
  • middleware/* — расширение middleware по умолчанию
  • pages/* — расширение страниц по умолчанию
  • plugins/* — расширение плагинов по умолчанию
  • utils/* — расширение утилит по умолчанию
  • app.config.ts — расширение конфигурации приложения по умолчанию
  • server/* — расширение серверных эндпоинтов и middleware по умолчанию
  • nuxt.config.ts — расширение конфигурации Nuxt по умолчанию

Базовый пример

nuxt.config.ts
export default defineNuxtConfig({
  extends: [
    './base',
  ],
})

Приоритет слоёв

При расширении из нескольких слоёв важно понимать порядок переопределения. Слои с более высоким приоритетом переопределяют слои с более низким приоритетом, если они задают одни и те же файлы или компоненты.

Порядок приоритета от большего к меньшему:

  1. Файлы вашего проекта — всегда самый высокий приоритет
  2. Автосканируемые слои из каталога ~~/layers — сортировка по алфавиту (Z выше, чем A)
  3. Слои в конфиге extends — первый элемент важнее второго

Когда что использовать

  • extends — для внешних зависимостей (npm-пакеты, удалённые репозитории) или слоёв вне каталога проекта
  • каталог ~~/layers — для локальных слоёв, которые являются частью проекта
Если нужно задать порядок автосканируемых слоёв, добавьте префиксы с номерами: ~/layers/1.z-layer, ~/layers/2.a-layer. Тогда 2.a-layer будет иметь приоритет выше, чем 1.z-layer.

Пример

nuxt.config.ts
export default defineNuxtConfig({
  extends: [
    // Локальный слой вне проекта
    '../base',
    // NPM-пакет
    '@my-themes/awesome',
    // Удалённый репозиторий
    'github:my-themes/awesome#v1',
  ],
})

Если у вас также есть ~~/layers/custom, порядок приоритета такой:

  • файлы проекта (наивысший)
  • ~~/layers/custom
  • ../base
  • @my-themes/awesome
  • github:my-themes/awesome#v1 (наинизший)

То есть файлы проекта переопределяют любой слой, а ~~/layers/custom переопределяет всё, что указано в extends.

Начальный шаблон

Для начала вы можете инициализировать слой с помощью шаблона nuxt/starter/layer. Это создаст базовую структуру, на которую вы сможете опираться. Выполните в терминале:

Terminal
npm create nuxt -- --template layer nuxt-layer

Следуйте инструкциям в README для следующих шагов.

Публикация слоёв

Вы можете публиковать и делиться слоями, используя либо удалённый источник, либо npm-пакет.

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

Вы можете использовать git-репозиторий, чтобы поделиться своим слоем Nuxt. Некоторые примеры:

nuxt.config.ts
export default defineNuxtConfig({
  extends: [
    // Удалённый источник GitHub
    'github:username/repoName',
    // Удалённый источник GitHub в каталоге /base
    'github:username/repoName/base',
    // Удалённый источник GitHub из ветки dev
    'github:username/repoName#dev',
    // Удалённый источник GitHub с тегом v1.0.0
    'github:username/repoName#v1.0.0',
    // Пример удалённого источника GitLab
    'gitlab:username/repoName',
    // Пример удалённого источника Bitbucket
    'bitbucket:username/repoName',
  ],
})
Если вы хотите расширить приватный удалённый источник, добавьте переменную окружения GIGET_AUTH=<token> с токеном доступа.
Если вы хотите расширить удалённый источник из самостоятельно размещённого экземпляра GitHub или GitLab, укажите его URL через переменные окружения GIGET_GITHUB_URL=<url> или GIGET_GITLAB_URL=<url> — или настройте напрямую опцию auth в nuxt.config.
Имейте в виду: если вы подключаете удалённый источник как слой, вы не сможете использовать его зависимости вне Nuxt. Например, если удалённый слой тянет плагин для eslint, тот не появится в вашей конфигурации eslint. Это потому, что такие зависимости оказываются в отдельном месте (node_modules/.c12/layer_name/node_modules/), куда ваш менеджер пакетов не смотрит.
При использовании удалённых git-источников, если у слоя есть npm-зависимости и их нужно установить, укажите install: true в опциях слоя.
nuxt.config.ts
export default defineNuxtConfig({
  extends: [
    ['github:username/repoName', { install: true }],
  ],
})

Пакет npm

Вы можете опубликовать слои Nuxt в виде npm-пакета с файлами и зависимостями, которые хотите расширить. Это позволит поделиться конфигурацией, использовать её в нескольких проектах или приватно.

Для расширения из npm-пакета убедитесь, что модуль опубликован в npm и установлен в проекте пользователя как devDependency. Затем используйте имя модуля в extends:

nuxt.config.ts
export default defineNuxtConfig({
  extends: [
    // scoped-пакет npm
    '@scope/moduleName',
    // или просто имя модуля
    'moduleName',
  ],
})

Чтобы опубликовать каталог слоя как npm-пакет, заполните в package.json нужные поля — так файлы попадут в публикацию.

package.json
{
  "name": "my-theme",
  "version": "1.0.0",
  "type": "module",
  "main": "./nuxt.config.ts",
  "dependencies": {},
  "devDependencies": {
    "nuxt": "^3.0.0"
  }
}
Убедитесь, что любая зависимость, импортируемая в слой, явно добавлена в dependencies. Зависимость nuxt и всё, что нужно только для тестирования слоя до публикации, оставьте в devDependencies.

Далее опубликуйте модуль в npm — публично или приватно.

При публикации слоя как приватного npm-пакета войдите в аккаунт npm для аутентификации и загрузки модуля.

Советы

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

Автосканируемые слои (из ~~/layers) получают алиасы автоматически. Например, слой ~~/layers/test доступен как #layers/test.

Для остальных слоёв можно задать имя в конфигурации самого слоя:

nuxt.config.ts
export default defineNuxtConfig({
  $meta: {
    name: 'example',
  },
})

Появится алиас #layers/example, указывающий на этот слой.

Относительные пути и алиасы

При импорте через глобальные алиасы (~/, @/ и т.п.) в компонентах и композаблах слоя помните: они разрешаются относительно проекта пользователя, а не слоя. Обходной путь — относительные пути или именованные алиасы слоёв.

Также относительные пути в nuxt.config слоя (кроме вложенных extends) разрешаются относительно проекта пользователя, а не слоя. Используйте полностью разрешённые пути в nuxt.config:

nuxt.config.ts
import { fileURLToPath } from 'node:url'
import { dirname, join } from 'node:path'

const currentDir = dirname(fileURLToPath(import.meta.url))

export default defineNuxtConfig({
  css: [
    join(currentDir, './assets/main.css'),
  ],
})

Отключение модулей из слоёв

Расширяя слой, вы можете отключить входящие в него модули: задайте для ключа конфигурации модуля значение false в своём nuxt.config.

nuxt.config.ts
export default defineNuxtConfig({
  extends: ['./base-layer'],
  // Отключение модулей слоя через ключ конфигурации false
  image: false, // отключает @nuxt/image
  pinia: false, // отключает @pinia/nuxt
})
Ключ задаётся каждым модулем. Частые примеры: image для @nuxt/image, pinia для @pinia/nuxt, content для @nuxt/content. Смотрите документацию модуля.

Полезно, когда:

  • в слое есть модули, которые вам не нужны
  • вы хотите другую реализацию, чем в слое
  • нужно отключить аналитику или другие модули в отдельных окружениях
Так же можно отключать модули в своём проекте, не только из слоёв. Ключ false останавливает выполнение setup модуля, но типы для модуля по-прежнему генерируются.

Многослойная поддержка модулей Nuxt

Используйте утилиту getLayerDirectories из Nuxt Kit для своей логики работы со слоями.

modules/my-module.ts
import { defineNuxtModule, getLayerDirectories } from 'nuxt/kit'

export default defineNuxtModule({
  setup (_options, nuxt) {
    const layerDirs = getLayerDirectories()

    for (const [index, layer] of layerDirs.entries()) {
      console.log(`Слой ${index}:`)
      console.log(`  Корень: ${layer.root}`)
      console.log(`  App: ${layer.app}`)
      console.log(`  Server: ${layer.server}`)
      console.log(`  Pages: ${layer.appPages}`)
      // ... другие каталоги
    }
  },
})

Примечания:

  • более ранние элементы массива имеют более высокий приоритет и переопределяют более поздние
  • проект пользователя — первый элемент массива

Углубляясь в тему

Загрузка конфигурации и extends обеспечиваются unjs/c12, слияние — unjs/defu, удалённые git-источники — unjs/giget. Подробнее — в документации и исходниках пакетов.

Следите за текущей разработкой улучшений поддержки слоёв на GitHub.