Авторство слоёв Nuxt
Слои Nuxt — мощный инструмент для совместного использования и повторного применения частей Nuxt-приложения в монорепозитории, из git-репозитория или npm-пакета. Структура слоя почти совпадает со структурой обычного Nuxt-приложения, поэтому их удобно писать и поддерживать.
Минимальная директория слоя Nuxt должна содержать файл nuxt.config.ts, чтобы Nuxt распознал её как слой.
export default defineNuxtConfig({})
Кроме того, отдельные другие файлы в директории слоя автоматически сканируются и подключаются Nuxt для проекта, который расширяет этот слой.
app/components/*— расширяют компоненты по умолчаниюapp/composables/*— расширяют композаблы по умолчаниюapp/layouts/*— расширяют макеты по умолчаниюapp/middleware/*— расширяют middleware по умолчаниюapp/pages/*— расширяют страницы по умолчаниюapp/plugins/*— расширяют плагины по умолчаниюapp/utils/*— расширяют утилиты по умолчаниюapp/app.config.ts— расширяют конфиг приложения по умолчаниюserver/*— расширяют серверные эндпоинты и middleware по умолчаниюnuxt.config.ts- расширяют конфиг Nuxt по умолчанию
Базовый пример
export default defineNuxtConfig({
extends: [
'./base',
],
})
Приоритет слоёв
При расширении нескольких слоёв важно понимать порядок переопределения. Слои с более высоким приоритетом переопределяют слои с более низким приоритетом, если они задают одни и те же файлы или компоненты.
Порядок приоритета от высшего к низшему:
- Файлы вашего проекта — всегда самый высокий приоритет
- Автосканируемые слои из каталога
~~/layers— сортируются по алфавиту (Z выше, чем A) - Слои в конфиге
extends— первая запись имеет более высокий приоритет, чем вторая
Когда что использовать
extends— для внешних зависимостей (npm-пакеты, удалённые репозитории) или слоёв вне каталога проекта- Каталог
~~/layers— для локальных слоёв, которые являются частью проекта
~/layers/1.z-layer, ~/layers/2.a-layer. Тогда 2.a-layer будет иметь более высокий приоритет, чем 1.z-layer.Пример
export default defineNuxtConfig({
extends: [
// Локальный слой вне проекта
'../base',
// NPM-пакет
'@my-themes/awesome',
// Удалённый репозиторий
'github:my-themes/awesome#v1',
],
})
Если у вас также есть ~~/layers/custom, порядок приоритета такой:
- Файлы проекта (высший)
~~/layers/custom../base@my-themes/awesomegithub:my-themes/awesome#v1(низший)
То есть файлы проекта переопределяют любой слой, а ~~/layers/custom переопределяет всё, что указано в extends.
Стартовый шаблон
Чтобы начать, можно инициализировать слой по шаблону nuxt/starter/layer. Получится базовая структура для дальнейшей работы. Выполните в терминале:
npm create nuxt -- --template layer nuxt-layer
Дальше следуйте инструкциям в README.
Публикация слоёв
Публиковать и делиться слоями можно через удалённый источник или npm-пакет.
Git-репозиторий
Слой Nuxt можно вынести в git-репозиторий. Примеры:
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> с токеном доступа.GIGET_GITHUB_URL=<url> или GIGET_GITLAB_URL=<url> — либо настройте напрямую опцией auth в nuxt.config.node_modules/.c12/layer_name/node_modules/), куда менеджер пакетов проекта не смотрит.install: true в опциях слоя.export default defineNuxtConfig({
extends: [
['github:username/repoName', { install: true }],
],
})
npm-пакет
Слой Nuxt можно опубликовать как npm-пакет с нужными файлами и зависимостями — так проще делиться конфигом, использовать в нескольких проектах или держать приватно.
Чтобы расширять конфиг из npm-пакета, модуль должен быть опубликован в npm и установлен в проекте как devDependency. Затем укажите имя модуля в extends:
export default defineNuxtConfig({
extends: [
// Node-модуль со scope
'@scope/moduleName',
// или просто имя модуля
'moduleName',
],
})
Чтобы опубликовать директорию слоя как npm-пакет, заполните в 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 — публично или приватно.
Советы
Именованные алиасы слоёв
У автосканируемых слоёв (из ~~/layers) автоматически появляются алиасы. Например, слой ~~/layers/test доступен как #layers/test.
Для других слоёв имя можно задать в конфигурации слоя.
export default defineNuxtConfig({
$meta: {
name: 'example',
},
})
Получится алиас #layers/example, указывающий на ваш слой.
Относительные пути и алиасы
При импорте через глобальные алиасы (~/, @/) в компонентах и композаблах слоя они разрешаются относительно путей проекта пользователя. Обходной путь — относительные импорты или именованные алиасы слоёв.
Относительные пути в nuxt.config слоя (кроме вложенных extends) тоже разрешаются относительно проекта пользователя, а не слоя. Используйте полные пути в nuxt.config:
import { fileURLToPath } from 'node:url'
import { dirname, join } from 'node:path'
const currentDir = dirname(fileURLToPath(import.meta.url))
export default defineNuxtConfig({
css: [
join(currentDir, './app/assets/main.css'),
],
})
Отключение модулей из слоёв
Расширяя слой, иногда нужно отключить входящие в него модули. Задайте для ключа конфигурации модуля значение false в конфиге Nuxt.
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.
import { defineNuxtModule, getLayerDirectories } from 'nuxt/kit'
export default defineNuxtModule({
setup (_options, nuxt) {
const layerDirs = getLayerDirectories()
for (const [index, layer] of layerDirs.entries()) {
console.log(`Layer ${index}:`)
console.log(` Root: ${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. Подробности — в документации и исходниках.