Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 BUG: import.meta env variables not working in server-only code fence in Astro component file *.astro? #2903

Closed
1 task
riledigital opened this issue Mar 27, 2022 · 15 comments · Fixed by #3327
Assignees
Labels
- P4: important Violate documented behavior or significantly impacts performance (priority)

Comments

@riledigital
Copy link

riledigital commented Mar 27, 2022

What version of astro are you using?

0.25.2

What package manager are you using?

pnpm

What operating system are you using?

Mac

Describe the Bug

import.meta env variables not working in server-only Astro component file *.astro?

I've noticed a lot of issues in various threads about environment variables in both Astro and in Vite and wanted to chime in with my own issue I've had: it seems currently that I can't access server-side env variables on Netlify builds with the import.meta.VITE_S_TOKEN convention. My Netlify builds are only running successfully when I use process.env.? I'm on Astro 0.25.2. The builds fail because the JS client fails when passing in an undefined clientId (but the issue isn't with the client)

I'm using a server-only sanityClient.js client js file to fetch data from a CMS and setting up the js client using env variables set through the Netlify UI.
However, using process.env breaks my local astro dev process, where the env vars show up undefined. I have tried using a fallback like import.meta.VITE_S_PROJECT_ID ?? process.env.VITE_S_PROJECT_ID but that doesn't work either, and I'd really like to have both Netlify builds and local dev runs work properly.

Gnarly closed thread on Vite about a similar issue

Example Netlify deploy

Expected text: hello my server variable
Hello my client variable

Actual: Blank
Deploy link

10:39:45 PM: Build ready to start
10:39:49 PM: build-image version: 195fbe127e5c374d9c4758652cb62e3b8936a395 (focal)
10:39:49 PM: build-image tag: v4.6.0
10:39:49 PM: buildbot version: 43c70c62bfed821cfaaabbb50f00238dd4bdd2d6
10:39:49 PM: Fetching cached dependencies
10:39:49 PM: Starting to download cache of 134.2MB
10:39:50 PM: Finished downloading cache in 1.75333425s
10:39:50 PM: Starting to extract cache
10:39:55 PM: Finished extracting cache in 4.850406998s
10:39:55 PM: Finished fetching cache in 6.635595376s
10:39:55 PM: Starting to prepare the repo for build
10:39:56 PM: Preparing Git Reference refs/heads/master
10:39:56 PM: Parsing package.json dependencies
10:39:58 PM: Starting build script
10:39:58 PM: Installing dependencies
10:39:58 PM: Python version set to 2.7
10:39:58 PM: Started restoring cached node version
10:40:00 PM: Finished restoring cached node version
10:40:01 PM: v16.14.2 is already installed.
10:40:01 PM: Now using node v16.14.2 (npm v8.5.0)
10:40:02 PM: Started restoring cached build plugins
10:40:02 PM: Finished restoring cached build plugins
10:40:02 PM: Attempting ruby version 2.7.2, read from environment
10:40:04 PM: Using ruby version 2.7.2
10:40:04 PM: Using PHP version 8.0
10:40:04 PM: Started restoring cached node modules
10:40:04 PM: Finished restoring cached node modules
10:40:05 PM: Started restoring cached go cache
10:40:05 PM: Finished restoring cached go cache
10:40:05 PM: go version go1.16.5 linux/amd64
10:40:05 PM: go version go1.16.5 linux/amd64
10:40:05 PM: Installing missing commands
10:40:05 PM: Verify run directory
10:40:07 PM: ​
10:40:07 PM: ────────────────────────────────────────────────────────────────
10:40:07 PM:   Netlify Build                                                 
10:40:07 PM: ────────────────────────────────────────────────────────────────
10:40:07 PM: ​
10:40:07 PM: ❯ Version
10:40:07 PM:   @netlify/build 26.5.1
10:40:07 PM: ​
10:40:07 PM: ❯ Flags
10:40:07 PM:   baseRelDir: true
10:40:07 PM:   buildId: 623fce71b2755d000801b1ef
10:40:07 PM:   deployId: 623fce71b2755d000801b1f1
10:40:07 PM: ​
10:40:07 PM: ❯ Current directory
10:40:07 PM:   /opt/build/repo
10:40:07 PM: ​
10:40:07 PM: ❯ Config file
10:40:07 PM:   No config file was defined: using default values.
10:40:07 PM: ​
10:40:07 PM: ❯ Context
10:40:07 PM:   production
10:40:07 PM: ​
10:40:07 PM: ────────────────────────────────────────────────────────────────
10:40:07 PM:   1. Build command from Netlify app                             
10:40:07 PM: ────────────────────────────────────────────────────────────────
10:40:07 PM: ​
10:40:07 PM: $ npm run build
10:40:08 PM: > @example/[email protected] build
10:40:08 PM: > astro build
10:40:09 PM: 02:40:09 AM [config] Set "buildOptions.site" to generate correct canonical URLs and sitemap
10:40:09 PM: 02:40:09 AM [build] Initial setup...
10:40:09 PM: 02:40:09 AM [build] Collecting page data...
10:40:11 PM: env variables loading:
10:40:11 PM: { MY_SERVER_VARIABLE: undefined, MY_CLIENT_VARIABLE: undefined }
10:40:11 PM: 02:40:11 AM [build] Completed in 1.14s
10:40:11 PM: 02:40:11 AM [build] Discovering entrypoints...
10:40:11 PM: 02:40:11 AM [build] Building for SSR...
10:40:12 PM: 02:40:12 AM [build] Completed in 1.07s
10:40:12 PM: 
10:40:12 PM:  generating static routes 
10:40:12 PM: env variables loading:
10:40:12 PM: { MY_SERVER_VARIABLE: undefined, MY_CLIENT_VARIABLE: undefined }
10:40:12 PM: </> src/pages/index.astro
10:40:12 PM: { MY_SERVER_VARIABLE: undefined, MY_CLIENT_VARIABLE: undefined }
10:40:12 PM:     ┃ / +14ms
10:40:12 PM: Completed in 80ms
10:40:12 PM: 
10:40:12 PM: 02:40:12 AM [build] 1 pages built in 2.31s (2309ms avg per page + resources)
10:40:12 PM: 02:40:12 AM [build] 🚀 Done
10:40:14 PM: ​
10:40:14 PM: (build.command completed in 6.5s)
10:40:14 PM: ​
10:40:14 PM: ────────────────────────────────────────────────────────────────
10:40:14 PM: Creating deploy upload records
10:40:14 PM:   2. Deploy site                                                
10:40:14 PM: ────────────────────────────────────────────────────────────────
10:40:14 PM: ​
10:40:14 PM: Starting to deploy site from 'dist'
10:40:14 PM: Creating deploy tree 
10:40:14 PM: 2 new files to upload
10:40:14 PM: 0 new functions to upload
10:40:14 PM: Site deploy was successfully initiated
10:40:14 PM: ​
10:40:14 PM: (Deploy site completed in 694ms)
10:40:14 PM: ​
10:40:14 PM: Starting post processing
10:40:14 PM: ────────────────────────────────────────────────────────────────
10:40:14 PM:   Netlify Build Complete                                        
10:40:14 PM: ────────────────────────────────────────────────────────────────
10:40:14 PM: ​
10:40:14 PM: Post processing - HTML
10:40:14 PM: (Netlify Build completed in 7.2s)
10:40:15 PM: Caching artifacts
10:40:15 PM: Started saving node modules
10:40:15 PM: Finished saving node modules
10:40:15 PM: Started saving build plugins
10:40:15 PM: Finished saving build plugins
10:40:15 PM: Started saving pip cache
10:40:15 PM: Finished saving pip cache
10:40:15 PM: Started saving emacs cask dependencies
10:40:15 PM: Finished saving emacs cask dependencies
10:40:15 PM: Post processing - header rules
10:40:15 PM: Started saving maven dependencies
10:40:15 PM: Finished saving maven dependencies
10:40:15 PM: Started saving boot dependencies
10:40:15 PM: Finished saving boot dependencies
10:40:15 PM: Post processing - redirect rules
10:40:15 PM: Started saving rust rustup cache
10:40:15 PM: Finished saving rust rustup cache
10:40:15 PM: Started saving go dependencies
10:40:15 PM: Post processing done
10:40:15 PM: Finished saving go dependencies
10:40:15 PM: Build script success
10:40:18 PM: Site is live ✨
10:40:40 PM: Finished processing build request in 51.227811809s

Link to Minimal Reproducible Example

https://stackblitz.com/edit/github-crbayc?file=src/client.js

Participation

  • I am willing to submit a pull request for this issue.
@sciencefidelity
Copy link

For private server side only variables like the Sanity token use import.meta.env.S_TOKEN.

For public client side variables use prefix the variable with PUBLIC_, so to get the Sanity project id use import.meta.env.PUBLIC_S_PROJECT_ID. I've been able to deploy to Netlify and Vercel with using these.

https://docs.astro.build/en/guides/environment-variables/

I've replied on Discord.

@riledigital
Copy link
Author

riledigital commented Mar 28, 2022

Hey, thanks for looking at this and sharing some examples.

Do you know why the Sanity ID would be prefixed as client-side when I am only using it on the server in the component script, which should be server-only per the Astro docs?

Regardless of the Sanity client, it seems like the non-Sanity-specific env variables in my minimal reproducible example aren't behaving as expected, unless I'm misunderstanding how the Astro component code fence works.
from Astro:

The code fence is designed to guarantee that the JavaScript that you write in it is “fenced in.” It won’t escape into your frontend application, or fall into your users hands. You can safely write code here that is expensive or sensitive (like a call to your private database) without worrying about it ever ending up in your user’s browser.

@riledigital riledigital changed the title 🐛 BUG: server-only environment variables with import.meta.env undefined on Netlify build step 🐛 BUG: import.meta env variables not working in server-only Astro component file *.astro? Mar 28, 2022
@riledigital riledigital changed the title 🐛 BUG: import.meta env variables not working in server-only Astro component file *.astro? 🐛 BUG: import.meta env variables not working in server-only code fence in Astro component file *.astro? Mar 28, 2022
@sciencefidelity
Copy link

@riledigital
Copy link
Author

riledigital commented Mar 29, 2022

Thanks, but that example doesn't illustrate the problem in my example where I am using env variables within a server-only script imported in the Astro code fence.

@natemoo-re
Copy link
Member

@riledigital Looking at your example, I see that the environment variables are all undefined, but I don't know where you've actually tried to define them... can you clarify?

@riledigital
Copy link
Author

riledigital commented Mar 30, 2022

@natemoo-re Sorry, I added back.env to the example. (forgot about .gitignore)

Here are steps to reproduce:

  • Define variables in .env file

  • Define same variables in Netlify UI
    Screen Shot 2022-03-30 at 10 20 38 AM

  • Use both import.meta.env and process.env in ./src/client.js and export their values

  • Import the values from client.js inside of ./src/pages/index.astro

  • Run npm run dev and see that all 3 env variables render properly

  • Build to Netlify and see that they are undefined in logs:

Netlify log
10:21:44 AM: ────────────────────────────────────────────────────────────────
10:21:44 AM:   1. Build command from Netlify app                             
10:21:44 AM: ────────────────────────────────────────────────────────────────
10:21:44 AM: ​
10:21:44 AM: $ npm run build
10:21:44 AM: > @example/[email protected] build
10:21:44 AM: > astro build
10:21:46 AM: 02:21:46 PM [config] Set "buildOptions.site" to generate correct canonical URLs and sitemap
10:21:46 AM: 02:21:46 PM [build] Initial setup...
10:21:46 AM: 02:21:46 PM [build] Collecting page data...
10:21:47 AM: env variables loading:
10:21:47 AM: {
10:21:47 AM:   MY_SERVER_VARIABLE: undefined,
10:21:47 AM:   MY_CLIENT_VARIABLE: undefined,
10:21:47 AM:   MY_FALLBACK_VARIABLE: 'i am a fallback variable'
10:21:47 AM: }
10:21:47 AM: 02:21:47 PM [build] Completed in 0.90s
10:21:47 AM: 02:21:47 PM [build] Discovering entrypoints...
10:21:47 AM: 02:21:47 PM [build] Building for SSR...
10:21:47 AM: 02:21:47 PM [build] Completed in 0.84s
10:21:47 AM: 
10:21:47 AM:  generating static routes 
10:21:47 AM: env variables loading:
10:21:47 AM: {
10:21:47 AM:   MY_SERVER_VARIABLE: undefined,
10:21:47 AM:   MY_CLIENT_VARIABLE: undefined,
10:21:47 AM:   MY_FALLBACK_VARIABLE: 'i am a fallback variable'
10:21:47 AM: }
10:21:47 AM:  src/pages/index.astro
10:21:47 AM: {
10:21:47 AM:   MY_SERVER_VARIABLE: undefined,
10:21:47 AM:   MY_CLIENT_VARIABLE: undefined,
10:21:47 AM:   MY_FALLBACK_VARIABLE: 'i am a fallback variable'
10:21:47 AM: }
10:21:47 AM:     ┃ / +13ms
10:21:47 AM: Completed in 33ms
10:21:47 AM: 
10:21:47 AM: 02:21:47 PM [build] 1 pages built in 1.78s (1777ms avg per page + resources)
10:21:47 AM: 02:21:47 PM [build] 🚀 Done
10:21:49 AM: ​
10:21:49 AM: (build.command completed in 4.9s)
10:21:49 AM: 

@sciencefidelity
Copy link

@riledigital Thanks for clarifying. I downloaded your example, removed the process.env fallback and changed VITE_ to PUBLIC_. I deployed to Netlify – with these changes only MY_CLIENT_VARIABLE is defined.

I tried with one of my Sanity projects by changing PUBLIC_SANITY_PROJECT_ID to SANITY_PROJECT_ID. The build fails on Netlify, Error: Configuration must contain 'projectId'.

@Atmos4
Copy link

Atmos4 commented Apr 9, 2022

This is my take on this, after being stuck for a couple hours:

The env variables you setup with Netlify UI cannot be accessed by Vite, and hence are not accessible with import.meta.env. You need to use process.env.

So the first step is to make sure you use a .env.development file (and a .env.local for your local builds).
Then you can setup a module and import it in your .astro components. Here is a quick example:

// /src/utils/envHelper.js
function getSomeEnvVariable() {
  return import.meta.env.SOME_ENV_VARIABLE ?? process.env.SOME_ENV_VARIABLE ;
}

export default getSomeEnvVariable;

@rschristian
Copy link
Contributor

rschristian commented Apr 11, 2022

(Just in case more context is helpful)

Currently writing a custom integration, and when Astro is building the client, console.log(import.meta.env); results in the following:

{
  BASE_URL: '/',
  MODE: 'production',
  DEV: false,
  PROD: true,
  SSR: true
}

Come time to generate static routes, however, and import.meta.env is undefined. process.env is not affected, however, and consistently works.

@pdkn
Copy link

pdkn commented Apr 20, 2022

Have same issue trying to integrate with Datocms. It's not ideal having to access env vars differently based on local/serve build

const token = import.meta.env.DATOCMS_API_TOKEN ?? process.env.DATOCMS_API_TOKEN;

Not sure what the answer is at moment. Or if Netlify is able to pick this up as a bug to fix their end for astro projects. Just commented to add support for this issue.

@natemoo-re natemoo-re added - P4: important Violate documented behavior or significantly impacts performance (priority) s1-small and removed bb:investigate labels May 10, 2022
@natemoo-re
Copy link
Member

Okay, definitely some weird behavior here. I'm going to take a look at this and try to fix it.

georgeblahblah added a commit to guardian/guardian-engineering-site that referenced this issue Jul 6, 2022
Now that withastro/astro#2903 has been fixed,
we can remove the workaround of loading from process.env
@garethweaver
Copy link

garethweaver commented Jun 22, 2023

Just to add more info here if anyone else is struggling.

We run Astro with @astrojs/node and mode: "standalone" as shown here in the docs. We then deploy it in a Docker container on to Heroku (for now).

I found that when using the PUBLIC_ prefix my envs would always be an empty string. When I swapped to using the ASTRO_ or VITE_ prefix I found that I could set my envs perfectly fine in Heroku, and see them passed into the Docker container to be consumed in client-side Astro code. Very odd stuff.

@morriq
Copy link

morriq commented Oct 27, 2023

It looks it no longer works, @garethweaver . I have the same setup as you have but I have to use process.env

@tobitestra
Copy link

tobitestra commented Mar 30, 2024

We're deploying to cloudflare for evaluating some Astro beahaviors and ran into some similar issues with the difference between:

  1. import.meta.env
  2. process.env

We need runtime configuration that is not exposed to the public. At the moment we fetch an "/app-config.json" through a middleware and make it available to astro using Astro.locals).
So we are investigating how ENV variables could help us here, since the above solution makes the config json available to "everybody that knows the path".

