Модули

Source
Утилиты для создания и использования модулей Nuxt.

Модули — базовые блоки Nuxt. Kit даёт утилиты для создания и использования модулей: своих или существующих. Например, defineNuxtModule объявляет модуль и зависимости через moduleDependencies.

defineNuxtModule

Объявление Nuxt-модуля: слияние опций по умолчанию с пользовательскими, установка переданных хуков и опциональная функция setup для полного контроля.

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

import { defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  meta: {
    name: 'my-module',
    configKey: 'myModule',
  },
  defaults: {
    enabled: true,
  },
  setup (options) {
    if (options.enabled) {
      console.log('Модуль Nuxt включён!')
    }
  },
})

Type

// @errors: 2391
import type { ModuleDefinition, ModuleOptions, NuxtModule } from '@nuxt/schema'
// ---cut---
export function defineNuxtModule<TOptions extends ModuleOptions> (
  definition?: ModuleDefinition<TOptions, Partial<TOptions>, false> | NuxtModule<TOptions, Partial<TOptions>, false>,
): NuxtModule<TOptions, TOptions, false>

export function defineNuxtModule<TOptions extends ModuleOptions> (): {
  with: <TOptionsDefaults extends Partial<TOptions>> (
    definition: ModuleDefinition<TOptions, TOptionsDefaults, true> | NuxtModule<TOptions, TOptionsDefaults, true>,
  ) => NuxtModule<TOptions, TOptionsDefaults, true>
}

Параметры

definition: объект определения модуля или функция. Объект может содержать:

СвойствоТипОбязательныйОписание
metaModuleMetaнетМетаданные: имя, версия, configKey, совместимость.
defaultsT | ((nuxt: Nuxt) => T)нетОпции по умолчанию. Функция получает экземпляр Nuxt.
schemaTнетСхема опций модуля.
hooksPartial<NuxtHooks>нетХуки, регистрируемые модулем.
moduleDependenciesRecord<string, ModuleDependency> | ((nuxt: Nuxt) => ...)нетЗависимости от других модулей (версии, конфиг). Пример.
onInstall(nuxt: Nuxt) => Awaitable<void>нетВызывается при первой установке. Нужны meta.name и meta.version.
onUpgrade(nuxt, options, previousVersion) => Awaitable<void>нетВызывается при обновлении модуля. Нужны meta.name и meta.version.
setup(resolvedOptions, nuxt) => Awaitable<void | false | ModuleSetupInstallResult>нетФункция настройки модуля.

Примеры

Настройка модуля через configKey

configKey задаёт ключ в nuxt.config, под которым пользователь передаёт опции модуля.

import { defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  meta: {
    name: 'my-module',
    configKey: 'myModule',
  },
  defaults: {
    // Module options
    enabled: true,
  },
  setup (options) {
    if (options.enabled) {
      console.log('Модуль Nuxt включён!')
    }
  },
})

Опции модуля передаются в nuxt.config под этим ключом:

export default defineNuxtConfig({
  myModule: {
    enabled: false,
  },
})

Модуль можно полностью отключить, задав ключ в false: setup не выполнится, типы опций по-прежнему генерируются.

export default defineNuxtConfig({
  // Полностью отключить модуль
  myModule: false,
})
Удобно для отключения модулей, унаследованных из слоёв Nuxt.

Требования к совместимости модуля

При разработке модуля Nuxt, использующего API только определённых версий Nuxt, рекомендуется задать compatibility.nuxt.

export default defineNuxtModule({
  meta: {
    name: '@nuxt/icon',
    configKey: 'icon',
    compatibility: {
      // Требуемая версия Nuxt в формате semver.
      nuxt: '>=3.0.0', // или '^3.0.0'
    },
  },
  setup () {
    const resolver = createResolver(import.meta.url)
    // Реализация модуля
  },
})

При несовместимой версии Nuxt в консоли выводится предупреждение.

 WARN  Module @nuxt/icon is disabled due to incompatibility issues:
 - [nuxt] Nuxt version ^3.1.0 is required but currently using 3.0.0

Типизация итоговых опций через .with()

Для типобезопасности итоговых (слитых с defaults) опций модуля используйте метод .with(). TypeScript сможет вывести связь между значениями по умолчанию и аргументом setup.

import { defineNuxtModule } from '@nuxt/kit'

// Интерфейс опций модуля
interface ModuleOptions {
  apiKey: string
  baseURL: string
  timeout?: number
  retries?: number
}

export default defineNuxtModule<ModuleOptions>().with({
  meta: {
    name: '@nuxtjs/my-api',
    configKey: 'myApi',
  },
  defaults: {
    baseURL: 'https://api.example.com',
    timeout: 5000,
    retries: 3,
  },
  setup (resolvedOptions, nuxt) {
    // resolvedOptions типизирован как:
    // {
    //   apiKey: string          // Обязательный, без значения по умолчанию
    //   baseURL: string         // Обязательный, есть значение по умолчанию
    //   timeout: number        // Необязательный, есть значение по умолчанию
    //   retries: number        // Необязательный, есть значение по умолчанию
    // }

    console.log(resolvedOptions.baseURL) // ✅ TypeScript knows this is always defined
    console.log(resolvedOptions.timeout) // ✅ TypeScript knows this is always defined
    console.log(resolvedOptions.retries) // ✅ TypeScript knows this is always defined
  },
})

