Хуки и расширение типов
Ниже — продвинутые приёмы для авторов модулей: хуки, шаблоны и дополнение типов.
Жизненные хуки
Хуки жизненного цикла позволяют расширять почти любой аспект Nuxt. Модули могут подписываться на них из кода или через карту hooks в определении модуля.
import { addPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
// Hook to the `app:error` hook through the `hooks` map
hooks: {
'app:error': (err) => {
console.info(`This error happened: ${err}`)
},
},
setup (options, nuxt) {
// Programmatically hook to the `pages:extend` hook
nuxt.hook('pages:extend', (pages) => {
console.info(`Discovered ${pages.length} pages`)
})
},
})
Если модуль открывает ресурсы, обрабатывает что-то или запускает watcher, закройте это по завершении жизненного цикла Nuxt. Для этого есть хук
close.import { defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
nuxt.hook('close', async (nuxt) => {
// Your custom code here
})
},
})
Свои хуки
Модуль может объявлять и вызывать собственные хуки — удобно для расширяемости.
Если другие модули должны подписаться на ваши хуки, вызывайте их в хуке modules:done: к этому моменту все модули успеют зарегистрировать слушатели в своём setup.
// 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) {
// Call your hook in `modules:done`
nuxt.hook('modules:done', async () => {
const payload = { foo: 'bar' }
await nuxt.callHook('my-module:custom-hook', payload)
})
},
})
Виртуальные файлы
Чтобы добавить виртуальный файл, импортируемый в приложении пользователя, используйте addTemplate.
import { addTemplate, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
// The file is added to Nuxt's internal virtual file system and can be imported from '#build/my-module-feature.mjs'
addTemplate({
filename: 'my-module-feature.mjs',
getContents: () => 'export const myModuleFeature = () => "hello world !"',
})
},
})
Для сервера используйте addServerTemplate.
import { addServerTemplate, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
// The file is added to Nitro's virtual file system and can be imported in the server code from 'my-server-module.mjs'
addServerTemplate({
filename: 'my-server-module.mjs',
getContents: () => 'export const myServerModule = () => "hello world !"',
})
},
})
Обновление виртуальных файлов
Чтобы обновить шаблоны/виртуальные файлы, используйте updateTemplates:
nuxt.hook('builder:watch', (event, path) => {
if (path.includes('my-module-feature.config')) {
// This will reload the template that you registered
updateTemplates({ filter: t => t.filename === 'my-module-feature.mjs' })
}
})
Объявления типов
Чтобы добавить объявления типов в проект пользователя (например, расширить интерфейс Nuxt или дать глобальный тип), используйте addTypeTemplate: шаблон записывается на диск и попадает в сгенерированный nuxt.d.ts.
Если модуль дополняет типы, которыми управляет Nuxt:
import { addTemplate, addTypeTemplate, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
addTypeTemplate({
filename: 'types/my-module.d.ts',
getContents: () => `// Generated by my-module
interface MyModuleNitroRules {
myModule?: { foo: 'bar' }
}
declare module 'nitro/types' {
interface NitroRouteRules extends MyModuleNitroRules {}
interface NitroRouteConfig extends MyModuleNitroRules {}
}
export {}`,
})
},
})
Для более тонкого контроля — хук prepare:types и callback для подключения типов.
const template = addTemplate({ /* template options */ })
nuxt.hook('prepare:types', ({ references }) => {
references.push({ path: template.dst })
})
Расширение TypeScript {#extend-typescript-config}
Расширить tsconfig проекта из модуля можно по-разному.
Проще всего править конфигурацию Nuxt напрямую:
// extend tsconfig.app.json
nuxt.options.typescript.tsConfig.include ??= []
nuxt.options.typescript.tsConfig.include.push(resolve('./augments.d.ts'))
// extend tsconfig.shared.json
nuxt.options.typescript.sharedTsConfig.include ??= []
nuxt.options.typescript.sharedTsConfig.include.push(resolve('./augments.d.ts'))
// extend tsconfig.node.json
nuxt.options.typescript.nodeTsConfig.include ??= []
nuxt.options.typescript.nodeTsConfig.include.push(resolve('./augments.d.ts'))
// extend 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 для ссылок в нужных контекстах типов или правки конфигурации аналогично примеру выше.
nuxt.hook('prepare:types', ({ references, sharedReferences, nodeReferences }) => {
// extend app context
references.push({ path: resolve('./augments.d.ts') })
// extend shared context
sharedReferences.push({ path: resolve('./augments.d.ts') })
// extend node context
nodeReferences.push({ path: resolve('./augments.d.ts') })
})
nuxt.hook('nitro:prepare:types', ({ references }) => {
// extend server context
references.push({ path: resolve('./augments.d.ts') })
})
exclude в tsconfig.json.Дополнение типов
Nuxt сам подключает каталоги модуля в нужные контексты типов. Чтобы дополнить типы, положите файл объявлений в каталог, соответствующий контексту. Или расширьте конфигурацию TypeScript из произвольного пути.
my-module/runtime/— контекст приложения (кромеruntime/server)my-module/runtime/server/— серверный контекстmy-module/— node-контекст (кромеruntime/иruntime/server)
-| my-module/ # node type context
---| runtime/ # app type context
------| augments.app.d.ts
------| server/ # server type context
---------| augments.server.d.ts
---| module.ts
---| augments.node.d.ts
Известные ограничения
Проверка типов серверных маршрутов в контексте приложения
Серверные маршруты проверяются и по tsconfig.app.json, и по tsconfig.server.json.
Так Nuxt выводит типы ответов для $fetch и useFetch.
addServerTemplate и типы для него объявлены только в tsconfig.server.json, при проверке маршрутов в app-контексте эти типы недоступны — появятся ошибки. Обычно такие типы приходится дублировать и в app-контексте.