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:
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
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_
?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
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
I've tried moving to dynamic (runtime) env variables and they also don't load. I must be doing something wrong
Those aren't available until your project has been deployed, so that makes sense
Sorry I wasn't clear, the build succeeds but they don't load on the deployed site still
Oh... Yeah, in my projects, I just pull them from
platform.env
, and that appears to workI had not considered that. Does that work for local dev? Do you place them in
.dev.vars
or something?Secrets, yeah. You should be able to put them in your
wrangler.toml
too if they aren't secretThat 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 😅Does dev not also read the
wrangler.toml
? With the new bindings update, it should?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 methodsHuh...
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 teamI 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
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)?That's a good point, how do you access the platform vars in client code..?
Via a
load
?Yeah, probably that. Though you could probably also pass a secret from an
import
via a loadUsing the
platform.env.
approach makes me fear for my future self when I've forgotten what I've done and something goes wrong 😅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.
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?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
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...
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?
GitHub
GitHub - sveltejs/kit: web development, streamlined
web development, streamlined. Contribute to sveltejs/kit development by creating an account on GitHub.
I don't think it is a
wrangler
problem, since it is correctly passing in to platform.env
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
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
syntaxGitHub
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...
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:
But i'm still not getting un-populated variables. Any thoughts?
Did you try
platform.env
?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.
🙂
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 [31mError[39m: Module '"$env/static/public"' has no exported member 'PUBLIC_SUPABASE_URL'.
Have you tried
platform.env
?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.It is on the
RequestEvent
SvelteKit docs
Types • SvelteKit documentation
How are people handling CRON requirements?