Skip to content

Commit f09de07

Browse files
authored
feat: allow dynamic env access during prerender (#14243)
* feat: allow dynamic `env` access during prerender * update docs
1 parent 2ca64db commit f09de07

File tree

11 files changed

+26
-79
lines changed

11 files changed

+26
-79
lines changed

.changeset/neat-items-stay.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': minor
3+
---
4+
5+
feat: allow dynamic `env` access during prerender

packages/kit/src/core/postbuild/analyse.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { load_config } from '../config/index.js';
55
import { forked } from '../../utils/fork.js';
66
import { installPolyfills } from '../../exports/node/polyfills.js';
77
import { ENDPOINT_METHODS } from '../../constants.js';
8-
import { filter_private_env, filter_public_env } from '../../utils/env.js';
8+
import { filter_env } from '../../utils/env.js';
99
import { has_server_load, resolve_route } from '../../utils/routing.js';
1010
import { check_feature } from '../../utils/features.js';
1111
import { createReadableStream } from '@sveltejs/kit/node';
@@ -56,11 +56,10 @@ async function analyse({
5656

5757
// set env, in case it's used in initialisation
5858
const { publicPrefix: public_prefix, privatePrefix: private_prefix } = config.env;
59-
const private_env = filter_private_env(env, { public_prefix, private_prefix });
60-
const public_env = filter_public_env(env, { public_prefix, private_prefix });
59+
const private_env = filter_env(env, private_prefix, public_prefix);
60+
const public_env = filter_env(env, public_prefix, private_prefix);
6161
internal.set_private_env(private_env);
6262
internal.set_public_env(public_env);
63-
internal.set_safe_public_env(public_env);
6463
internal.set_manifest(manifest);
6564
internal.set_read_implementation((file) => createReadableStream(`${server_root}/server/${file}`));
6665

packages/kit/src/core/sync/write_server.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import root from '../root.${isSvelte5Plus() ? 'js' : 'svelte'}';
3232
import { set_building, set_prerendering } from '__sveltekit/environment';
3333
import { set_assets } from '__sveltekit/paths';
3434
import { set_manifest, set_read_implementation } from '__sveltekit/server';
35-
import { set_private_env, set_public_env, set_safe_public_env } from '${runtime_directory}/shared-server.js';
35+
import { set_private_env, set_public_env } from '${runtime_directory}/shared-server.js';
3636
3737
export const options = {
3838
app_template_contains_nonce: ${template.includes('%sveltekit.nonce%')},
@@ -87,7 +87,7 @@ export async function get_hooks() {
8787
};
8888
}
8989
90-
export { set_assets, set_building, set_manifest, set_prerendering, set_private_env, set_public_env, set_read_implementation, set_safe_public_env };
90+
export { set_assets, set_building, set_manifest, set_prerendering, set_private_env, set_public_env, set_read_implementation };
9191
`;
9292

9393
// TODO need to re-run this whenever src/app.html or src/error.html are

packages/kit/src/exports/vite/utils.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import path from 'node:path';
22
import { loadEnv } from 'vite';
33
import { posixify } from '../../utils/filesystem.js';
44
import { negotiate } from '../../utils/http.js';
5-
import { filter_private_env, filter_public_env } from '../../utils/env.js';
5+
import { filter_env } from '../../utils/env.js';
66
import { escape_html } from '../../utils/escape.js';
77
import { dedent } from '../../core/sync/utils.js';
88
import {
@@ -71,8 +71,8 @@ export function get_env(env_config, mode) {
7171
const env = loadEnv(mode, env_config.dir, '');
7272

7373
return {
74-
public: filter_public_env(env, { public_prefix, private_prefix }),
75-
private: filter_private_env(env, { public_prefix, private_prefix })
74+
public: filter_env(env, public_prefix, private_prefix),
75+
private: filter_env(env, private_prefix, public_prefix)
7676
};
7777
}
7878

packages/kit/src/runtime/server/index.js

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,11 @@
11
import { respond } from './respond.js';
2-
import { set_private_env, set_public_env, set_safe_public_env } from '../shared-server.js';
2+
import { set_private_env, set_public_env } from '../shared-server.js';
33
import { options, get_hooks } from '__SERVER__/internal.js';
44
import { DEV } from 'esm-env';
5-
import { filter_private_env, filter_public_env } from '../../utils/env.js';
6-
import { prerendering } from '__sveltekit/environment';
5+
import { filter_env } from '../../utils/env.js';
76
import { set_read_implementation, set_manifest } from '__sveltekit/server';
87
import { set_app } from './app.js';
98

10-
/** @type {ProxyHandler<{ type: 'public' | 'private' }>} */
11-
const prerender_env_handler = {
12-
get({ type }, prop) {
13-
throw new Error(
14-
`Cannot read values from $env/dynamic/${type} while prerendering (attempted to read env.${prop.toString()}). Use $env/static/${type} instead`
15-
);
16-
}
17-
};
18-
199
/** @type {Promise<any>} */
2010
let init_promise;
2111

@@ -44,21 +34,10 @@ export class Server {
4434
// been done already.
4535

4636
// set env, in case it's used in initialisation
47-
const prefixes = {
48-
public_prefix: this.#options.env_public_prefix,
49-
private_prefix: this.#options.env_private_prefix
50-
};
51-
52-
const private_env = filter_private_env(env, prefixes);
53-
const public_env = filter_public_env(env, prefixes);
54-
55-
set_private_env(
56-
prerendering ? new Proxy({ type: 'private' }, prerender_env_handler) : private_env
57-
);
58-
set_public_env(
59-
prerendering ? new Proxy({ type: 'public' }, prerender_env_handler) : public_env
60-
);
61-
set_safe_public_env(public_env);
37+
const { env_public_prefix, env_private_prefix } = this.#options;
38+
39+
set_private_env(filter_env(env, env_private_prefix, env_public_prefix));
40+
set_public_env(filter_env(env, env_public_prefix, env_private_prefix));
6241

6342
if (read) {
6443
// Wrap the read function to handle MaybePromise<ReadableStream>

packages/kit/src/runtime/server/page/render.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { s } from '../../../utils/misc.js';
99
import { Csp } from './csp.js';
1010
import { uneval_action_response } from './actions.js';
1111
import { clarify_devalue_error, handle_error_and_jsonify, serialize_uses } from '../utils.js';
12-
import { public_env, safe_public_env } from '../../shared-server.js';
12+
import { public_env } from '../../shared-server.js';
1313
import { create_async_iterator } from '../../../utils/streaming.js';
1414
import { SVELTE_KIT_ASSETS } from '../../../constants.js';
1515
import { SCHEME } from '../../../utils/url.js';
@@ -558,7 +558,7 @@ export async function render_response({
558558
body,
559559
assets,
560560
nonce: /** @type {string} */ (csp.nonce),
561-
env: safe_public_env
561+
env: public_env
562562
});
563563

564564
// TODO flush chunks as early as we can

packages/kit/src/runtime/shared-server.js

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,11 @@
55
export let private_env = {};
66

77
/**
8-
* `$env/dynamic/public`. When prerendering, this will be a proxy that forbids reads
8+
* `$env/dynamic/public`
99
* @type {Record<string, string>}
1010
*/
1111
export let public_env = {};
1212

13-
/**
14-
* The same as `public_env`, but without the proxy. Use for `%sveltekit.env.PUBLIC_FOO%`
15-
* @type {Record<string, string>}
16-
*/
17-
export let safe_public_env = {};
18-
1913
/** @param {any} error */
2014
export let fix_stack_trace = (error) => error?.stack;
2115

@@ -29,11 +23,6 @@ export function set_public_env(environment) {
2923
public_env = environment;
3024
}
3125

32-
/** @type {(environment: Record<string, string>) => void} */
33-
export function set_safe_public_env(environment) {
34-
safe_public_env = environment;
35-
}
36-
3726
/** @param {(error: Error) => string} value */
3827
export function set_fix_stack_trace(value) {
3928
fix_stack_trace = value;

packages/kit/src/types/internal.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ export interface ServerInternalModule {
4444
set_private_env(environment: Record<string, string>): void;
4545
set_public_env(environment: Record<string, string>): void;
4646
set_read_implementation(implementation: (path: string) => ReadableStream): void;
47-
set_safe_public_env(environment: Record<string, string>): void;
4847
set_version(version: string): void;
4948
set_fix_stack_trace(fix_stack_trace: (error: unknown) => string): void;
5049
get_hooks: () => Promise<Record<string, any>>;

packages/kit/src/types/synthetic/$env+dynamic+private.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ This module provides access to runtime environment variables, as defined by the
22

33
This module cannot be imported into client-side code.
44

5-
Dynamic environment variables cannot be used during prerendering.
6-
75
```ts
86
import { env } from '$env/dynamic/private';
97
console.log(env.DEPLOYMENT_SPECIFIC_VARIABLE);

packages/kit/src/types/synthetic/$env+dynamic+public.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ Similar to [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-pri
22

33
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.
44

5-
Dynamic environment variables cannot be used during prerendering.
6-
75
```ts
86
import { env } from '$env/dynamic/public';
97
console.log(env.PUBLIC_DEPLOYMENT_SPECIFIC_VARIABLE);

0 commit comments

Comments
 (0)