mirror of
https://github.com/withastro/astro.git
synced 2025-03-24 23:21:57 -05:00
fix: load env earlier (#12977)
This commit is contained in:
parent
3aff68a419
commit
80067c032f
8 changed files with 65 additions and 43 deletions
5
.changeset/cool-rings-tell.md
Normal file
5
.changeset/cool-rings-tell.md
Normal file
|
@ -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
|
|
@ -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(),
|
||||
|
|
|
@ -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).
|
||||
|
15
packages/astro/src/env/env-loader.ts
vendored
15
packages/astro/src/env/env-loader.ts
vendored
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
56
packages/astro/src/env/vite-plugin-env.ts
vendored
56
packages/astro/src/env/vite-plugin-env.ts
vendored
|
@ -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;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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;
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue