Unable to resolve import.meta.env.xxx
Closed this issue · 20 comments
Astro Info
PS F:\eya46eya46> astro info
Astro v5.0.2
Node v22.12.0
System Windows (x64)
Package Manager unknown // pnpm
Output server
Adapter @astrojs/node
Integrations @astrojs/tailwind
If this issue only occurs in one browser, which browser is a problem?
No response
Describe the Bug
my code src/utils/wakatime.ts
The following content is from a translation.
Reproduce the bug(?)
// astro.config.mjs
export default defineConfig({
output: "server",
adapter: node({
mode: "standalone",
}),
}
// any where
import.meta.env.xxx
It works correctly when using astro dev
, but after building, it doesn't work properly when running astro preview
or node dist/server/entry.mjs
.
In the new version, the source code const WAKATIME_TOKEN = import.meta.env.WAKATIME_TOKEN;
is compiled into const WAKATIME_TOKEN = process.env.WAKATIME_TOKEN;
.
Previously, import.meta.env.WAKATIME_TOKEN
would be directly replaced with the actual value. However, now it is replaced with process.env.xxx
, making it unusable.
The .env file in the root directory is properly configured.
The error message is as follows:
// dist/server/pages/index.astro.mjs
const WAKATIME_TOKEN = process.env.WAKATIME_TOKEN;
if (!WAKATIME_TOKEN) throw new Error("WAKATIME_TOKEN is not defined");
15:19:11 [ERROR] Error: WAKATIME_TOKEN is not defined
at file:///F:/eya46eya46/dist/server/pages/index.astro.mjs:121:28
at ModuleJob.run (node:internal/modules/esm/module_job:271:25)
at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:547:26)
at async AppPipeline.getModuleForRoute (file:///F:/eya46eya46/dist/server/chunks/_@astrojs-ssr-adapter_Boj1eyKp.mjs:2267:16)
at async NodeApp.render (file:///F:/eya46eya46/dist/server/chunks/_@astrojs-ssr-adapter_Boj1eyKp.mjs:2447:19)
at async file:///F:/eya46eya46/dist/server/chunks/_@astrojs-ssr-adapter_Boj1eyKp.mjs:2806:30
What's the expected result?
Able to correctly handle import.meta.env.xxx
or .env
files.
Link to Minimal Reproducible Example
https://stackblitz.com/edit/withastro-astro-drnr9z?file=src%2Fpages%2Findex.astro
Participation
- I am willing to submit a pull request for this issue.
Thank you for reporting this, we're trying to understand if the issue is related to Astro or Vite specifically. It's probably vite, but we'll keep you posted
I was just about to report this one too. This is also happening with the Cloudflare adapter. Running with astro dev
is totally fine, but building and deploying / running through wrangler will also replace the variable with process.env.VARIABLE_NAME
instead of the actual value of the variable.
It seems like prefixing the variable with PUBLIC_
will allow it to work again, so seems like it might be something weird with server variables?
Reproducible Example: https://stackblitz.com/edit/github-w9xio1?file=src%2Fpages%2Findex.astro
This seems to be the same issue as this behaviour currently where we mutate process.env
:
astro/packages/astro/src/env/vite-plugin-env.ts
Lines 30 to 35 in 350b3da
which we tried to fix before (#12227) but reverted. cc @florian-lefebvre
The issue is that since the new astro:env
feature loads the .env
files to process.env
, it kicks in a different behaviour in the import.meta.env.*
handling in Astro.
astro/packages/astro/src/vite-plugin-env/index.ts
Lines 38 to 58 in 350b3da
Aside from the behaviour being not the most intuitive and is hard to understand (which is where astro:env
comes in), I guess we still have to preserve the old env support and not break it.
may be...
https://vite.dev/guide/env-and-mode.html#env-files
To prevent accidentally leaking env variables to the client, only variables prefixed with VITE_ are exposed to your Vite-processed code. e.g. for the following env variables:
To add to this discussion, my environmental variables did not break after the v5 upgrade on my site dawnforge.app
Not using astro:env
just the standard import.meta.env
syntax, hosted on netlify. They are server variables, not prefixed with PUBLIC
I upgraded to v5 and mine env variables breaks. I was using them with import.meta.env
for example SECRET_PASSWORD
and it stopped working after upgrade.
I had to rewrite them to astro:env/server
with access public
. The access secret
not working in production too. I have hosted it on VPS with Fastify and Nginx with reverse proxy.
The access secret not working in production too.
@Fakerko can you file an issue with a reproduction?
@ematipico minimal reproduction for both, import.meta.env
and astro:env/server
, here: https://codesandbox.io/p/sandbox/nostalgic-hoover-kvycz3
Created .env
file, updated astro.config.mjs
and /src/pages/index.astro
if you run it in dev mode npm run dev
its working, if you build it npm run build
and run it with npm run preview
, it stop working.
The latter is not the same issue, and is not a bug. You'd need to run SECRET_PASSWORD=whatever npm run preview
The latter is not the same issue, and is not a bug. You'd need to run
SECRET_PASSWORD=whatever npm run preview
But that misses the point of using the .env file, doesn't it?
If I have 10 or 20 SECRET variables and I have to specify them every production run, not only will it be a mess, but I'll also have to have secret variables in the package.json
that gets committed to GIT.
Before I upgraded to version 5, everything worked fine using import.meta.env
directly from the .env
file.
Wouldn't import.meta.env
statically replace the secrets during the build?
which are statically replaced at build time
This means that, so far, all your 10/20 secrets have been replaced during the build, so they are in clear inside your built files. If that's what you want, then when using envField
, you must define your secret with public access.
It's possible I might have misunderstood something. Let's keep the discussion going .
That's exactly what I did, I changed access to public. To make it work.
So if I understand it correctly, if I use envField with context "server"
and access: "public"
, the content of the variable is on the server, but still someone can access it? Or am I understanding it wrong and it's fine?
Thanks for the explanation.
but still someone can access it? Or am I understanding it wrong and it's fine?
Yes, the value is statically replaced during the build, which means that the final, compiled code will have the value of the environment variable in the code, e.g.
That's how you run your code during the build
PUBLIC_SECRET=token123 astro build
Somewhere, your bundled JS files, will have this:
export const PUBLIC_SECRET = "token123"
Instead, if your secret contains sensitive information, make the variablesecret
, and don't use import.meta.env
. Eventually, when you run the app, you need to provide it:
SUPER_HIDDEN_SECRET=token123 node ./dist/server/entry.mjs
Okay, thank you for the explanation.
So if I use context: "server"
and access: "public",
the contents of the variable are contained in a bundle on the server in the /dist/server/...
One last question for my clarification:
Is there a real possibility that someone from the outside, for example a site visitor, can get to this data or is this data only accessible on the server to those (those who have access to the server, i.e. the person who has access to the VPS for example)?
Maybe this table should clear things up:
Client (browser) | Backend (server) | |
---|---|---|
client + public |
Visible | Visible |
server + public |
Not visible | Visible |
server + secret |
Not visible | Not Visible |
So, if a contractor who's external to your company has access to your server (VPS, SSH, etc.) and can read the emitted files by your application, they will be able to read the variables:
client
+public
server
+public
@eya46 Can you try this preview release? astro@experimental--astroenv-dev
Seems like that preview fixes this on the Cloudflare adapter for me!
Awesome! We'll most likely release it start of next week