如何在 Nuxt 3 中服务器启动时获取数据?

问题描述 投票:0回答:2

我在 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但似乎没有合适的。怎样才能达到想要的效果呢?

vue.js nuxt.js vuejs3 nuxtjs3 runtime-configuration
2个回答
1
投票

您正在寻找定制 Nuxt 3 模块

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 中关于类型模板或中间件的文档并不多,所以我希望这对某人有帮助。


0
投票

朝着正确的方向推动

考虑创建服务器/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

© www.soinside.com 2019 - 2024. All rights reserved.