Без .with() параметр resolvedOptions типизируется как ModuleOptions, и timeout/retries могут быть undefined даже при заданных defaults. Метод .with() даёт TypeScript понять, что при defaults эти поля в итоговых опциях обязательны.

Хуки жизненного цикла: установка и обновление модуля

Хуки выполняются при первой установке модуля или при обновлении версии. Удобны для разовой настройки, миграций БД и очистки.

Для работы хуков в определении модуля обязательно укажите meta.name и meta.version. По ним отслеживается состояние установки в .nuxtrc проекта.

Хуки выполняются до основного setup; при ошибке в хуке она логируется, сборка не прерывается.

onInstall выполняется один раз при первом добавлении модуля в проект.

onUpgrade выполняется при каждом повышении версии модуля (сравнение по semver) — один раз на каждое обновление версии.

Пример
import { defineNuxtModule } from '@nuxt/kit'
import semver from 'semver'

export default defineNuxtModule({
  meta: {
    name: 'my-awesome-module',
    version: '1.2.0', // обязательна для хуков жизненного цикла
    configKey: 'myAwesomeModule',
  },
  defaults: {
    apiKey: '',
    enabled: true,
  },

  onInstall (nuxt) {
    // Выполняется только при первой установке модуля
    console.log('Setting up my-awesome-module for the first time!')

    // Например:
    // - создать начальные конфиги
    // - настроить схемы БД
    // - показать приветствие
    // - выполнить первичную миграцию данных
  },

  onUpgrade (nuxt, options, previousVersion) {
    // Выполняется при обновлении модуля до новой версии
    console.log(`Upgrading my-awesome-module from ${previousVersion} to 1.2.0`)

    // Например:
    // - мигрировать конфиги
    // - обновить схемы БД
    // - удалить устаревшие файлы
    // - показать заметки об обновлении

    if (semver.lt(previousVersion, '1.1.0')) {
      console.log('⚠️  Breaking changes in 1.1.0 - please check the migration guide')
    }
  },

  setup (options, nuxt) {
    // Обычная логика setup выполняется при каждой сборке
    if (options.enabled) {
      // Configure the module
    }
  },
})

Зависимости от других модулей

Опция moduleDependencies объявляет зависимости модуля от других модулей: порядок инициализации, совместимость версий и управление конфигурацией.

moduleDependencies может быть объектом или функцией, принимающей экземпляр Nuxt:

Пример
import { defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  meta: {
    name: 'my-module',
  },
  moduleDependencies: {
    '@nuxtjs/tailwindcss': {
      // Ограничение версии (формат semver)
      version: '>=6.0.0',
      // Конфиг, переопределяющий настройки пользователя
      overrides: {
        exposeConfig: true,
      },
      // Значения по умолчанию с учётом настроек пользователя
      defaults: {
        config: {
          darkMode: 'class',
        },
      },
    },
    '@nuxtjs/fontaine': {
      // Опциональные зависимости не устанавливаются, но опции можно задать, если модуль установлен
      optional: true,
      defaults: {
        fonts: [
          {
            family: 'Roboto',
            fallbacks: ['Impact'],
          },
        ],
      },
    },
  },
  setup (options, nuxt) {

  },
})

Зависимости можно задать функцией по конфигурации Nuxt:

import { defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  meta: {
    name: 'my-module',
  },
  moduleDependencies (nuxt) {
    const dependencies: Record<string, any> = {
      '@nuxtjs/tailwindcss': {
        version: '>=6.0.0',
      },
    }

    // Добавлять зависимости в зависимости от конфига Nuxt
    if (nuxt.options.experimental?.someFeature) {
      dependencies['@nuxtjs/fontaine'] = {
        optional: true,
      }
    }

    return dependencies
  },
  setup (options, nuxt) {
    // setup выполняется после инициализации всех зависимостей
  },
})

installModule

Устарело: используйте опцию moduleDependencies в defineNuxtModule. Функция installModule будет удалена (или станет неблокирующей) в будущей версии.

Программная установка указанного модуля Nuxt. Удобно, когда ваш модуль зависит от других. Опции модуля можно передать объектом в inlineOptions — они попадут в setup этого модуля.

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

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

export default defineNuxtModule({
  async setup () {
    // установит @nuxtjs/fontaine с шрифтом Roboto и fallback Impact
    await installModule('@nuxtjs/fontaine', {
      // опции модуля
      fonts: [
        {
          family: 'Roboto',
          fallbacks: ['Impact'],
          fallbackName: 'fallback-a',
        },
      ],
    })
  },
})

Type

async function installModule (moduleToInstall: string | NuxtModule, inlineOptions?: any, nuxt?: Nuxt)

Параметры

СвойствоТипОбязательныйОписание
moduleToInstallstring | NuxtModuleдаМодуль для установки: строка с именем или объект модуля.
inlineOptionsanyнетОпции модуля, передаваемые в его setup.
nuxtNuxtнетЭкземпляр Nuxt; если не передан, берётся из контекста через useNuxt().

Примеры

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

export default defineNuxtModule({
  async setup (options, nuxt) {
    // установит @nuxtjs/fontaine с шрифтом Roboto и fallback Impact
    await installModule('@nuxtjs/fontaine', {
      // опции модуля
      fonts: [
        {
          family: 'Roboto',
          fallbacks: ['Impact'],
          fallbackName: 'fallback-a',
        },
      ],
    })
  },
})