模块

源文件
Nuxt Kit 提供了一套工具,旨在帮助你创建和使用模块。你可以使用这些工具来创建自己的模块,或者复用现有的模块。

模块是 Nuxt 的构建基块。Kit 提供了一套工具来帮助你创建和使用模块。你可以使用这些工具来创建自己的模块,或者复用现有的模块。例如,你可以使用 defineNuxtModule 函数来定义模块,并使用 moduleDependencies 选项指定依赖项。

defineNuxtModule

定义一个 Nuxt 模块,自动将默认值与用户提供的选项合并,安装所提供的任何钩子(hooks),并调用可选的 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('My Nuxt module is enabled!')
    }
  },
})

类型

// @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>
}

参数

定义:模块定义对象或模块函数。模块定义对象应包含以下属性:

属性类型必需描述
metaModuleMetafalse模块的元数据。它定义了模块名称、版本、配置键(config key)和兼容性。
defaultsT | ((nuxt: Nuxt) => T)false模块的默认选项。如果提供了一个函数,它将以 Nuxt 实例作为第一个参数被调用。
schemaTfalse模块选项的 Schema。如果提供,选项将应用于该 Schema。
hooksPartial<NuxtHooks>false要为模块安装的钩子(Hooks)。如果提供,模块将安装这些钩子。
moduleDependenciesRecord<string, ModuleDependency> | ((nuxt: Nuxt) => Record<string, ModuleDependency>)false对其他具有版本约束和配置的模块的依赖。可以是一个对象,也可以是一个接收 Nuxt 实例的函数。详见示例
onInstall(nuxt: Nuxt) => Awaitable<void>false模块首次安装时调用的生命周期钩子。要求定义 meta.namemeta.version
onUpgrade(nuxt: Nuxt, options: T, previousVersion: string) => Awaitable<void>false模块升级到新版本时调用的生命周期钩子。要求定义 meta.namemeta.version
setup(this: void, resolvedOptions: T, nuxt: Nuxt) => Awaitable<void | false | ModuleSetupInstallResult>false模块的设置函数。如果提供,模块将调用该设置函数。

示例

使用 configKey 使你的模块可配置

定义 Nuxt 模块时,你可以设置 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('My Nuxt module is enabled!')
    }
  },
})

用户可以在 nuxt.config 中对应的键下为该模块提供选项。

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

用户还可以通过将配置键设置为 false 来完全禁用某个模块。这可以防止模块的 setup 函数运行,同时仍然为模块选项生成类型。

export default defineNuxtConfig({
  // Disable the module entirely
  myModule: false,
})
当你想要禁用从 Nuxt 层(Layers)继承的模块时,这尤其有用。

定义模块兼容性要求

如果你正在开发 Nuxt 模块并使用了仅在特定 Nuxt 版本中支持的 API,强烈建议包含 compatibility.nuxt

export default defineNuxtModule({
  meta: {
    name: '@nuxt/icon',
    configKey: 'icon',
    compatibility: {
      // Required nuxt version in semver format.
      nuxt: '>=3.0.0', // or use '^3.0.0'
    },
  },
  setup () {
    const resolver = createResolver(import.meta.url)
    // Implement
  },
})

如果用户尝试在不兼容的 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() 实现已解析选项的类型安全

当你需要为已解析/合并的模块选项提供类型安全时,可以使用 .with() 方法。这使得 TypeScript 能够正确推断模块默认值与 setup 函数最终接收到的已解析选项之间的关系。

import { defineNuxtModule } from '@nuxt/kit'

// Define your module options interface
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 is properly typed as:
    // {
    //   apiKey: string          // Required, no default provided
    //   baseURL: string         // Required, has default value
    //   timeout: number         // Optional, has default value
    //   retries: number         // Optional, has default value
    // }

    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 接口,其中即使提供了默认值,timeoutretries 也可能被视为 undefined.with() 方法使 TypeScript 能够理解默认值使这些属性在已解析的选项中变为非可选的。