We actually have two CF workers running for the same project...:

  1. for testing the auto ci+cd features of CF, so each time we push to git, a build and deploy starts running automatically in cf...
  2. for testing the cli based deployment via an ide like vscode etc. (npm run deploy => astro build && wrangler pages deploy ./dist --commit-dirty=true --branch=production)

Testsetup:

This is our .env.development file:

PUBLIC_TOBITEST="PUBLIC_TOBITEST-DEV"
SECRET_TOBITEST="SECRET_TOBITEST-DEV"
VITE_TOBITEST="VITE_TOBITEST-DEV"

This is our CF environment variable configuration:

PUBLIC_TOBITEST=PUBLIC_TOBITEST-PROD
SECRET_TOBITEST=SECRET_TOBITEST-PROD
VITE_TOBITEST=VITE_TOBITEST-PROD

This is how we try to access (and display) them in our .astro component:

const tobiTestEnv1 = import.meta.env.PUBLIC_TOBITEST
const tobiTestEnv2 = process.env.PUBLIC_TOBITEST
const tobiTestEnv3 = import.meta.env.VITE_TOBITEST
const tobiTestEnv4 = process.env.VITE_TOBITEST
const tobiTestEnv5 = import.meta.env.SECRET_TOBITEST
const tobiTestEnv6 = process.env.SECRET_TOBITEST

