summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Florian Lefebvre <contact@florian-lefebvre.dev> 2025-01-13 16:09:44 +0100
committerGravatar GitHub <noreply@github.com> 2025-01-13 16:09:44 +0100
commit80067c032f9ce5852f3315d1046b2d0c220ddcd5 (patch)
tree04aed0b4a76f2a1c406e3f0f7f116f679f75fbbc
parent3aff68a4195a608e92dc6299610a4b06e7bb96f1 (diff)
downloadastro-80067c032f9ce5852f3315d1046b2d0c220ddcd5.tar.gz
astro-80067c032f9ce5852f3315d1046b2d0c220ddcd5.tar.zst
astro-80067c032f9ce5852f3315d1046b2d0c220ddcd5.zip
fix: load env earlier (#12977)
-rw-r--r--.changeset/cool-rings-tell.md5
-rw-r--r--packages/astro/src/core/create-vite.ts8
-rw-r--r--packages/astro/src/env/README.md (renamed from packages/astro/src/vite-plugin-env/README.md)6
-rw-r--r--packages/astro/src/env/env-loader.ts15
-rw-r--r--packages/astro/src/env/vite-plugin-env.ts56
-rw-r--r--packages/astro/src/env/vite-plugin-import-meta-env.ts (renamed from packages/astro/src/vite-plugin-env/index.ts)4
-rw-r--r--packages/astro/test/astro-sync.test.js7
-rw-r--r--packages/astro/test/fixtures/astro-env-content-collections/src/content.config.ts7
8 files changed, 65 insertions, 43 deletions
diff --git a/.changeset/cool-rings-tell.md b/.changeset/cool-rings-tell.md
new file mode 100644
index 000000000..11c2fd981
--- /dev/null
+++ b/.changeset/cool-rings-tell.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fixes a case where accessing `astro:env` APIs or `import.meta.env` inside the content config file would not work
diff --git a/packages/astro/src/core/create-vite.ts b/packages/astro/src/core/create-vite.ts
index cad0dbc3c..1431c698e 100644
--- a/packages/astro/src/core/create-vite.ts
+++ b/packages/astro/src/core/create-vite.ts
@@ -14,6 +14,7 @@ import {
} from '../content/index.js';
import { createEnvLoader } from '../env/env-loader.js';
import { astroEnv } from '../env/vite-plugin-env.js';
+import { importMetaEnv } from '../env/vite-plugin-import-meta-env.js';
import astroInternationalization from '../i18n/vite-plugin-i18n.js';
import astroPrefetch from '../prefetch/vite-plugin-prefetch.js';
import astroDevToolbar from '../toolbar/vite-plugin-dev-toolbar.js';
@@ -23,7 +24,6 @@ import astroPostprocessVitePlugin from '../vite-plugin-astro-postprocess/index.j
import { vitePluginAstroServer } from '../vite-plugin-astro-server/index.js';
import astroVitePlugin from '../vite-plugin-astro/index.js';
import configAliasVitePlugin from '../vite-plugin-config-alias/index.js';
-import envVitePlugin from '../vite-plugin-env/index.js';
import vitePluginFileURL from '../vite-plugin-fileurl/index.js';
import astroHeadPlugin from '../vite-plugin-head/index.js';
import astroHmrReloadPlugin from '../vite-plugin-hmr-reload/index.js';
@@ -124,7 +124,7 @@ export async function createVite(
});
const srcDirPattern = glob.convertPathToPattern(fileURLToPath(settings.config.srcDir));
- const envLoader = createEnvLoader();
+ const envLoader = createEnvLoader(mode, settings.config);
// Start with the Vite configuration that Astro core needs
const commonConfig: vite.InlineConfig = {
@@ -148,8 +148,8 @@ export async function createVite(
// The server plugin is for dev only and having it run during the build causes
// the build to run very slow as the filewatcher is triggered often.
command === 'dev' && vitePluginAstroServer({ settings, logger, fs, manifest, ssrManifest }), // ssrManifest is only required in dev mode, where it gets created before a Vite instance is created, and get passed to this function
- envVitePlugin({ envLoader }),
- astroEnv({ settings, mode, sync, envLoader }),
+ importMetaEnv({ envLoader }),
+ astroEnv({ settings, sync, envLoader }),
markdownVitePlugin({ settings, logger }),
htmlVitePlugin(),
astroPostprocessVitePlugin(),
diff --git a/packages/astro/src/vite-plugin-env/README.md b/packages/astro/src/env/README.md
index 305cff024..349ca140f 100644
--- a/packages/astro/src/vite-plugin-env/README.md
+++ b/packages/astro/src/env/README.md
@@ -1,4 +1,8 @@
-# vite-plugin-env
+# env
+
+The content of this directory is for `astro:env` features, except for `vite-plugin-import-meta-env.ts`.
+
+# vite-plugin-import-meta-env
Improves Vite's [Env Variables](https://vite.dev/guide/env-and-mode.html#env-files) support to include **private** env variables during Server-Side Rendering (SSR) but never in client-side rendering (CSR).
diff --git a/packages/astro/src/env/env-loader.ts b/packages/astro/src/env/env-loader.ts
index d3893c6f9..02f396652 100644
--- a/packages/astro/src/env/env-loader.ts
+++ b/packages/astro/src/env/env-loader.ts
@@ -43,17 +43,12 @@ function getPrivateEnv(
return privateEnv;
}
-export const createEnvLoader = () => {
- let privateEnv: Record<string, string> = {};
+export const createEnvLoader = (mode: string, config: AstroConfig) => {
+ const loaded = loadEnv(mode, config.vite.envDir ?? fileURLToPath(config.root), '');
+ const privateEnv = getPrivateEnv(loaded, config);
return {
- load: (mode: string, config: AstroConfig) => {
- const loaded = loadEnv(mode, config.vite.envDir ?? fileURLToPath(config.root), '');
- privateEnv = getPrivateEnv(loaded, config);
- return loaded;
- },
- getPrivateEnv: () => {
- return privateEnv;
- },
+ get: () => loaded,
+ getPrivateEnv: () => privateEnv,
};
};
diff --git a/packages/astro/src/env/vite-plugin-env.ts b/packages/astro/src/env/vite-plugin-env.ts
index 1d0283924..e01d8f3d6 100644
--- a/packages/astro/src/env/vite-plugin-env.ts
+++ b/packages/astro/src/env/vite-plugin-env.ts
@@ -14,17 +14,44 @@ import { getEnvFieldType, validateEnvVariable } from './validators.js';
interface AstroEnvPluginParams {
settings: AstroSettings;
- mode: string;
sync: boolean;
envLoader: EnvLoader;
}
-export function astroEnv({ settings, mode, sync, envLoader }: AstroEnvPluginParams): Plugin {
+export function astroEnv({ settings, sync, envLoader }: AstroEnvPluginParams): Plugin {
const { schema, validateSecrets } = settings.config.env;
let isDev: boolean;
let templates: { client: string; server: string; internal: string } | null = null;
+ function ensureTemplateAreLoaded() {
+ if (templates !== null) {
+ return;
+ }
+
+ const loadedEnv = envLoader.get();
+
+ if (!isDev) {
+ for (const [key, value] of Object.entries(loadedEnv)) {
+ if (value !== undefined) {
+ process.env[key] = value;
+ }
+ }
+ }
+
+ const validatedVariables = validatePublicVariables({
+ schema,
+ loadedEnv,
+ validateSecrets,
+ sync,
+ });
+
+ templates = {
+ ...getTemplates(schema, validatedVariables, isDev ? loadedEnv : null),
+ internal: `export const schema = ${JSON.stringify(schema)};`,
+ };
+ }
+
return {
name: 'astro-env-plugin',
enforce: 'pre',
@@ -32,27 +59,7 @@ export function astroEnv({ settings, mode, sync, envLoader }: AstroEnvPluginPara
isDev = command !== 'build';
},
buildStart() {
- const loadedEnv = envLoader.load(mode, settings.config);
-
- if (!isDev) {
- for (const [key, value] of Object.entries(loadedEnv)) {
- if (value !== undefined) {
- process.env[key] = value;
- }
- }
- }
-
- const validatedVariables = validatePublicVariables({
- schema,
- loadedEnv,
- validateSecrets,
- sync,
- });
-
- templates = {
- ...getTemplates(schema, validatedVariables, isDev ? loadedEnv : null),
- internal: `export const schema = ${JSON.stringify(schema)};`,
- };
+ ensureTemplateAreLoaded();
},
buildEnd() {
templates = null;
@@ -64,10 +71,12 @@ export function astroEnv({ settings, mode, sync, envLoader }: AstroEnvPluginPara
},
load(id, options) {
if (id === resolveVirtualModuleId(VIRTUAL_MODULES_IDS.client)) {
+ ensureTemplateAreLoaded();
return templates!.client;
}
if (id === resolveVirtualModuleId(VIRTUAL_MODULES_IDS.server)) {
if (options?.ssr) {
+ ensureTemplateAreLoaded();
return templates!.server;
}
throw new AstroError({
@@ -76,6 +85,7 @@ export function astroEnv({ settings, mode, sync, envLoader }: AstroEnvPluginPara
});
}
if (id === resolveVirtualModuleId(VIRTUAL_MODULES_IDS.internal)) {
+ ensureTemplateAreLoaded();
return templates!.internal;
}
},
diff --git a/packages/astro/src/vite-plugin-env/index.ts b/packages/astro/src/env/vite-plugin-import-meta-env.ts
index 76d295089..0740f7cb4 100644
--- a/packages/astro/src/vite-plugin-env/index.ts
+++ b/packages/astro/src/env/vite-plugin-import-meta-env.ts
@@ -1,7 +1,7 @@
import { transform } from 'esbuild';
import MagicString from 'magic-string';
import type * as vite from 'vite';
-import type { EnvLoader } from '../env/env-loader.js';
+import type { EnvLoader } from './env-loader.js';
interface EnvPluginOptions {
envLoader: EnvLoader;
@@ -65,7 +65,7 @@ async function replaceDefine(
};
}
-export default function envVitePlugin({ envLoader }: EnvPluginOptions): vite.Plugin {
+export function importMetaEnv({ envLoader }: EnvPluginOptions): vite.Plugin {
let privateEnv: Record<string, string>;
let defaultDefines: Record<string, string>;
let isDev: boolean;
diff --git a/packages/astro/test/astro-sync.test.js b/packages/astro/test/astro-sync.test.js
index e9ab90cf7..3e5a9bcbf 100644
--- a/packages/astro/test/astro-sync.test.js
+++ b/packages/astro/test/astro-sync.test.js
@@ -209,10 +209,15 @@ describe('astro sync', () => {
assert.fail();
}
});
- it('Does not throw if a virtual module is imported in content.config.ts', async () => {
+ it('Does not throw if a virtual module is imported in content.config.ts or import.meta.env is not loaded', async () => {
try {
await fixture.load('./fixtures/astro-env-content-collections/');
fixture.clean();
+ fs.writeFileSync(
+ new URL('./fixtures/astro-env-content-collections/.env', import.meta.url),
+ 'BAR=abc',
+ 'utf-8',
+ );
await fixture.whenSyncing();
assert.ok(true);
} catch {
diff --git a/packages/astro/test/fixtures/astro-env-content-collections/src/content.config.ts b/packages/astro/test/fixtures/astro-env-content-collections/src/content.config.ts
index 0fc443935..3276a6789 100644
--- a/packages/astro/test/fixtures/astro-env-content-collections/src/content.config.ts
+++ b/packages/astro/test/fixtures/astro-env-content-collections/src/content.config.ts
@@ -1,11 +1,14 @@
import { defineCollection, z } from "astro:content";
import { FOO } from "astro:env/client"
-console.log({ FOO })
+console.log({ FOO, BAR: import.meta.env.BAR })
export const collections = {
foo: defineCollection({
- type: "data",
+ loader: () => [{
+ id: 'x',
+ title: import.meta.env.BAR
+ }],
schema: z.object({
title: z.string()
})