Skip to content

Commit bf7c4e2

Browse files
saibotsivadelliott-with-the-longest-name-on-githubteemingc
authored andcommitted
docs: clarify functionality of $env/* variables (sveltejs#15078)
I spent a lot of time trying to understand the `$env/* variables and how they behave, the docs didn't really seem very fleshed out and I was confused. I wrote up a bunch of demo code to make sure I really understood the behaviour, and then realized that a little love in the docs would probably be appreciated. All sample code has been run locally and validated as correct as of `svelte@5.45.6` (using the `npx sv create` to make a minimal app). Anything that required validation between dev and prod I ran `npm run build`, editing the `.env` file as necessary, and then `npm run preview` to run. ## The overall idea Here's how I broke it down conceptually: | | Runtime | Buildtime | |-|-|-| | Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) | | Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) | Private versus public: - Whether or not it can be imported into client-side code. - Filtering variables based on the `publicPrefix`/`privatePrefix`. Runtime versus buildtime: - Whether or not values change based on platform specifics. - Whether variables make their way into bundled code. --- ### Please don't delete this checklist! Before submitting the PR, please make sure you do the following: - ~~[ ] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs~~ - Could not find an open issue about this, - [x] This message body should clearly illustrate what problems it solves. - ~~[ ] Ideally, include a test that fails without this PR but passes with it.~~ - This PR is documentation only. ### Tests - ~~[ ] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check`~~ - This PR is documentation only, hopefully I don't need to do this 😅 ### Changesets - ~~[ ] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. Changesets that add features should be `minor` and those that fix bugs should be `patch`. Please prefix changeset messages with `feat:`, `fix:`, or `chore:`.~~ - I don't think this needs to appear in a changelog. ### Edits - [x] Please ensure that 'Allow edits from maintainers' is checked. PRs without this option may be closed. --------- Co-authored-by: Elliott Johnson <elliott.johnson@vercel.com> Co-authored-by: Tee Ming <chewteeming01@gmail.com> Co-authored-by: Elliott Johnson <hello@ell.iott.dev>
1 parent 04336fc commit bf7c4e2

File tree

5 files changed

+130
-22
lines changed

5 files changed

+130
-22
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ on:
1313
- '.github/PULL_REQUEST_TEMPLATE.md'
1414
- 'documentation/**'
1515
- 'packages/*/CHANGELOG*.md'
16+
- 'packages/kit/src/types/synthetic/**'
1617
- 'AGENTS.md'
1718
- 'CLAUDE.md'
1819
- 'CONTRIBUTING.md'
Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,43 @@
1-
This module provides access to runtime environment variables, as defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/main/packages/adapter-node) (or running [`vite preview`](https://svelte.dev/docs/kit/cli)), this is equivalent to `process.env`. This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://svelte.dev/docs/kit/configuration#env) (if configured).
1+
This module provides access to environment variables set _dynamically_ at runtime and that are limited to _private_ access.
22

3-
This module cannot be imported into client-side code.
3+
| | Runtime | Build time |
4+
| ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
5+
| Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) |
6+
| Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) |
7+
8+
Dynamic environment variables are defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/main/packages/adapter-node) (or running [`vite preview`](https://svelte.dev/docs/kit/cli)), this is equivalent to `process.env`.
9+
10+
**_Private_ access:**
11+
12+
- This module cannot be imported into client-side code
13+
- This module includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://svelte.dev/docs/kit/configuration#env) (if configured)
14+
15+
> [!NOTE] In `dev`, `$env/dynamic` includes environment variables from `.env`. In `prod`, this behavior will depend on your adapter.
16+
17+
> [!NOTE] To get correct types, environment variables referenced in your code should be declared (for example in an `.env` file), even if they don't have a value until the app is deployed:
18+
>
19+
> ```env
20+
> MY_FEATURE_FLAG=
21+
> ```
22+
>
23+
> You can override `.env` values from the command line like so:
24+
>
25+
> ```sh
26+
> MY_FEATURE_FLAG="enabled" npm run dev
27+
> ```
28+
29+
For example, given the following runtime environment:
30+
31+
```env
32+
ENVIRONMENT=production
33+
PUBLIC_BASE_URL=http://site.com
34+
```
35+
36+
With the default `publicPrefix` and `privatePrefix`:
437

538
```ts
639
import { env } from '$env/dynamic/private';
7-
console.log(env.DEPLOYMENT_SPECIFIC_VARIABLE);
8-
```
940

10-
> [!NOTE] In `dev`, `$env/dynamic` always includes environment variables from `.env`. In `prod`, this behavior will depend on your adapter.
41+
console.log(env.ENVIRONMENT); // => "production"
42+
console.log(env.PUBLIC_BASE_URL); // => undefined
43+
```
Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,46 @@
1-
Similar to [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private), but only includes variables that begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) (which defaults to `PUBLIC_`), and can therefore safely be exposed to client-side code.
1+
This module provides access to environment variables set _dynamically_ at runtime and that are _publicly_ accessible.
22

3-
Note that public dynamic environment variables must all be sent from the server to the client, causing larger network requests — when possible, use `$env/static/public` instead.
3+
| | Runtime | Build time |
4+
| ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
5+
| Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) |
6+
| Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) |
7+
8+
Dynamic environment variables are defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/main/packages/adapter-node) (or running [`vite preview`](https://svelte.dev/docs/kit/cli)), this is equivalent to `process.env`.
9+
10+
**_Public_ access:**
11+
12+
- This module _can_ be imported into client-side code
13+
- **Only** variables that begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) (which defaults to `PUBLIC_`) are included
14+
15+
> [!NOTE] In `dev`, `$env/dynamic` includes environment variables from `.env`. In `prod`, this behavior will depend on your adapter.
16+
17+
> [!NOTE] To get correct types, environment variables referenced in your code should be declared (for example in an `.env` file), even if they don't have a value until the app is deployed:
18+
>
19+
> ```env
20+
> MY_FEATURE_FLAG=
21+
> ```
22+
>
23+
> You can override `.env` values from the command line like so:
24+
>
25+
> ```sh
26+
> MY_FEATURE_FLAG="enabled" npm run dev
27+
> ```
28+
29+
For example, given the following runtime environment:
30+
31+
```env
32+
ENVIRONMENT=production
33+
PUBLIC_BASE_URL=http://example.com
34+
```
35+
36+
With the default `publicPrefix` and `privatePrefix`:
437

538
```ts
639
import { env } from '$env/dynamic/public';
7-
console.log(env.PUBLIC_DEPLOYMENT_SPECIFIC_VARIABLE);
40+
console.log(env.ENVIRONMENT); // => undefined, not public
41+
console.log(env.PUBLIC_BASE_URL); // => "http://example.com"
42+
```
43+
44+
```
45+
846
```
Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
1-
Environment variables [loaded by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files) from `.env` files and `process.env`. Like [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private), this module cannot be imported into client-side code. This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://svelte.dev/docs/kit/configuration#env) (if configured).
1+
This module provides access to environment variables that are injected _statically_ into your bundle at build time and are limited to _private_ access.
22

3-
_Unlike_ [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private), the values exported from this module are statically injected into your bundle at build time, enabling optimisations like dead code elimination.
3+
| | Runtime | Build time |
4+
| ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
5+
| Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) |
6+
| Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) |
47

5-
```ts
6-
import { API_KEY } from '$env/static/private';
7-
```
8+
Static environment variables are [loaded by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files) from `.env` files and `process.env` at build time and then statically injected into your bundle at build time, enabling optimisations like dead code elimination.
89

9-
Note that all environment variables referenced in your code should be declared (for example in an `.env` file), even if they don't have a value until the app is deployed:
10+
**_Private_ access:**
1011

12+
- This module cannot be imported into client-side code
13+
- This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://svelte.dev/docs/kit/configuration#env) (if configured)
14+
15+
For example, given the following build time environment:
16+
17+
```env
18+
ENVIRONMENT=production
19+
PUBLIC_BASE_URL=http://site.com
1120
```
12-
MY_FEATURE_FLAG=""
13-
```
1421

15-
You can override `.env` values from the command line like so:
22+
With the default `publicPrefix` and `privatePrefix`:
23+
24+
```ts
25+
import { ENVIRONMENT, PUBLIC_BASE_URL } from '$env/static/private';
1626

17-
```sh
18-
MY_FEATURE_FLAG="enabled" npm run dev
27+
console.log(ENVIRONMENT); // => "production"
28+
console.log(PUBLIC_BASE_URL); // => throws error during build
1929
```
30+
31+
The above values will be the same _even if_ different values for `ENVIRONMENT` or `PUBLIC_BASE_URL` are set at runtime, as they are statically replaced in your code with their build time values.
Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,31 @@
1-
Similar to [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private), except that it only includes environment variables that begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) (which defaults to `PUBLIC_`), and can therefore safely be exposed to client-side code.
1+
This module provides access to environment variables that are injected _statically_ into your bundle at build time and are _publicly_ accessible.
22

3-
Values are replaced statically at build time.
3+
| | Runtime | Build time |
4+
| ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
5+
| Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) |
6+
| Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) |
7+
8+
Static environment variables are [loaded by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files) from `.env` files and `process.env` at build time and then statically injected into your bundle at build time, enabling optimisations like dead code elimination.
9+
10+
**_Public_ access:**
11+
12+
- This module _can_ be imported into client-side code
13+
- **Only** variables that begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) (which defaults to `PUBLIC_`) are included
14+
15+
For example, given the following build time environment:
16+
17+
```env
18+
ENVIRONMENT=production
19+
PUBLIC_BASE_URL=http://site.com
20+
```
21+
22+
With the default `publicPrefix` and `privatePrefix`:
423

524
```ts
6-
import { PUBLIC_BASE_URL } from '$env/static/public';
25+
import { ENVIRONMENT, PUBLIC_BASE_URL } from '$env/static/public';
26+
27+
console.log(ENVIRONMENT); // => throws error during build
28+
console.log(PUBLIC_BASE_URL); // => "http://site.com"
729
```
30+
31+
The above values will be the same _even if_ different values for `ENVIRONMENT` or `PUBLIC_BASE_URL` are set at runtime, as they are statically replaced in your code with their build time values.

0 commit comments

Comments
 (0)