添加插件、组件及更多
学习如何从你的模块中注入插件、组件、组合函数和服务器路由。
以下是模块作者常用的一些模式。
修改 Nuxt 配置
模块可以读取并修改 Nuxt 配置。下面是一个启用实验性功能的模块示例。
import { defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
// 如果还不存在,则创建 `experimental` 对象
nuxt.options.experimental ||= {}
nuxt.options.experimental.componentIslands = true
},
})
当你需要处理更复杂的配置修改时,建议使用 defu。
向运行时暴露选项
由于模块不是应用的运行时一部分,它们的选项也不是。然而,在许多情况下,你可能需要在运行时代码中访问某些模块选项。我们建议使用 Nuxt 的 runtimeConfig 来暴露所需的配置。
import { defineNuxtModule } from '@nuxt/kit'
import { defu } from 'defu'
export default defineNuxtModule({
setup (options, nuxt) {
nuxt.options.runtimeConfig.public.myModule = defu(nuxt.options.runtimeConfig.public.myModule, {
foo: options.foo,
})
},
})
注意,这里我们使用 defu 来合并用户提供的公共运行时配置,而不是直接覆盖。
然后你可以在插件、组件或应用中像访问其他运行时配置一样访问你的模块选项:
import { useRuntimeConfig } from '@nuxt/kit'
const options = useRuntimeConfig().public.myModule
请注意不要在公共运行时配置中暴露任何敏感的模块配置,如私有 API 密钥,因为它们将出现在公共包中。
添加插件
插件是模块添加运行时逻辑的常见方式。你可以使用 addPlugin 工具从模块中注册它们。
import { addPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
// 创建解析器以解析相对路径
const resolver = createResolver(import.meta.url)
addPlugin(resolver.resolve('./runtime/plugin'))
},
})
添加组件
如果你的模块需要提供 Vue 组件,可以使用 addComponent 工具将其添加为 Nuxt 自动导入的组件。
import { addComponent, createResolver, defineNuxtModule, useRuntimeConfig } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
const resolver = createResolver(import.meta.url)
// 来自 runtime 目录
addComponent({
name: 'MySuperComponent', // 组件在 vue 模板中使用的名字
export: 'MySuperComponent', // (可选)如果组件是具名导出(非默认导出)
filePath: resolver.resolve('runtime/app/components/MySuperComponent.vue'),
})
// 来自库
addComponent({
name: 'MyAwesomeComponent', // 组件在 vue 模板中使用的名字
export: 'MyAwesomeComponent', // (可选)如果组件是具名导出(非默认导出)
filePath: '@vue/awesome-components',
})
},
})
或者,你也可以使用 addComponentsDir 添加整个目录。
import { addComponentsDir, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
const resolver = createResolver(import.meta.url)
addComponentsDir({
path: resolver.resolve('runtime/app/components'),
})
},
})
强烈建议给你的导出添加前缀,以避免与用户代码或其他模块冲突。
请注意,所有通常放置于你的
app/ 文件夹下的组件、页面、组合函数和其他文件,需要放在 runtime/app/ 下。这样才能获得正确的类型检查。添加组合函数
如果你的模块需要提供组合函数,可以使用 addImports 工具将它们添加为 Nuxt 的自动导入项。
import { addImports, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
const resolver = createResolver(import.meta.url)
addImports({
name: 'useComposable', // 组合函数名称
as: 'useMyComposable', // 可选别名,供使用该模块的应用调用
from: resolver.resolve('runtime/app/composables/useComposable'), // 组合函数路径
})
},
})
也可以传入数组添加多个:
import { addImports, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
const resolver = createResolver(import.meta.url)
addImports([
{ name: 'useFirstComposable', from: resolver.resolve('runtime/composables/useFirstComposable') },
{ name: 'useSecondComposable', from: resolver.resolve('runtime/composables/useSecondComposable') },
])
},
})
或者,使用 addImportsDir 添加整个目录。
import { addImportsDir, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
const resolver = createResolver(import.meta.url)
addImportsDir(resolver.resolve('runtime/composables'))
},
})
强烈建议给你的导出添加前缀,以避免与用户代码或其他模块冲突。
请注意,所有通常放置于你的
app/ 文件夹下的组件、页面、组合函数和其他文件,需要放在 runtime/app/ 下。这样才能获得正确的类型检查。添加服务器路由
import { addServerHandler, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
const resolver = createResolver(import.meta.url)
addServerHandler({
route: '/api/_my-module/hello',
handler: resolver.resolve('./runtime/server/api/hello/index.get'),
})
},
})
你也可以添加动态服务器路由:
import { addServerHandler, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
const resolver = createResolver(import.meta.url)
addServerHandler({
route: '/api/_my-module/hello/:name',
handler: resolver.resolve('./runtime/server/api/hello/[name].get'),
})
// 或者使用 catch all 路由
addServerHandler({
route: '/api/_my-module/files/**:path',
handler: resolver.resolve('./runtime/server/api/files/[...path].get'),
})
},
})
强烈建议给你的服务器路由添加前缀,以避免与用户定义的路由冲突。像
/api/auth、/api/login 或 /api/user 这样的常用路径可能已经被应用使用。添加其他资源
如果你的模块需要提供其他类型的资源,也可以注入。下面是一个简单的示例模块,通过 Nuxt 的 css 数组注入样式表。
import { addPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
const resolver = createResolver(import.meta.url)
nuxt.options.css.push(resolver.resolve('./runtime/style.css'))
},
})
还有一个更高级的示例,通过 Nitro 的 publicAssets 选项暴露一个资源目录:
import { createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
const resolver = createResolver(import.meta.url)
nuxt.hook('nitro:config', (nitroConfig) => {
nitroConfig.publicAssets ||= []
nitroConfig.publicAssets.push({
dir: resolver.resolve('./runtime/public'),
maxAge: 60 * 60 * 24 * 365, // 1 年
})
})
},
})
使用其他模块
如果你的模块依赖其他模块,可以使用 moduleDependencies 选项指定它们。这提供了更稳健的依赖处理方式,支持版本约束和配置合并:
import { createResolver, defineNuxtModule } from '@nuxt/kit'
const resolver = createResolver(import.meta.url)
export default defineNuxtModule<ModuleOptions>({
meta: {
name: 'my-module',
},
moduleDependencies: {
'@nuxtjs/tailwindcss': {
// 你可以指定模块的版本约束
version: '>=6',
// 任何需要覆盖 `nuxt.options` 的配置
overrides: {
exposeConfig: true,
},
// 任何默认配置。这会覆盖模块默认值,但不会覆盖用户在 `nuxt.options` 里设置的配置
defaults: {
config: {
darkMode: 'class',
content: {
files: [
resolver.resolve('./runtime/components/**/*.{vue,mjs,ts}'),
resolver.resolve('./runtime/*.{mjs,js,ts}'),
],
},
},
},
},
},
setup (options, nuxt) {
// 我们可以注入包含 Tailwind 指令的 CSS 文件
nuxt.options.css.push(resolver.resolve('./runtime/assets/styles.css'))
},
})
moduleDependencies 选项替代了已废弃的 installModule 函数,确保正确的模块安装顺序和配置合并。