Are environment variables available at build or only runtime?

My SvelteKit builds fail when I use import { SECRET } from '$env/static/private' or the public equivalent ($env/static/public) with an error such as:
RollupError: "SECRET" is not exported by "virtual:$env/static/private"
RollupError: "SECRET" is not exported by "virtual:$env/static/private"
However accessing environment variables via import { env } from '$env/dynamic/private'; works. Is it correct to assume environment variables created on Cloudflare Pages are only available at runtime?
36 Replies
Hello, I’m Allie!
The build container itself does expose your environment variables(not other bindings) at build time, though as to whether SvelteKit actually passes those in... Looking at it, have you prefixed the variable with VITE_?
stibbs
stibbsOP7mo ago
No, SvelteKit dropped the VITE_ environment variables in SvelteKit 1.0, in favor of clear static vs runtime and private vs public env variables (https://kit.svelte.dev/docs/modules#$env-dynamic-private). Do I need to revert back to using VITE_ when deploying to Cloudflare?
SvelteKit docs
Modules • SvelteKit documentation
Hello, I’m Allie!
Hm... Not sure then, maybe it handles it differently on Pages somehow, since the build environment is entirely separate from the runtime? I would probably ask in the Svelte Discord
stibbs
stibbsOP7mo ago
I've tried moving to dynamic (runtime) env variables and they also don't load. I must be doing something wrong
Hello, I’m Allie!
Those aren't available until your project has been deployed, so that makes sense
stibbs
stibbsOP7mo ago
Sorry I wasn't clear, the build succeeds but they don't load on the deployed site still
Hello, I’m Allie!
Oh... Yeah, in my projects, I just pull them from platform.env, and that appears to work
stibbs
stibbsOP7mo ago
I had not considered that. Does that work for local dev? Do you place them in .dev.vars or something?
Hello, I’m Allie!
Secrets, yeah. You should be able to put them in your wrangler.toml too if they aren't secret
stibbs
stibbsOP7mo ago
That was the trick: creating environment variables in wrangler.toml (and encrypted secrets via dashboard) makes them accessible via the SvelteKit methods in deployed code: - import { env } from '$env/dynamic/private'; for runtime secrets - import { env } from '$env/dynamic/public'; for PUBLIC_ runtime vars - import { SECRET } from '$env/static/private'; for static secrets - import { PUBLIC_KEY } from '$env/static/public'; for PUBLIC_ static vars Locally you will need to maintain parity between .env (to make pnpm run dev work) and wrangler.toml for your deployments to succeed. You can also access them via platform.env.PUBLIC_KEY but I prefer to use the SK way. It is worth noting that you cannot import PUBLIC_ keys using either /private variant, despite this seemingly posing no risk. Those variants exist to ensure you don't accidentally leak secrets into the client, but the opposite risk isn't real (leaking public keys into your server?) Slightly weird but it is clear I suppose 😅
Hello, I’m Allie!
Does dev not also read the wrangler.toml? With the new bindings update, it should?
stibbs
stibbsOP7mo ago
It does read wrangler.toml but it does not appear to map items listed under [vars] to be environment variables. They are accessible via platform.env.KEY but not the SvelteKit methods
Hello, I’m Allie!
Huh... Weird Though now I'm actually wondering what the benefit to using import syntax for vars are, other than just being recommended by the SvelteKit team
stibbs
stibbsOP7mo ago
I just did a little console.log experiment to validate that I like the safety the SvelteKit approach provides. There is no way to accidentally leak secrets into the client using their import methods
Hello, I’m Allie!
Wouldn't that work with platform.env syntax too, since IIRC the platform isn't available to the client at all(unless you pass it down manually somehow)?
stibbs
stibbsOP7mo ago
That's a good point, how do you access the platform vars in client code..? Via a load?
Hello, I’m Allie!
Yeah, probably that. Though you could probably also pass a secret from an import via a load
stibbs
stibbsOP7mo ago
Using the platform.env. approach makes me fear for my future self when I've forgotten what I've done and something goes wrong 😅
stibbs
stibbsOP7mo ago
https://developers.cloudflare.com/workers/configuration/environment-variables/ is clear that wrangler environment variables are bindings, not environment variables. Environment variables are a type of binding that allow you to attach text strings or JSON values to your Worker.
Cloudflare Docs
Environment variables · Cloudflare Workers docs
Attach text strings and JSON values as environment variables to your Worker.
Hello, I’m Allie!
I believe that is because while all variables are bindings, not all bindings are variables If you can't access platform on the client, it should be just as safe though, right?
stibbs
stibbsOP7mo ago
Yes for secrets it would be equivalent. But then you need a workaround for non-secret environment variables as we discussed. Neither approach is "great" The lesser evil is probably just keeping your local dev .env aligned to your wrangler.toml
Hello, I’m Allie!
This may actually warrant a Bug Report, since I would assume that SvelteKit is supposed to pull in Environment Variables irrespective of where they are coming from...
stibbs
stibbsOP7mo ago
It does work when deployed, it's the local dev experience that requires the workaround But you are right I'll submit a bug 🙂 ...do you know where I would do that?
Hello, I’m Allie!
GitHub
GitHub - sveltejs/kit: web development, streamlined
web development, streamlined. Contribute to sveltejs/kit development by creating an account on GitHub.
Hello, I’m Allie!
I don't think it is a wrangler problem, since it is correctly passing in to platform.env
stibbs
stibbsOP7mo ago
Ah right. I was thinking it was a wrangler bug and they could make them accessible as env vars instead of bindings But the other way could also work
Hello, I’m Allie!
Yeah, I was leaning the other way, because the only thing wrangler does in Svelte Dev is to provide the bindings to Svelte(plus the CF object, cache, execution context, etc.). The fact that they are accessible on platform.env means that it is working in that job, so what is failing should just be Svelte passing those variables along to you via the import syntax
stibbs
stibbsOP7mo ago
GitHub
Surface wrangler.toml [vars] as environment variables locally so th...
Describe the problem Local development requires environment variables and secrets to exist in .env if they are to be accessed by SvelteKit's import methods A successful deployment to Cloudflare...
Stigin
Stigin5mo ago
Hey @stibbs sorry to jump in on your thread. I've literally just run into this issue. I have added secrets to my project and i've added "import { env } from '$env/dynamic/private';" with example code:
export const github = new GitHub(
env.GITHUB_CLIENT_ID || '',
env.GITHUB_SECRET || ''
);
export const github = new GitHub(
env.GITHUB_CLIENT_ID || '',
env.GITHUB_SECRET || ''
);
But i'm still not getting un-populated variables. Any thoughts?
Hello, I’m Allie!
Did you try platform.env?
Stigin
Stigin5mo ago
Hey @HardlyWorkin' - thanks for jumping in. Looks like i was using wrangler secret PUT as opposed to wrangler pages secret PUT.... note its just env. with import { env } from '$env/dynamic/private'; albeit the local dev experience is crap and not matched up at all. 🙂
Magick
Magick5mo ago
I've tried adding env vars to both the wrangler.toml and in the dashboard settings > environment variables, but neither works. I consistently get an error like Error: Module '"$env/static/public"' has no exported member 'PUBLIC_SUPABASE_URL'.
Hard@Work
Hard@Work5mo ago
Have you tried platform.env?
Magick
Magick5mo ago
Have you tried platform.env?
Is this is a filename or to be used in code? I've tried: - import { VAR } from '$env/static/public' - import.meta.env.VAR - process.env.VAR - platform.env.VAR this results in ReferenceError [Error]: platform is not defined. None of them have worked.
Hard@Work
Hard@Work5mo ago
It is on the RequestEvent
SvelteKit docs
Types • SvelteKit documentation
Stigin
Stigin5mo ago
How are people handling CRON requirements?
Want results from more Discord servers?
Add your server