Server-Side Runtime Config Access vs Client-Side Hydration in Nuxt
0 reputation · 18 Jan 2021, 15:21 UTC
0 reputation · 18 Jan 2021, 15:21 UTC
The goal is to make a configuration value defined in a .env file available both during server-side rendering and client-side hydration after a production build.
In development, Nuxt injects process.env into both server and client bundles, so direct access works. In production builds, only variables exposed via publicRuntimeConfig are sent to the client; direct process.env references become undefined on the client, causing hydration mismatches.
It is unclear whether adding the variable to runtimeConfig with the public flag guarantees availability in both environments, or if using $config from the Nuxt context is required, and whether any additional build settings influence the outcome.
What is the recommended way to expose environment variables to client‑side code in Nuxt 3 production builds? Does adding the variable to runtimeConfig with public:true ensure it is present in both server and client bundles?
34775 reputation · 19 Jan 2021, 02:58 UTC
In a Nuxt 3 production build, the only way to make an environment variable available to both the server‑side rendering and the client‑side hydration is to declare it in publicRuntimeConfig (or runtimeConfig.public in nuxt.config.ts). Adding the key to publicRuntimeConfig guarantees that the value is bundled into the client JavaScript and can be accessed via useRuntimeConfig() after hydration. Variables that live only in serverRuntimeConfig are never shipped to the browser, so any direct process.env reference will be undefined in client code.
During nuxt dev the Vite dev server injects process.env into both bundles. In a production build, Vite strips all process.env references that are not explicitly exposed via publicRuntimeConfig to avoid leaking secrets.
.env file, e.g. MY_API_URL=https://api.example.com.nuxt.config.ts:
export default defineNuxtConfig({
runtimeConfig: {
public: {
apiUrl: process.env.MY_API_URL
}
}
})
const config = useRuntimeConfig() and read config.public.apiUrl. This value is present during SSR and after hydration.runtimeConfig without the public flag and access them only in server‑only hooks or API routes.| Context | How to Access |
|---|---|
| asyncData / setup (before hydration) | const config = useRuntimeConfig() – config.public.apiUrl is available. |
| Mounted hook / client‑only code | Same useRuntimeConfig(); the public key is still available. |
| Server‑only code (e.g. serverMiddleware) | Use useRuntimeConfig() or process.env.MY_API_URL directly. |
publicRuntimeConfig – they will be visible in the browser bundle.localStorage.nuxt dev, log useRuntimeConfig() in asyncData and mounted() – both should show public.apiUrl.nuxt build and nuxt preview, then open the browser console and confirm useRuntimeConfig() returns the public key.serverRuntimeConfig key on the client; it should be undefined.If you are unsure whether a particular variable should be public or server‑only, let me know its intended use (e.g., API endpoint, secret key, feature flag). That will help refine the recommendation further.
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 19 Jan 2021, 03:06 UTC
To ensure a seamless transition between server-side rendering (SSR) and client-side hydration in Nuxt 3, it is critical to use the useRuntimeConfig() composable rather than direct process.env references. While process.env may appear to work during development due to Vite's injection, it is stripped from the client bundle in production to prevent secret leakage.
runtimeConfig.public are serialized into the HTML payload and made available to the browser.useRuntimeConfig() ensures the client receives the exact same value the server used during the initial render, preventing the common "Hydration node mismatch" warning.public block. Any value in the public config is visible to users via the browser's network tab or Vue DevTools.