withastro/astro

Variables from `.env` are not available in `astro.config`

JekRock opened this issue · 8 comments

Astro Info

Astro                    v5.0.3
Node                     v22.12.0
System                   macOS (arm64)
Package Manager          npm
Output                   static
Adapter                  none
Integrations             none

If this issue only occurs in one browser, which browser is a problem?

No response

Describe the Bug

When running npm run dev, the PUBLIC_SITE_DOMAIN env variable from the .env file is undefined in the astro.config.mjs file.

❯ npm install && npm run dev

added 275 packages in 3s

139 packages are looking for funding
  run `npm fund` for details

> @example/minimal@0.0.1 dev
> astro dev

PUBLIC_SITE_DOMAIN: undefined
15:36:26 [types] Generated 1ms

 astro  v5.0.3 ready in 263 ms

┃ Local    http://localhost:4321/
┃ Network  use --host to expose

15:36:26 [content] Syncing content
15:36:26 [content] Astro version changed
15:36:26 [content] Clearing content store
15:36:26 [content] Synced content
15:36:26 watching for file changes...
15:36:29 [200] / 8ms

Bur after a hot reload (making any change to any file in the project and saving it), the variable is read from the .env file and available in the astro.config.mjs file:

❯ npm install && npm run dev

added 275 packages in 3s

139 packages are looking for funding
  run `npm fund` for details

> @example/minimal@0.0.1 dev
> astro dev

PUBLIC_SITE_DOMAIN: undefined
15:36:26 [types] Generated 1ms

 astro  v5.0.3 ready in 263 ms

┃ Local    http://localhost:4321/
┃ Network  use --host to expose

15:36:26 [content] Syncing content
15:36:26 [content] Astro version changed
15:36:26 [content] Clearing content store
15:36:26 [content] Synced content
15:36:26 watching for file changes...
15:36:29 [200] / 8ms
15:40:32 Configuration file updated. Restarting...
PUBLIC_SITE_DOMAIN: https://example.com
15:40:33 [types] Generated 1ms
15:40:34 Configuration file updated. Restarting...
PUBLIC_SITE_DOMAIN: https://example.com
15:40:34 [200] / 6ms
15:40:34 [types] Generated 0ms
15:40:35 [200] / 5ms

What's the expected result?

Environment variables are populated from .env* files and available in the astro.config.mjs file from the first run of the npm run dev command

Link to Minimal Reproducible Example

https://stackblitz.com/edit/github-nf7bmr?file=astro.config.mjs

Participation

  • I am willing to submit a pull request for this issue.

As a workaround, you can use .env.local

@ematipico do you mean replacing .env with .env.local?
If so, the issue is still the same there

I tried it in your reproduction, and it works 🤔 I might have done something wrong

@ematipico could you share a link to stackblitz with the changes, please?
Maybe I'm doing that a wrong way

I tried both .env and .env.local in Stackblitz and both returned undefined for me. My steps after creating a .env file:

  1. Stop the server
  2. Run npm run dev (undefined)
  3. Make a change and wait for hot reload (the value is defined).

But, as a workaround, you can use loadEnv from Vite:

import { loadEnv } from "vite";

const env = loadEnv(process.env.NODE_ENV, process.cwd(), '');

export default defineConfig({
  site: env.PUBLIC_SITE_DOMAIN,
});

I tried in Stackblitz and it seems to work!
As suggested in the docs, you might need to explicitly add vite to your dependencies depending on your package manager (pnpm).

@ArmandPhilippot thank you for the workaround!
I'm wondering why astro doesn't read env files in the dev mode. When the astro.config.mjs config is loaded, there is no code for loading env variables

if (/\.[cm]?js$/.test(configPath)) {
try {
const config = await import(pathToFileURL(configPath).toString() + '?t=' + Date.now());
return config.default ?? {};
} catch (e) {
// We do not need to throw the error here as we have a Vite fallback below
debug('Failed to load config with Node', e);
}
}

Env variables seem to load only when vite dev server starts here

await viteServer.listen(port);

I've found one caveat with this workaround: The astro dev --mode <MODE> doesn't set the process.env.NODE_ENV environment variable to the value passed to that command.
In such an example, process.env.NODE_ENV will always be either development or production and will not load .env* files the way one would expect.

So NODE_ENV should be set explicitly in package.json scripts