Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions .changeset/wet-suits-help.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
'astro': major
---

Updates `import.meta.env` values to always be inlined

In Astro 5.13, the `experimental.staticImportMetaEnv` was introduced to update the behavior when accessing `import.meta.env` directly to align with [Vite's handling of environment variables](https://vite.dev/guide/env-and-mode.html#env-variables) and ensures that `import.meta.env` values are always inlined.

In Astro 5.x, non-public environment variables were replaced by a reference to `process.env`. Additionally, Astro could also convert the value type of your environment variables used through `import.meta.env`, which could prevent access to some values such as the strings `"true"` (which was converted to a boolean value), and `"1"` (which was converted to a number).

Astro 6 removes this experimental flag and makes this the new default behavior in Astro: `import.meta.env` values are always inlined and never coerced.

#### What should I do?

If you were previously using this experimental feature, you must remove this experimental flag from your configuration as it no longer exists:

```diff
// astro.config.mjs
import { defineConfig } from 'astro/config';

export default defineConfig({
experimental: {
- staticImportMetaEnv: true,
},
})
```

If you were relying on coercion, you may need to update your project code to apply it manually:

```diff
// src/components/MyComponent.astro
-const enabled: boolean = import.meta.env.ENABLED;
+const enabled: boolean = import.meta.env.ENABLED === "true";
```

If you were relying on the transformation into `process.env`, you may need to update your project code to apply it manually:

```diff
// src/components/MyComponent.astro
-const enabled: boolean = import.meta.env.DB_PASSWORD;
+const enabled: boolean = process.env.DB_PASSWORD;
```

You may also need to update types:

```diff
// src/env.d.ts
interface ImportMetaEnv {
readonly PUBLIC_POKEAPI: string;
- readonly DB_PASSWORD: string;
- readonly ENABLED: boolean;
+ readonly ENABLED: string;
}

interface ImportMeta {
readonly env: ImportMetaEnv;
}

+namespace NodeJS {
+ interface ProcessEnv {
+ DB_PASSWORD: string;
+ }
+}
```

If you need more control over environment variables in Astro, we recommend you use `astro:env`.
5 changes: 0 additions & 5 deletions packages/astro/src/core/config/schemas/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ export const ASTRO_CONFIG_DEFAULTS = {
preserveScriptOrder: false,
liveContentCollections: false,
csp: false,
staticImportMetaEnv: false,
chromeDevtoolsWorkspace: false,
failOnPrerenderConflict: false,
},
Expand Down Expand Up @@ -500,10 +499,6 @@ export const AstroConfigSchema = z.object({
])
.optional()
.default(ASTRO_CONFIG_DEFAULTS.experimental.csp),
staticImportMetaEnv: z
.boolean()
.optional()
.default(ASTRO_CONFIG_DEFAULTS.experimental.staticImportMetaEnv),
chromeDevtoolsWorkspace: z
.boolean()
.optional()
Expand Down
1 change: 0 additions & 1 deletion packages/astro/src/core/create-vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ export async function createVite(
const envLoader = createEnvLoader({
mode,
config: settings.config,
useStatic: settings.config.experimental.staticImportMetaEnv,
});

// Start with the Vite configuration that Astro core needs
Expand Down
26 changes: 3 additions & 23 deletions packages/astro/src/env/env-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ const isValidIdentifierRe = /^[_$a-zA-Z][\w$]*$/;
function getPrivateEnv({
fullEnv,
viteConfig,
useStatic,
}: {
fullEnv: Record<string, string>;
viteConfig: AstroConfig['vite'];
useStatic: boolean;
}): Record<string, string> {
let envPrefixes: string[] = ['PUBLIC_'];
if (viteConfig.envPrefix) {
Expand All @@ -32,37 +30,19 @@ function getPrivateEnv({
if (!isValidIdentifierRe.test(key) || envPrefixes.some((prefix) => key.startsWith(prefix))) {
continue;
}
// Only replace with process.env if not static
// TODO: make static the default and only way to do this in Astro 6
if (!useStatic && typeof process.env[key] !== 'undefined') {
let value = process.env[key];
// Replacements are always strings, so try to convert to strings here first
if (typeof value !== 'string') {
value = `${value}`;
}
// Boolean values should be inlined to support `export const prerender`
// We already know that these are NOT sensitive values, so inlining is safe
if (value === '0' || value === '1' || value === 'true' || value === 'false') {
privateEnv[key] = value;
} else {
privateEnv[key] = `process.env.${key}`;
}
} else {
privateEnv[key] = JSON.stringify(fullEnv[key]);
}
privateEnv[key] = JSON.stringify(fullEnv[key]);
}
return privateEnv;
}

interface EnvLoaderOptions {
mode: string;
config: AstroConfig;
useStatic: boolean;
}

function getEnv({ mode, config, useStatic }: EnvLoaderOptions) {
function getEnv({ mode, config }: EnvLoaderOptions) {
const loaded = loadEnv(mode, config.vite.envDir ?? fileURLToPath(config.root), '');
const privateEnv = getPrivateEnv({ fullEnv: loaded, viteConfig: config.vite, useStatic });
const privateEnv = getPrivateEnv({ fullEnv: loaded, viteConfig: config.vite });

return { loaded, privateEnv };
}
Expand Down
18 changes: 0 additions & 18 deletions packages/astro/src/types/public/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2411,24 +2411,6 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
*/
liveContentCollections?: boolean;

/**
* @name experimental.staticImportMetaEnv
* @type {boolean}
* @default `false`
* @version 5.13
* @description
*
* Disables replacement of `import.meta.env` values with `process.env` calls and their coercion
*
* Currently, non-public `import.meta.env` environment variables are replaced by a reference to `process.env`. Additionally, Astro may also convert the value type of your environment variables used through `import.meta.env`, which can prevent access to some values such as the strings `"true"` (which is converted to a boolean value), and `"1"` (which is converted to a number).
*
* The `experimental.staticImportMetaEnv` flag simplifies Astro's default behavior, making it easier to understand and use. Astro will no longer replace any `import.meta.env` environment variables with a `process.env` call, nor will it coerce values.
*
* This flag aligns `import.meta.env`'s behavior in Astro with [Vite](https://vite.dev/guide/env-and-mode.html#env-variables).
*
* See the [experimental static `import.meta.env` docs](https://docs.astro.build/en/reference/experimental-flags/static-import-meta-env/) for more information.
*/
staticImportMetaEnv?: boolean;
/**
* @name experimental.chromeDevtoolsWorkspace
* @type {boolean}
Expand Down
4 changes: 2 additions & 2 deletions packages/astro/test/astro-envs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ describe('Environment Variables', () => {
assert.equal(found, false, 'found the private env variable in the JS build');
});

it('does not coerce environment variable values when experimental.staticImportMetaEnv is true', async () => {
it('does not coerce environment variable values', async () => {
let indexHtml = await fixture.readFile('/index.html');
assert.equal(indexHtml.includes('typeof BOOLEAN_VAR is string'), true);
assert.equal(indexHtml.includes('typeof NUMBER_VAR is string'), true);
Expand Down Expand Up @@ -167,7 +167,7 @@ describe('Environment Variables', () => {
delete process.env.SECRET_PLACE;
});

it('does not turn import.meta.env into process.env when experimental.staticImportMetaEnv is true', async () => {
it('does not turn import.meta.env into process.env', async () => {
const request = new Request('http://example.com/');
const response = await app.render(request);
const html = await response.text();
Expand Down
3 changes: 0 additions & 3 deletions packages/astro/test/fixtures/astro-envs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,4 @@ export default defineConfig({
},
],
},
experimental: {
staticImportMetaEnv: true,
}
});
Loading