Слои

Исходники
Утилиты для работы со слоями и их структурой директорий.

Слои Nuxt позволяют переиспользовать и расширять функциональность между проектами. В модулях часто нужны пути к каталогам каждого слоя. Утилита getLayerDirectories возвращает разрешённые пути для всех слоёв приложения.

getLayerDirectories

Возвращает разрешённые пути каталогов для всех слоёв. Удобная замена прямого доступа к nuxt.options._layers.

Использование

import { defineNuxtModule, getLayerDirectories } from '@nuxt/kit'

export default defineNuxtModule({
  setup () {
    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}`)
      // ... other directories
    }
  },
})

Тип

// @errors: 2391
import type { Nuxt } from '@nuxt/schema'
// ---cut---
function getLayerDirectories (nuxt?: Nuxt): LayerDirectories[]

interface LayerDirectories {
  /** Nuxt rootDir (по умолчанию `/`) */
  readonly root: string
  /** Исходный каталог Nitro (по умолчанию `/server`) */
  readonly server: string
  /** Локальные модули (по умолчанию `/modules`) */
  readonly modules: string
  /** Общий код (по умолчанию `/shared`) */
  readonly shared: string
  /** Публичные файлы (по умолчанию `/public`) */
  readonly public: string
  /** Nuxt srcDir (по умолчанию `/app/`) */
  readonly app: string
  /** Макеты (по умолчанию `/app/layouts`) */
  readonly appLayouts: string
  /** Middleware (по умолчанию `/app/middleware`) */
  readonly appMiddleware: string
  /** Страницы (по умолчанию `/app/pages`) */
  readonly appPages: string
  /** Плагины (по умолчанию `/app/plugins`) */
  readonly appPlugins: string
}

Параметры

nuxt (опционально): экземпляр Nuxt. Если не передан — используется текущий контекст.

Возвращаемое значение

Массив объектов LayerDirectories, по одному на каждый слой.

Порядок слоёв по приоритету:

  • Первый элемент — слой пользователя/проекта (наивысший приоритет)
  • Более ранние слои в массиве переопределяют более поздние
  • Базовые слои идут в конце (наименьший приоритет)

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

LayerDirectories — объект с разрешёнными путями каталогов слоя:

СвойствоТипОписание
rootstringКорневой каталог слоя (rootDir)
serverstringСерверный каталог Nitro
modulesstringЛокальные модули
sharedstringОбщий код (клиент и сервер)
appstringИсходный каталог приложения (srcDir)
publicstringСтатические ресурсы
appLayoutsstringМакеты Vue
appMiddlewarestringRoute middleware
appPagesstringФайловая маршрутизация
appPluginsstringПлагины Nuxt

Примеры

Обработка файлов из всех слоёв:

// @errors: 2307
// ---cut---
import { defineNuxtModule, getLayerDirectories } from '@nuxt/kit'
import { resolve } from 'pathe'
import { globby } from 'globby'

export default defineNuxtModule({
  async setup () {
    const layerDirs = getLayerDirectories()

    // Поиск всех компонентов по слоям
    // layerDirs[0] — слой пользователя (наивысший приоритет)
    // дальше в массиве — более низкий приоритет
    const componentFiles = []
    for (const [index, layer] of layerDirs.entries()) {
      const files = await globby('**/*.vue', {
        cwd: resolve(layer.app, 'components'),
        absolute: true,
      })
      console.log(`Слой ${index} (${index === 0 ? 'пользователь' : 'базовый'}):`, files.length, 'компонентов')
      componentFiles.push(...files)
    }
  },
})

Добавление шаблонов из нескольких слоёв:

import { addTemplate, defineNuxtModule, getLayerDirectories } from '@nuxt/kit'
import { basename, resolve } from 'pathe'
import { existsSync } from 'node:fs'

export default defineNuxtModule({
  setup () {
    const layerDirs = getLayerDirectories()

    // Добавить конфиг из каждого слоя, где он есть
    for (const dirs of layerDirs) {
      const configPath = resolve(dirs.app, 'my-module.config.ts')
      if (existsSync(configPath)) {
        addTemplate({
          filename: `my-module-${basename(dirs.root)}.config.ts`,
          src: configPath,
        })
      }
    }
  },
})

Учёт приоритета слоёв:

import { defineNuxtModule, getLayerDirectories } from '@nuxt/kit'
import { resolve } from 'pathe'
import { existsSync, readFileSync } from 'node:fs'

export default defineNuxtModule({
  setup () {
    const layerDirs = getLayerDirectories()

    // Первый (наивысший приоритет) слой с нужным конфигом
    let configContent = null
    for (const dirs of layerDirs) {
      const configPath = resolve(dirs.app, 'my-config.json')
      if (existsSync(configPath)) {
        configContent = readFileSync(configPath, 'utf-8')
        console.log(`Используется конфиг слоя: ${dirs.root}`)
        break // берём первый найденный (наивысший приоритет)
      }
    }

    // Вариант: собрать конфиги из всех слоёв, слой пользователя переопределяет
    const allConfigs = {}
    for (const dirs of layerDirs.reverse()) { // от низшего к высшему приоритету
      const configPath = resolve(dirs.app, 'my-config.json')
      if (existsSync(configPath)) {
        const config = JSON.parse(readFileSync(configPath, 'utf-8'))
        Object.assign(allConfigs, config) // последующие перезаписывают предыдущие
      }
    }
  },
})

Проверка каталогов, специфичных для слоя:

import { defineNuxtModule, getLayerDirectories } from '@nuxt/kit'
import { existsSync } from 'node:fs'
import { resolve } from 'pathe'

export default defineNuxtModule({
  setup () {
    const layerDirs = getLayerDirectories()

    // Слои с кастомным каталогом assets
    const layersWithAssets = layerDirs.filter((layer) => {
      return existsSync(resolve(layer.app, 'assets'))
    })

    console.log(`Найдено ${layersWithAssets.length} слоёв с каталогом assets`)
  },
})
getLayerDirectories кэширует результат через WeakMap, чтобы не пересчитывать пути для одних и тех же слоёв при повторных вызовах.
Возвращаемые пути каталогов всегда с завершающим слэшем.