使用生命周期钩子进行模块安装和升级

你可以定义在模块首次安装或升级到新版本时运行的生命周期钩子。这些钩子对于执行一次性设置任务、数据库迁移或清理操作非常有用。

为了使生命周期钩子生效,你必须在模块定义中同时提供 meta.namemeta.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', // Required for lifecycle hooks
    configKey: 'myAwesomeModule',
  },
  defaults: {
    apiKey: '',
    enabled: true,
  },

  onInstall (nuxt) {
    // This runs only when the module is first installed
    console.log('Setting up my-awesome-module for the first time!')

    // You might want to:
    // - Create initial configuration files
    // - Set up database schemas
    // - Display welcome messages
    // - Perform initial data migration
  },

  onUpgrade (nuxt, options, previousVersion) {
    // This runs when the module is upgraded to a newer version
    console.log(`Upgrading my-awesome-module from ${previousVersion} to 1.2.0`)

    // You might want to:
    // - Migrate configuration files
    // - Update database schemas
    // - Clean up deprecated files
    // - Display upgrade notes

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

  setup (options, nuxt) {
    // Regular setup logic runs on every build
    if (options.enabled) {
      // Configure the module
    }
  },
})

指定模块依赖项

你可以使用 moduleDependencies 选项来声明对其他模块的依赖。这提供了一种稳健的方法来确保正确的设置顺序、版本兼容性和配置管理。

moduleDependencies 选项可以是一个对象,也可以是一个接收 Nuxt 实例的函数。

示例
import { defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  meta: {
    name: 'my-module',
  },
  moduleDependencies: {
    '@nuxtjs/tailwindcss': {
      // Specify a version constraint (semver format)
      version: '>=6.0.0',
      // Configuration that overrides user settings
      overrides: {
        exposeConfig: true,
      },
      // Configuration that sets defaults but respects user settings
      defaults: {
        config: {
          darkMode: 'class',
        },
      },
    },
    '@nuxtjs/fontaine': {
      // Optional dependencies won't be installed but ensure that options
      // can be set if they _are_ installed
      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',
      },
    }

    // Conditionally add dependencies based on Nuxt config
    if (nuxt.options.experimental?.someFeature) {
      dependencies['@nuxtjs/fontaine'] = {
        optional: true,
      }
    }

    return dependencies
  },
  setup (options, nuxt) {
    // Your setup logic runs after all dependencies are initialized
  },
})

installModule

已弃用: 请改用 defineNuxtModule 中的 moduleDependencies 选项。installModule 函数将在未来版本中被移除(或可能变为非阻塞)。

以编程方式安装指定的 Nuxt 模块。当你的模块依赖于其他模块时,这非常有用。你可以将模块选项作为对象传递给 inlineOptions,它们将被传递给模块的 setup 函数。

使用

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

export default defineNuxtModule({
  async setup () {
    // will install @nuxtjs/fontaine with Roboto font and Impact fallback
    await installModule('@nuxtjs/fontaine', {
      // module configuration
      fonts: [
        {
          family: 'Roboto',
          fallbacks: ['Impact'],
          fallbackName: 'fallback-a',
        },
      ],
    })
  },
})

类型

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

参数

属性类型必需描述
moduleToInstallstring | NuxtModuletrue要安装的模块。可以是带有模块名称的字符串,也可以是模块对象本身。
inlineOptionsanyfalse包含要传递给模块 setup 函数的模块选项的对象。
nuxtNuxtfalseNuxt 实例。如果未提供,它将通过 useNuxt() 调用从上下文中获取。

示例

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

export default defineNuxtModule({
  async setup (options, nuxt) {
    // will install @nuxtjs/fontaine with Roboto font and Impact fallback
    await installModule('@nuxtjs/fontaine', {
      // module configuration
      fonts: [
        {
          family: 'Roboto',
          fallbacks: ['Impact'],
          fallbackName: 'fallback-a',
        },
      ],
    })
  },
})