Nuxt instance unavailable when trying to run useRuntimeConfig in a file within utils directory during server side rendering (SSR)

huangapple go评论75阅读模式
英文:

Nuxt instance unavailable when trying to run useRuntimeConfig in a file within utils directory during server side rendering (SSR)

问题

我正在使用Nuxt 3构建一个具有服务器端渲染(SSR)的前端网站,后端使用Laravel。在Nuxt 3项目中,我在utils目录下有一个名为ApiBridge.js的文件,用于组织API调用和设置基本URL等。自从开始这个项目以来,我一直将服务器端渲染关闭以方便开发,但当我尝试启用SSR(在nuxt.config.js中打开)时,出现"Nuxt实例不可用"错误。我正在学习Nuxt 3并同时进行项目开发,所以可能遗漏了一些明显的东西。

为什么会出现这个问题?这是一种不好的做法吗?如何修复它?为什么在关闭SSR时它可以工作?是因为自动导入吗?提前感谢!

在网上查找,但没有找到有用的信息。

编辑:
根据评论的要求,这是nuxt.config.js的内容:

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
    modules: [
        '@nuxtjs/tailwindcss',
        [
            '@pinia/nuxt',
            {
                autoImports: [
                    // 自动导入 `defineStore`
                    'defineStore', // import { defineStore } from 'pinia'
                    // 自动导入 `defineStore` 为 `definePiniaStore`
                    ['defineStore', 'definePiniaStore'], // import { defineStore as definePiniaStore } from 'pinia'
                ],
            },
        ],
    ],
    tailwindcss: {
        configPath: './tailwind.config.js'
    },
    build: {

    },
    // ssr: false, // 稍后移除
    runtimeConfig: {
        public: {
            BASE_URL: process.env.BASE_URL,
            API_BASE_URL: process.env.API_BASE_URL,
        }
    },
})

希望这些信息能够帮助解决你的问题。

英文:

I'm building a website in Nuxt 3 for frontend with SSR, and Laravel in the backend. In the Nuxt 3 project, I have an ApiBridge.js file in the utils directory that I use to organize API calls, set the base URL etc. Since starting the project, I've been running this with server side rendering turned off for my convenience, but when I try to run this with SSR on (Turned on in nuxt.config.js), I get a "Nuxt instance unavailable" error. I'm working on this project while learning Nuxt 3 on the go, so I might be missing something obvious.

import axios from "axios";

const runtimeConfig = useRuntimeConfig()

const api = axios.create({
    baseURL: runtimeConfig?.API_BASE_URL,
    withCredentials: true,
});


const apiBridge = {
    login: (info) => api.post('/login', {
        ...info,
    }),

    register: (info) => api.post('/register', {
        ...info,
    })

    /* .... */
}

export default apiBridge;

Why is this happening? Is this a bad way to do this? How to fix it? Why's it working with SSR turned off? Is it because of the auto imports? Thanks in advance!

Looked around the web but found nothing useful.

EDIT:
nuxt.config.js as requested by a comment

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
    modules: [
        '@nuxtjs/tailwindcss',
        [
            '@pinia/nuxt',
            {
                autoImports: [
                    // automatically imports `defineStore`
                    'defineStore', // import { defineStore } from 'pinia'
                    // automatically imports `defineStore` as `definePiniaStore`
                    ['defineStore', 'definePiniaStore'], // import { defineStore as definePiniaStore } from 'pinia'
                ],
            },
        ],
    ],
    tailwindcss: {
        configPath: './tailwind.config.js'
    },
    build: {

    },
    // ssr: false, // remove later
    runtimeConfig: {
        public: {
            BASE_URL: process.env.BASE_URL,
            API_BASE_URL: process.env.API_BASE_URL,
        }
    },
})

答案1

得分: 3

在一番讨论后,我最终将apiBridge移到了composables目录,并将其改为Nuxt 3可组合对象。我认为这是在Nuxt 3中应该采取的方式。它看起来很整洁,而且能够完成工作。

import axios from "axios"

