Skip to content

Conversation

@teemingc
Copy link
Member

@teemingc teemingc commented Feb 4, 2026

closes #15212
and helps with #1485

This PR writes the virtual env modules to disk so that they can be used in files that run outside of the Vite pipeline.

Some thoughts while implementing this:

  • It's not very nice that secrets can now exist in both the .env file and the generated module. But maybe it's fine because it's gitignored and bound to be overwritten when updated and sync runs? the dynamic module no longer serialises the .env file
  • svelte-kit sync used to only generate types but now it generates modules too so that we can use $env without starting the dev server.
  • I noticed our test apps had tests in a "test" folder instead of "tests" (plural). Is that on purpose? Or should we include both variations in the generated tsconfig.json in case of mistakes like this? created fix: include test directory in generated tsconfig.json #15254

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
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with pnpm test and lint the project with pnpm lint and pnpm check

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:.

Edits

  • Please ensure that 'Allow edits from maintainers' is checked. PRs without this option may be closed.

@changeset-bot
Copy link

changeset-bot bot commented Feb 4, 2026

🦋 Changeset detected

Latest commit: 9cc1ebe

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sveltejs/kit Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@teemingc teemingc marked this pull request as draft February 4, 2026 11:12
@benmccann
Copy link
Member

I noticed our test apps had tests in a "test" folder instead of "tests" (plural). Is that on purpose? Or should we include both variations in the generated tsconfig.json in case of mistakes like this?

I don't know if one vs the other is better. sv doesn't create other, so I'm not sure we've decided on a preference as a group. If I search the SvelteKit node_modules it seems that test is way more popular than tests. I don't have any objection to including both variations so that users can choose which they prefer

@benmccann
Copy link
Member

It's not very nice that secrets can now exist in both the .env file and the generated module. But maybe it's fine because it's gitignored and bound to be overwritten when updated and sync runs?

I guess only the STATIC secrets need to be? Because presumably the DYNAMIC secrets get read from .env on disk. The STATIC secrets already get embedded into the build output, so I don't think this is anything new or anything to worry about

@benmccann
Copy link
Member

One last thought... Even though this isn't a breaking change, I would personally add it to the 3.0 milestone because it is highly demanded and I think that people are more likely to learn about it if it's part of the 3.0 release notes and it will make the 3.0 release more exciting

Comment on lines -64 to -78
/**
* Load environment variables from process.env and .env files
* @param {import('types').ValidatedKitConfig['env']} env_config
* @param {string} mode
*/
export function get_env(env_config, mode) {
const { publicPrefix: public_prefix, privatePrefix: private_prefix } = env_config;
const env = loadEnv(mode, env_config.dir, '');

return {
public: filter_env(env, public_prefix, private_prefix),
private: filter_env(env, private_prefix, public_prefix)
};
}

Copy link
Member Author

@teemingc teemingc Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be moved to a separate module to avoid type errors when users import $env/dynamic/* and they type check their code. We're currently using it in the generated module to avoid serialising users' dynamic env vars

@teemingc teemingc marked this pull request as ready for review February 4, 2026 20:31
@ottomated
Copy link
Contributor

Are there plans to include $app/environment too?

@teemingc
Copy link
Member Author

teemingc commented Feb 4, 2026

Are there plans to include $app/environment too?

Yes, but I'm wondering if it's just about making everything in $app/* importable or if folks want to be able to mock them more easily too. Let's continue the discussion in #1485 (comment)

Comment on lines +17 to +37
test.describe('$env access outside the Vite pipeline', () => {
test('$env/static/public', async () => {
const env = await import('$env/static/public');
expect(env.PUBLIC_DYNAMIC).toBe('accessible anywhere/evaluated at run time');
});

test('$env/static/private', async () => {
const env = await import('$env/static/private');
expect(env.PRIVATE_STATIC).toBe('accessible to server-side code/replaced at build time');
});

test('$env/dynamic/public', async () => {
const { env } = await import('$env/dynamic/public');
expect(env.PUBLIC_DYNAMIC).toBe('accessible anywhere/evaluated at run time');
});

test('$env/dynamic/private', async () => {
const { env } = await import('$env/dynamic/private');
expect(env.PRIVATE_DYNAMIC).toBe('accessible to server-side code/evaluated at run time');
});
});
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also change these to Playwright component tests, which is what the majority of users are facing issues with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace virtual modules with generated modules

3 participants