DEV Community

Dana Woodman
Dana Woodman

Posted on • Edited on

Using environment variables in SvelteKit (and Vite)

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"
Enter fullscreen mode Exit fullscreen mode

Then, in your route or component, use import.meta.env.VAR:

<h1>Hello, {import.meta.env.VITE_MESSAGE}</h1>
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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",
    // ...
  }
  // ...
}
Enter fullscreen mode Exit fullscreen mode

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 to env.
  • 🛑 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)

Collapse
 
p6gb profile image
p6gb

This works fine with the svelte-kit dev script but crashes svelte-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?

Collapse
 
timdeschryver profile image
Tim Deschryver

This is probably because your svelte component includes a style tag?
timdeschryver.dev/blog/environment...

Collapse
 
p6gb profile image
p6gb

That might have been it. I am now adding the env variables to session in a hook:

export function getSession() {
    return {
        API_ENDPOINT: import.meta.env.VITE_API_ENDPOINT
    };
}
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
timdeschryver profile image
Tim Deschryver

That's smart!

Collapse
 
danawoodman profile image
Dana Woodman

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?

Collapse
 
amaseal profile image
Amaseal

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

Collapse
 
esojrafael profile image
Jose Rafael

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.

Collapse
 
danawoodman profile image
Dana Woodman

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, like VITE_PRIVATE_SOME_SECRET_TOKEN?

Collapse
 
skit profile image
jj_skit

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.

Collapse
 
barmaleyhd profile image
Dmitry Nagorny

Same questions I had when just learned VITE_ concept. I'm not alone :)

Collapse
 
anthonygushu profile image
Anthony Gushu

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 the compilerOptions in my jsconfig.json fixed the issue.

Collapse
 
danawoodman profile image
Dana Woodman

Glad I could help!

Collapse
 
skit profile image
jj_skit

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?

Collapse
 
oncode profile image
Manuel Sommerhalder

Awesome article, now I'm even more excited to try out SvelteKit!

Collapse
 
danawoodman profile image
Dana Woodman

Awesome! That's the type of stuff I love to hear! 🤓

Collapse
 
jmpark6846 profile image
jmpark6846

thanks for this article. It was confusing to understand but now it became clear