Слои (layers)

Исходный код
Утилиты Nuxt Kit для слоёв и разрешённых путей к их каталогам.

Слои Nuxt переиспользуют и наращивают код между проектами. В модулях часто нужны абсолютные пути каталогов каждого слоя — для этого служит getLayerDirectories.

getLayerDirectories

Возвращает массив структур с абсолютными путями каталогов для каждого слоя приложения — стабильный API вместо 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(`Слой ${index}:`)
      console.log(`  Корень: ${layer.root}`)
      console.log(`  Приложение: ${layer.app}`)
      console.log(`  Сервер: ${layer.server}`)
      console.log(`  Страницы: ${layer.appPages}`)
      // ... другие каталоги
    }
  },
})

Тип

// @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
  /** Каталог лейаутов (по умолчанию `/layouts`) */
  readonly appLayouts: string
  /** Каталог прослоек маршрутов (по умолчанию `/middleware`) */
  readonly appMiddleware: string
  /** Каталог страниц (по умолчанию `/pages`) */
  readonly appPages: string
  /** Каталог плагинов (по умолчанию `/plugins`) */
  readonly appPlugins: string
}

Параметры

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

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

Функция возвращает массив объектов LayerDirectories — по одному на каждый слой.

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

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

Это совпадает с тем, как Nuxt накладывает слои: файлы и настройки проекта имеют приоритет над базовыми слоями.

LayerDirectories: разрешённые пути каталогов для слоя.

СвойствоТипОписание
rootstringКорень слоя (аналог rootDir)
serverstringКаталог сервера Nitro
modulesstringЛокальный каталог модулей
sharedstringОбщий каталог для клиента и сервера
appstringИсходный каталог слоя (аналог srcDir)
publicstringПубличный каталог статики
appLayoutsstringКаталог лейаутов Vue
appMiddlewarestringКаталог route 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()

    const layersWithAssets = layerDirs.filter((layer) => {
      return existsSync(resolve(layer.app, 'assets'))
    })

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