export const useApiBridge = () => {
    const runtimeConfig = useRuntimeConfig()

    const api = axios.create({
        baseURL: runtimeConfig.API_BASE_URL,
        withCredentials: true,
    });

    return {   
        login: (info) => api.post('/login', {
            ...info,
        }),

        register: (info) => api.post('/register', {
            ...info,
        })
    }
}

然后在组件和其他文件中,我像这样使用它:

const apiBridge = useApiBridge()
英文:

After some back and forth, I ended up moving the apiBridge to the composables directory and changing it to be a Nuxt 3 composable. I assume this is the way it should be done in Nuxt 3. It does look neat, and gets the job done.

import axios from "axios"

export const useApiBridge = () => {
    const runtimeConfig = useRuntimeConfig()

    const api = axios.create({
        baseURL: runtimeConfig.API_BASE_URL,
        withCredentials: true,
    });

    return {   
        login: (info) => api.post('/login', {
            ...info,
        }),

        register: (info) => api.post('/register', {
            ...info,
        })
    }
}

and then in components and other files I use it like

const apiBridge = useApiBridge()

答案2

得分: 2

"Nuxt实例不可用"错误消息通常在尝试在Nuxt实例创建之前或销毁之后访问Nuxt实例时发生。当尝试在Nuxt的生命周期钩子之外访问Nuxt的上下文或插件时,可能会发生此错误。

在您的情况下,似乎useRuntimeConfig()函数被调用在Nuxt的生命周期钩子之外。我假设这个函数是由Nuxt插件或模块提供的。由于服务器端渲染过程与客户端端渲染过程是分开的,因此在使用SSR时,该函数可能不可用,因为它无法访问Nuxt实例。

修复这个问题的一种方法是将useRuntimeConfig()调用移到Nuxt生命周期钩子内,例如asyncData()fetch()。这将确保在调用该函数时Nuxt实例是可用的。然后,您可以将API_BASE_URL作为参数传递给ApiBridge模块或通过nuxtServerInit()动作传递。

另一种修复方法是使用环境变量而不是运行时配置。您可以在.env文件或托管环境中设置环境变量,并使用process.env来访问它们。这样,API基本URL可以在构建过程中设置,并且在服务器端和客户端都可用。

关于您关于为什么在关闭SSR时能正常工作的问题,这可能是因为useRuntimeConfig()函数在客户端端渲染过程中被调用,其中Nuxt实例是可用的。然而,这不是一种可靠的解决方案,可能在使用SSR时会出现问题。

总的来说,最好的做法是避免在Nuxt的生命周期钩子之外访问Nuxt实例,并使用适当的依赖注入技术将变量和依赖项传递给您的模块和组件。

英文:

The error message "Nuxt instance unavailable" typically occurs when trying to access Nuxt's instance before it has been created or after it has been destroyed. This error can occur when trying to access Nuxt's context or plugins from outside of Nuxt's lifecycle hooks.

In your case, it seems that the useRuntimeConfig() function, which I assume is provided by a Nuxt plugin or module, is being called outside of Nuxt's lifecycle hooks. This function is likely not available when running with SSR because the server-side rendering process is separate from the client-side rendering process, and does not have access to the Nuxt instance.

One way to fix this is to move the useRuntimeConfig() call inside a Nuxt lifecycle hook, such as asyncData() or fetch(). This will ensure that the Nuxt instance is available when the function is called. You can then pass the API_BASE_URL to the ApiBridge module as a parameter or through the nuxtServerInit() action.

Another way to fix this is to use environment variables instead of runtime config. You can set environment variables in the .env file or in your hosting environment, and access them using process.env. This way, the API base URL can be set during the build process and will be available both server-side and client-side.

Regarding your question about why this is working with SSR turned off, it could be because the useRuntimeConfig() function is being called during the client-side rendering process, where the Nuxt instance is available. However, this is not a reliable solution and can lead to issues when running with SSR.

In general, it's a good practice to avoid accessing the Nuxt instance outside of its lifecycle hooks and to use proper dependency injection techniques to pass variables and dependencies to your modules and components.

huangapple
  • 本文由 发表于 2023年2月27日 06:02:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/75575272.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定