# Слои (layers)

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

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

## `getLayerDirectories`

Возвращает массив структур с абсолютными путями каталогов для каждого слоя приложения — стабильный API вместо `nuxt.options._layers`.

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

```tstwoslash
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}`)
      // ... другие каталоги
    }
  },
})
```

### Тип

```tstwoslash
// @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**: разрешённые пути каталогов для слоя.

<table>
<thead>
  <tr>
    <th>
      Свойство
    </th>
    
    <th>
      Тип
    </th>
    
    <th>
      Описание
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        root
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Корень слоя (аналог <code>
        rootDir
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        server
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Каталог сервера Nitro
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        modules
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Локальный каталог модулей
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        shared
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Общий каталог для клиента и сервера
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        app
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Исходный каталог слоя (аналог <code>
        srcDir
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        public
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Публичный каталог статики
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        appLayouts
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Каталог лейаутов Vue
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        appMiddleware
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Каталог route middleware
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        appPages
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Каталог страниц (маршрутизация по файлам)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        appPlugins
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Каталог плагинов Nuxt
    </td>
  </tr>
</tbody>
</table>

### Примеры

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

```tstwoslash
// @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)
    }
  },
})
```

**Шаблоны из нескольких слоёв:**

```tstwoslash
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,
        })
      }
    }
  },
})
```

**С учётом приоритета слоёв:**

```tstwoslash
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)
      }
    }
  },
})
```

**Проверка каталогов в слоях:**

```tstwoslash
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}`)
  },
})
```

<note>

`getLayerDirectories` кэширует результат в `WeakMap`, повторные вызовы с тем же `nuxt` не пересчитывают пути.

</note>

<note>

Возвращаемые пути всегда с завершающим слэшем.

</note>

<style>

html pre.shiki code .s8R28, html code.shiki .s8R28{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sDfIl, html code.shiki .sDfIl{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sZSNi, html code.shiki .sZSNi{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sGFVr, html code.shiki .sGFVr{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}html pre.shiki code .s3cPz, html code.shiki .s3cPz{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .sRlkE, html code.shiki .sRlkE{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .smZ93, html code.shiki .smZ93{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .sWuyu, html code.shiki .sWuyu{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s1nJG, html code.shiki .s1nJG{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .s52Pk, html code.shiki .s52Pk{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}html pre.shiki code .sbKd-, html code.shiki .sbKd-{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}html pre.shiki code .sYRBq, html code.shiki .sYRBq{--shiki-light:#F76D47;--shiki-default:#F76D47;--shiki-dark:#F78C6C}

</style>

---

- [Исходный код](https://github.com/nuxt/nuxt/blob/main/packages/kit/src/layers.ts)
