我在 Nuxt 3 中有一个 Web 应用程序,正在从 Nuxt 2 迁移。我们还有一个配套 API 来处理从数据库获取的所有数据。启动网络服务器时,nuxt 应用程序必须从此 API 获取带有一些设置(启动所需的内容和一些用作运行时参数的常量变量)的 JSON 对象。这些值在每个部署中可能不同,并且仅在 API 和应用程序更新时才会更改(这意味着两者都需要重新启动)。我不想每次用户进入应用程序时都在插件中获取这些数据,因为调用总是会产生相同的结果。当前的 Nuxt 2 配置如下所示:
// nuxt.config.js (Nuxt 2)
export default async () => {
const result = await someAsyncCall()
return {
// actual config, use result in runtime parameters here, exposed under this.$config
}
}
根据迁移指南(https://nuxt.com/docs/migration/configuration#async-configuration)这种工作方式现已在 Nuxt 3 中弃用,建议使用 Nuxt hooks,但我找不到正确的实现这一目标的方法。目标是让应用程序在启动时获取此 json 数据,并使此数据可供任何地方使用。我尝试过以下方法:
// This is the Nuxt 3 equivalent, but it's deprecated and for some reason it calls the data twice:
// nuxt.config.ts
export default async () => {
const result = await someAsyncCall()
return defineNuxtConfig({
runtimeConfig:{
// use result here
}
})
}
// This doesn't update the runtime config
//nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
public: {
myparam: ''
}
},
hooks: {
ready: async (nuxt) => { // not sure if 'ready' is available at deploy since it's a build hook anyway
console.log('READY')
const settings = await getRuntimeConfig()
nuxt.options.runtimeConfig.public.myparam = settings
}
},
})
// It's not allowed to import from nuxt.config.ts so this doesn't work.
// nuxt.config.ts
export const settings = {}
export default defineNuxtConfig({
hooks: {
ready: async (nuxt) => {
console.log('READY')
const _settings = await getRuntimeConfig()
settings = _settings
}
},
})
// myPlugin.ts
import { settings } from 'nuxt.config' // not allowed
export default defineNuxtPlugin(() => {
return { provide: { settings } }
})
我还检查了https://nuxt.com/docs/api/advanced/hooks但似乎没有合适的。怎样才能达到想要的效果呢?
Nuxt 3 插件仅在运行时运行,而模块现在仅在构建时运行。
我认为文档中的这一部分可以解决您的问题:向运行时公开选项
这是我如何实现这一目标的示例(我使用的是 Nuxt v3.6.1):
import {
defineNuxtModule,
useLogger,
createResolver,
addImportsDir,
addRouteMiddleware,
addTypeTemplate,
} from 'nuxt/kit'
import { $fetch } from 'ofetch'
export default defineNuxtModule({
meta: {
// Usually the npm package name of your module
name: '@nuxtjs/my-module',
// The key in `nuxt.config` that holds your module options
configKey: 'my-module',
// Compatibility constraints
compatibility: {
// Semver version of supported nuxt versions
nuxt: '^3.6.1',
},
},
defaults: {
// Your Defuault Options
},
async setup(options, nuxt) {
// Create the path resolver
const resolver = createResolver(import.meta.url)
// Create the consola logger
const logger = useLogger('my-module')
logger.start('Starting...')
const URL = `some-api/endpoint`
const data = await $fetch<ResponseType>(URL) // I type my responses
if (data) { //! I don't know what your response is going to look like
// You could put these in public or merge existing ones with defu from unjs
nuxt.options.runtimeConfig.options.myModuleOptions = data
logger.success('Successfuly Loaded!')
}
//* Add Feature Specific Composables
addImportsDir(resolver.resolve('runtime/composables'))
//* Add Feature Specific Middleware
addRouteMiddleware({
name: 'myModuleMiddleware',
path: resolver.resolve('runtime/middleware/someMiddleware'),
global: true,
})
//* Add the Feature Specific Types
addTypeTemplate({
filename: 'types/my-module-types.d.ts',
src: resolver.resolve('runtime/types.ts'),
write: true,
})
},
})
实际上 Nuxt 3 中关于类型模板或中间件的文档并不多,所以我希望这对某人有帮助。
考虑创建服务器/Nitro 插件:Nuxt 3 服务器插件文档
Nuxt 3 支持两种类型的插件:“应用程序”插件(在
/plugins
目录中)和“服务器”或 Nitro 插件(在 /server/plugins
中)。常规插件在创建 Vue 应用程序时加载,并不能解决这个问题,但是......
Nitro 插件会自动注册(文件名排序)并在第一次 nitro 初始化时同步运行。 有关更多信息,请参阅 Nitro 插件文档。即使没有客户端,我也能够在服务器启动时使用插件来获取数据,使用以下代码:
// server/plugins/01.fetchSettings.ts
export default defineNitroPlugin(async (nitroApp) => {
const endpoint = useRuntimeConfig().settingsEndpoint
try {
const result = await $fetch(endpoint)
// Use result here
} catch (e) {
console.log('Error fetching settings.')
}
})
下一步是找到将数据传递给客户端的正确方法。我可以尝试使用
defu
来扩展运行时配置,如 this 但我不确定这是否有效。也许带有 Nitro 钩子的东西,比如 使用 render:response
钩子?我现在正在做其他事情,但如果我弄清楚了,我一定会更新这篇文章。
编辑:不允许更改服务器端的运行时参数,因为如果操作不当,可能会泄漏客户端之间的上下文。运行时参数不是这里的方法:https://nuxt.com/docs/guide/going-further/runtime-config#vue-app