This is what we get on localhost:

Tobitest1 from env meta: PUBLIC_TOBITEST-DEV
Tobitest2 from env process: 
Tobitest3 from env meta: VITE_TOBITEST-DEV
Tobitest4 from env process: 
Tobitest5 from env meta: SECRET_TOBITEST-DEV
Tobitest6 from env process:

This is what we get on cf worker #1

Tobitest1 from env meta: PUBLIC_TOBITEST-PROD
Tobitest2 from env process: PUBLIC_TOBITEST-PROD
Tobitest3 from env meta: VITE_TOBITEST-PROD
Tobitest4 from env process: VITE_TOBITEST-PROD
Tobitest5 from env meta: SECRET_TOBITEST-PROD
Tobitest6 from env process: SECRET_TOBITEST-PROD

This is what we get on cf worker #2

Tobitest1 from env meta: 
Tobitest2 from env process: PUBLIC_TOBITEST-PROD
Tobitest3 from env meta: 
Tobitest4 from env process: VITE_TOBITEST-PROD
Tobitest5 from env meta: 
Tobitest6 from env process: SECRET_TOBITEST-PROD

Does anyone have any clue on how to explain this?
localhost: meta works, process not, ok
cf worker 1: both work, ok perfect
cf worker 2: meta not, process works, why not both as in worker1?

@grohart
Copy link

grohart commented Aug 12, 2024

I had similar issue while using node adapter. For example, with these vars in my .env file:

PUBLIC_SOMETHING=hello
MY_SECRET=bye

In my .astro files, or my .ts endpoints, middleware or libraries:

import.meta.env.PUBLIC_SOMETHING: hello
import.meta.env.MY_SECRET: undefined

I had to install dotenv and dotenv-cli packages to my project and then add the following lines in my package.json file:

"scripts": {
    "dev": "astro dev",
    "start": "dotenv -e .env node ./dist/server/entry.mjs",
    "build": "astro check --minimumSeverity error && astro build",
    "preview": "astro preview",
    "astro": "astro"
  },

Now:

import.meta.env.PUBLIC_SOMETHING: hello
import.meta.env.MY_SECRET: bye

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
- P4: important Violate documented behavior or significantly impacts performance (priority)
Projects
None yet
Development

Successfully merging a pull request may close this issue.