UPDATE August 8, 2022: SvelteKit now has support for both private and public environment variables without directly using Vite, so please refer to the following docs instead of this article:
UPDATE April 13, 2022: the new Svelte FAQ now has this info in it (though I go into a little more detail here in case you're curious)
Setting environment variables in SvelteKit is as simple as creating a .env
file at the base of your repo and add some content to it:
VITE_MESSAGE="World"
SOME_PRIVATE_VAR="You can't see me"
Then, in your route or component, use import.meta.env.VAR
:
<h1>Hello, {import.meta.env.VITE_MESSAGE}</h1>
Which will get you "Hello, World".
Important note: Keys prefixed with VITE_
will be accessible to your components, routes and endpoints and other JS/TS code. Any key not prefixed cannot be imported to prevent leaking keys unintentionally.
Typescript
If you want to type your env vars in Typescript, you can extend ImportMetaEnv
in your global.d.ts
file:
interface ImportMetaEnv {
VITE_MESSAGE: string
}
If you want to use env vars in your endpoints or non-Svelte code and not get TS errors, you'll need to add "module": "es2020"
to your tsconfig.json
:
{
"compilerOptions": {
"module": "es2020",
// ...
}
// ...
}
Security note 🔐
Any environment variable prefixed with VITE_
has the potential to be leaked to the client browser if you use it in your Svelte components. Make sure to do the following to keep potential secrets safe:
- ✅ ALWAYS: Only use secret keys in "endpoints" or other server-side code (e.g. a database connection string, auth token or secret)
- 🛑 NEVER: do something like
const env = import.meta.env
in a component as now anyone can access all the values attached toenv
. - 🛑 NEVER: access your private environment variables in Svelte components or routes (e.g. DON'T do this in a component:
console.log(import.meta.env.VITE_DATABASE_URL)
).
Vite statically replaces any use of an environment variable so import.meta.env.VITE_FOO
will compile down to "foo"
assuming your .env
has VITE_FOO="foo"
in it.
Going further
You can read more about Vite's import.meta.env
here
Note: you cannot use dynamic access of keys, e.g. this won't work: import.meta.env["VITE_MESSAGE"]
. If you need dynamic variables, a solution would be to use svelte-preprocess
's replace
setting.
Fin
Well, that's it for today, give this post a 👍 / 🦄 / 🔖 if it was helpful for ya!
Follow me on Dev.to, Twitter and Github for more web dev and startup related content 🤓
Top comments (16)
This works fine with the
svelte-kit dev
script but crashessvelte-kit build
with the following error:[rollup-plugin-dynamic-import-variables] Unexpected token (6:265)
which points to the line where I use the imported variable in a .svelte file. Any idea why?This is probably because your svelte component includes a style tag?
timdeschryver.dev/blog/environment...
That might have been it. I am now adding the env variables to
session
in a hook:That's smart!
It crashes for you on
npm run build
? It is working fine for me on a fresh SvelteKit project, maybe you can try from scratch to eliminate variables? Do you have a specific adapter you're using?some might still get errors like this even when applying Tim Deshryver's fix, apparently you cant just comment out old code that used this solution
Thanks for the post! Quick question, why would I declare any other variable besides VITE_* if I cant access it in endpoints. What if I have sensitive credentials that I need in an endpoint.
Great question, I don't know the reason Vite went this way ultimately, but I would assume you could have sensitive variables in
.env
and then import them where you need using dotenv or similar. Since Vite isn't designed for Svelte, it likely doesn't know if it is running in an endpoint vs a component, so I think that may be the root cause. Maybe you can prefix your private vars in a way so you don't accidentally like vars, likeVITE_PRIVATE_SOME_SECRET_TOKEN
?Oct 2022. Using Vite/Svelte not Sveltekit and ES6 and dotenv is just not playing ball. Thanks for this post. Wish I had seen it three hours ago! Your suggestion here to prefix VITE and use import.meta.env.VITE worked! Thank you.
Same questions I had when just learned VITE_ concept. I'm not alone :)
Thank you! This helped me figure out the issue I was having when trying to import
.env
vars into my endpoints.The SvelteKit project init had set the ecma version in my eslint
parserOptions
to 2019. Changing that to 2020 and defining thecompilerOptions
in myjsconfig.json
fixed the issue.Glad I could help!
Thanks for this. Using Vite 3.1.0 with Svelte 3.49.0, trying (unsucessfully so far) to get connected to Mongodb without using an Express server. Ran around in circles before I started checking line by line thinking it was mongodb npm package or mongoose, but then realizing it was dotenv not complying. Your solution here worked in that regards.
I wanted to ask you, using import.meta.env.VITE_MESSAGE, works fine in development but how do you use that in production? For example on hosts that allow for environment/config variables, can you simply set these on the host and import.meta.env will pick them up same was as if they were in an .env file?
Awesome article, now I'm even more excited to try out SvelteKit!
Awesome! That's the type of stuff I love to hear! 🤓
thanks for this article. It was confusing to understand but now it became clear