# Хуки и типы

> Хуки жизненного цикла, виртуальные файлы и объявления TypeScript в модулях.

Продвинутые приёмы: хуки, шаблоны и расширение типов.

## Хуки жизненного цикла

[Хуки](/docs/3.x/guide/going-further/hooks) позволяют вмешиваться почти во все этапы Nuxt. Модуль может подписаться через карту `hooks` или в `setup`.

```js
import { addPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  // Подписка на хук `app:error` через карту `hooks`
  hooks: {
    'app:error': (err) => {
      console.info(`Произошла ошибка: ${err}`)
    },
  },
  setup (options, nuxt) {
    // Программная подписка на хук `pages:extend`
    nuxt.hook('pages:extend', (pages) => {
      console.info(`Найдено страниц: ${pages.length}`)
    })
  },
})
```

<read-more to="/docs/3.x/api/advanced/hooks">



</read-more>

<tip icon="i-lucide-video" target="_blank" to="https://vueschool.io/lessons/nuxt-lifecycle-hooks?friend=nuxt">

Видео Vue School про хуки в модулях.

</tip>

<note>

**Очистка в модуле**

<br />

<br />

Если модуль открывает вотчеры или долгоживущие ресурсы, закройте их на `close`.

```ts
import { defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    nuxt.hook('close', async (nuxt) => {
      // Ваш код очистки здесь
    })
  },
})
```

</note>

### Свои хуки

Модуль может объявлять и вызывать собственные хуки — удобно для расширяемости.

Если другие модули должны подписаться, вызывайте хук в `modules:done`: к этому моменту они уже успели зарегистрировать слушатели в `setup`.

```ts
// пример: my-module/module.ts
import { defineNuxtModule } from '@nuxt/kit'

export interface ModuleHooks {
  'my-module:custom-hook': (payload: { foo: string }) => void
}

export default defineNuxtModule({
  setup (options, nuxt) {
    // Вызовите свой хук в `modules:done`
    nuxt.hook('modules:done', async () => {
      const payload = { foo: 'bar' }
      await nuxt.callHook('my-module:custom-hook', payload)
    })
  },
})
```

## Виртуальные файлы

Чтобы добавить виртуальный файл, импортируемый в приложении пользователя, используйте `addTemplate`.

```ts
import { addTemplate, defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    // Файл попадает во внутреннюю виртуальную ФС Nuxt; импорт из '#build/my-module-feature.mjs'
    addTemplate({
      filename: 'my-module-feature.mjs',
      getContents: () => 'export const myModuleFeature = () => "привет, мир!"',
    })
  },
})
```

Для сервера — `addServerTemplate`.

```ts
import { addServerTemplate, defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    // Файл в виртуальной ФС Nitro; в серверном коде — импорт из 'my-server-module.mjs'
    addServerTemplate({
      filename: 'my-server-module.mjs',
      getContents: () => 'export const myServerModule = () => "привет, мир!"',
    })
  },
})
```

## Обновление шаблонов

При изменении конфигурации виртуальных файлов вызывайте `updateTemplates`:

```ts
nuxt.hook('builder:watch', (event, path) => {
  if (path.includes('my-module-feature.config')) {
    // Перезагрузит зарегистрированный шаблон
    updateTemplates({ filter: t => t.filename === 'my-module-feature.mjs' })
  }
})
```

## Объявления типов

Чтобы добавить типы в проект пользователя (расширить интерфейсы Nuxt или объявить свои глобальные типы), используйте `addTypeTemplate`: шаблон попадает на диск и в ссылки генерируемого `nuxt.d.ts`.

Расширение типов Nitro:

```js
import { addTemplate, addTypeTemplate, defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    addTypeTemplate({
      filename: 'types/my-module.d.ts',
      getContents: () => `// Сгенерировано модулем my-module
        interface MyModuleNitroRules {
          myModule?: { foo: 'bar' }
        }
        declare module 'nitropack/types' {
          interface NitroRouteRules extends MyModuleNitroRules {}
          interface NitroRouteConfig extends MyModuleNitroRules {}
        }
        export {}`,
    })
  },
})
```

Тоньше — хук `prepare:types`:

```ts
const template = addTemplate({ /* параметры шаблона */ })
nuxt.hook('prepare:types', ({ references }) => {
  references.push({ path: template.dst })
})
```

## Расширение tsconfig

Проще всего править опции Nuxt:

```ts
// расширить tsconfig.app.json
nuxt.options.typescript.tsConfig.include ??= []
nuxt.options.typescript.tsConfig.include.push(resolve('./augments.d.ts'))

// расширить tsconfig.shared.json
nuxt.options.typescript.sharedTsConfig.include ??= []
nuxt.options.typescript.sharedTsConfig.include.push(resolve('./augments.d.ts'))

// расширить tsconfig.node.json
nuxt.options.typescript.nodeTsConfig.include ??= []
nuxt.options.typescript.nodeTsConfig.include.push(resolve('./augments.d.ts'))

// расширить tsconfig.server.json
nuxt.options.nitro.typescript ??= {}
nuxt.options.nitro.typescript.tsConfig ??= {}
nuxt.options.nitro.typescript.tsConfig.include ??= []
nuxt.options.nitro.typescript.tsConfig.include.push(resolve('./augments.d.ts'))
```

Или хуки `prepare:types` и `nitro:prepare:types`:

```ts
nuxt.hook('prepare:types', ({ references, sharedReferences, nodeReferences }) => {
  // контекст приложения
  references.push({ path: resolve('./augments.d.ts') })
  // общий контекст
  sharedReferences.push({ path: resolve('./augments.d.ts') })
  // контекст Node
  nodeReferences.push({ path: resolve('./augments.d.ts') })
})

nuxt.hook('nitro:prepare:types', ({ references }) => {
  // серверный контекст
  references.push({ path: resolve('./augments.d.ts') })
})
```

<note>

Ссылки TypeScript подключают файлы в контекст типов [независимо от `exclude` в `tsconfig.json`](https://www.typescriptlang.org/tsconfig/#exclude).

</note>

## Дополнение типов

Nuxt сам подхватывает каталоги модуля в нужных контекстах типов. Файлы объявлений кладите в каталог, соответствующий контексту, или [расширьте tsconfig](#%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D0%B5-tsconfig).

- `my-module/runtime/` — контекст приложения (кроме `runtime/server`)
- `my-module/runtime/server/` — серверный контекст
- `my-module/` — Node-контекст (кроме `runtime/` и `runtime/server/`)

```bash [Структура каталогов]
-| my-module/   # контекст типов Node
---| runtime/   # контекст типов приложения
------| augments.app.d.ts
------| server/ # контекст типов сервера
---------| augments.server.d.ts
---| module.ts
---| augments.node.d.ts
```

### Ограничения

#### Типы серверных маршрутов в контексте приложения

Серверные маршруты проверяются и по `tsconfig.app.json`, и по `tsconfig.server.json`, потому что Nuxt выводит типы ответов для [`$fetch`](/docs/3.x/api/utils/dollarfetch) и [`useFetch`](/docs/3.x/api/composables/use-fetch).

<warning>

**Только серверные типы** в файлах маршрутов могут ломать проверку: если модуль добавляет виртуальный файл через [`addServerTemplate`](/docs/3.x/api/kit/templates#addservertemplate) и типы объявлены только в серверном tsconfig, при проверке в контексте приложения их не видно. Тогда типы нужно продублировать (или сделать видимыми) и в контексте приложения.

</warning>
