From afa2d516bf8bbb30ed68ecc8b4cd805a79ac4949 Mon Sep 17 00:00:00 2001 From: bluwy Date: Thu, 4 Jan 2024 18:03:04 +0800 Subject: [PATCH 1/9] Initial code --- .../content/vite-plugin-content-imports.ts | 9 +- packages/astro/src/vite-plugin-env/index.ts | 134 ++++++++++++------ .../astro/src/vite-plugin-markdown/index.ts | 6 +- packages/astro/src/vite-plugin-utils/index.ts | 11 -- 4 files changed, 94 insertions(+), 66 deletions(-) diff --git a/packages/astro/src/content/vite-plugin-content-imports.ts b/packages/astro/src/content/vite-plugin-content-imports.ts index d75378c2a811..9410e4076fba 100644 --- a/packages/astro/src/content/vite-plugin-content-imports.ts +++ b/packages/astro/src/content/vite-plugin-content-imports.ts @@ -16,7 +16,6 @@ import { getProxyCode } from '../assets/utils/proxy.js'; import { AstroError } from '../core/errors/errors.js'; import { AstroErrorData } from '../core/errors/index.js'; import { isServerLikeOutput } from '../prerender/utils.js'; -import { escapeViteEnvReferences } from '../vite-plugin-utils/index.js'; import { CONTENT_FLAG, DATA_FLAG } from './consts.js'; import { getContentEntryExts, @@ -93,7 +92,7 @@ export function astroContentImportPlugin({ pluginContext: this, }); - const code = escapeViteEnvReferences(` + const code = ` export const id = ${JSON.stringify(id)}; export const collection = ${JSON.stringify(collection)}; export const data = ${stringifyEntryData(data, isServerLikeOutput(settings.config))}; @@ -102,7 +101,7 @@ export const _internal = { filePath: ${JSON.stringify(_internal.filePath)}, rawData: ${JSON.stringify(_internal.rawData)}, }; -`); +`; return code; } else if (hasContentFlag(viteId, CONTENT_FLAG)) { const fileId = viteId.split('?')[0]; @@ -115,7 +114,7 @@ export const _internal = { pluginContext: this, }); - const code = escapeViteEnvReferences(` + const code = ` export const id = ${JSON.stringify(id)}; export const collection = ${JSON.stringify(collection)}; export const slug = ${JSON.stringify(slug)}; @@ -125,7 +124,7 @@ export const _internal = { type: 'content', filePath: ${JSON.stringify(_internal.filePath)}, rawData: ${JSON.stringify(_internal.rawData)}, - };`); + };`; return { code, map: { mappings: '' } }; } diff --git a/packages/astro/src/vite-plugin-env/index.ts b/packages/astro/src/vite-plugin-env/index.ts index 1958344e595c..10309ec46a43 100644 --- a/packages/astro/src/vite-plugin-env/index.ts +++ b/packages/astro/src/vite-plugin-env/index.ts @@ -1,13 +1,15 @@ -import MagicString from 'magic-string'; import { fileURLToPath } from 'node:url'; import type * as vite from 'vite'; import { loadEnv } from 'vite'; +import { transform } from 'esbuild'; import type { AstroConfig, AstroSettings } from '../@types/astro.js'; interface EnvPluginOptions { settings: AstroSettings; } +const importMetaEnvOnlyRe = /import\.meta\.env\b(?!\.)/; + function getPrivateEnv( viteConfig: vite.ResolvedConfig, astroConfig: AstroConfig @@ -67,13 +69,40 @@ function getReferencedPrivateKeys(source: string, privateEnv: Record, + config: vite.ResolvedConfig +): Promise<{ code: string; map: string | null }> { + const esbuildOptions = config.esbuild || {}; + + const result = await transform(code, { + loader: 'js', + charset: esbuildOptions.charset ?? 'utf8', + platform: 'neutral', + define, + sourcefile: id, + sourcemap: config.command === 'build' ? !!config.build.sourcemap : true, + }); + + return { + code: result.code, + map: result.map || null, + }; +} + +export default function envVitePlugin({ settings }: EnvPluginOptions): vite.Plugin { let privateEnv: Record; + let defaultDefines: Record; let viteConfig: vite.ResolvedConfig; const { config: astroConfig } = settings; return { name: 'astro:vite-plugin-env', - enforce: 'pre', config() { return { define: { @@ -88,6 +117,23 @@ export default function envVitePlugin({ settings }: EnvPluginOptions): vite.Plug }, configResolved(resolvedConfig) { viteConfig = resolvedConfig; + + // HACK: move ourselves before Vite's define plugin to apply replacements at the right time (before Vite normal plugins) + const viteDefinePluginIndex = resolvedConfig.plugins.findIndex( + (p) => p.name === 'vite:define' + ); + if (viteDefinePluginIndex !== -1) { + const myPluginIndex = resolvedConfig.plugins.findIndex( + (p) => p.name === 'astro:vite-plugin-env' + ); + if (myPluginIndex !== -1) { + const myPlugin = resolvedConfig.plugins[myPluginIndex]; + // @ts-ignore-error ignore readonly annotation + resolvedConfig.plugins.splice(viteDefinePluginIndex, 0, myPlugin); + // @ts-ignore-error ignore readonly annotation + resolvedConfig.plugins.splice(myPluginIndex, 1); + } + } }, async transform(source, id, options) { if (!options?.ssr || !source.includes('import.meta.env')) { @@ -95,55 +141,49 @@ export default function envVitePlugin({ settings }: EnvPluginOptions): vite.Plug } // Find matches for *private* env and do our own replacement. - let s: MagicString | undefined; - const pattern = new RegExp( - // Do not allow preceding '.', but do allow preceding '...' for spread operations - '(?; - let match: RegExpExecArray | null; - - while ((match = pattern.exec(source))) { - let replacement: string | undefined; - // If we match exactly `import.meta.env`, define _only_ referenced private variables - if (match[0] === 'import.meta.env') { - privateEnv ??= getPrivateEnv(viteConfig, astroConfig); - references ??= getReferencedPrivateKeys(source, privateEnv); - replacement = `(Object.assign(import.meta.env,{`; - for (const key of references.values()) { - replacement += `${key}:${privateEnv[key]},`; - } - replacement += '}))'; - } - // If we match `import.meta.env.*`, replace with private env - else if (match[2]) { - privateEnv ??= getPrivateEnv(viteConfig, astroConfig); - replacement = privateEnv[match[2]]; - } - if (replacement) { - const start = match.index; - const end = start + match[0].length; - s ??= new MagicString(source); - s.overwrite(start, end, replacement); + privateEnv ??= getPrivateEnv(viteConfig, astroConfig); + if (!defaultDefines) { + defaultDefines = {}; + for (const key in privateEnv) { + defaultDefines[`import.meta.env.${key}`] = privateEnv[key]; } } - if (s) { - return { - code: s.toString(), - map: s.generateMap({ hires: 'boundary' }), + let defines = defaultDefines; + + // If reference the `import.meta.env` object directly, we want to inject private env vars + // into Vite's injected `import.meta.env` object. To do this, we use `Object.assign` and keeping + // the `import.meta.env` identifier so Vite sees it. + // However, since esbuild doesn't support replacing complex expressions, we replace `import.meta.env` + // with a marker string first, then postprocess and apply the `Object.assign` code. + let importMetaEnvMarker: string | undefined; + let importMetaEnvReplacement: string | undefined; + if (importMetaEnvOnlyRe.test(source)) { + const references = getReferencedPrivateKeys(source, privateEnv); + // Create the `Object.assign` code + importMetaEnvReplacement = `(Object.assign(import.meta.env,{`; + for (const key of references.values()) { + importMetaEnvReplacement += `${key}:${privateEnv[key]},`; + } + importMetaEnvReplacement += '}))'; + // Compute the marker from the length of the replaced code. We do this so that esbuild generates + // the sourcemap with the right column offset when we do the postprocessing. + importMetaEnvMarker = `__astro_import_meta_env${'_'.repeat( + importMetaEnvReplacement.length - 23 /* length of preceding string */ + )}`; + defines = { + ...defaultDefines, + 'import.meta.env': importMetaEnvMarker, }; } + + const result = await replaceDefine(source, id, defines, viteConfig); + + if (importMetaEnvMarker) { + result.code = result.code.replaceAll(importMetaEnvMarker, importMetaEnvReplacement!); + } + + return result; }, }; } diff --git a/packages/astro/src/vite-plugin-markdown/index.ts b/packages/astro/src/vite-plugin-markdown/index.ts index fdfe3db3760f..cc138149b1c4 100644 --- a/packages/astro/src/vite-plugin-markdown/index.ts +++ b/packages/astro/src/vite-plugin-markdown/index.ts @@ -15,7 +15,7 @@ import type { Logger } from '../core/logger/core.js'; import { isMarkdownFile } from '../core/util.js'; import { shorthash } from '../runtime/server/shorthash.js'; import type { PluginMetadata } from '../vite-plugin-astro/types.js'; -import { escapeViteEnvReferences, getFileInfo } from '../vite-plugin-utils/index.js'; +import { getFileInfo } from '../vite-plugin-utils/index.js'; import { getMarkdownCodeForImages, type MarkdownImagePath } from './images.js'; interface AstroPluginOptions { @@ -116,7 +116,7 @@ export default function markdown({ settings, logger }: AstroPluginOptions): Plug ); } - const code = escapeViteEnvReferences(` + const code = ` import { unescapeHTML, spreadAttributes, createComponent, render, renderComponent, maybeRenderHead } from ${JSON.stringify( astroServerRuntimeModulePath )}; @@ -166,7 +166,7 @@ export default function markdown({ settings, logger }: AstroPluginOptions): Plug } }); export default Content; - `); + `; return { code, diff --git a/packages/astro/src/vite-plugin-utils/index.ts b/packages/astro/src/vite-plugin-utils/index.ts index 7bf9f092f618..6f672d7d99a8 100644 --- a/packages/astro/src/vite-plugin-utils/index.ts +++ b/packages/astro/src/vite-plugin-utils/index.ts @@ -8,17 +8,6 @@ import { } from '../core/path.js'; import { viteID } from '../core/util.js'; -/** - * Converts the first dot in `import.meta.env` to its Unicode escape sequence, - * which prevents Vite from replacing strings like `import.meta.env.SITE` - * in our JS representation of modules like Markdown - */ -export function escapeViteEnvReferences(code: string) { - return code - .replace(/import\.meta\.env/g, 'import\\u002Emeta.env') - .replace(/process\.env/g, 'process\\u002Eenv'); -} - export function getFileInfo(id: string, config: AstroConfig) { const sitePathname = appendForwardSlash( config.site ? new URL(config.base, config.site).pathname : config.base From e403ff8f3a6dfb39e7ec7ce0f55f4e5d7bcf2119 Mon Sep 17 00:00:00 2001 From: bluwy Date: Thu, 4 Jan 2024 18:09:16 +0800 Subject: [PATCH 2/9] Refactor similar to vite --- packages/astro/src/vite-plugin-env/index.ts | 46 +++++++++++---------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/packages/astro/src/vite-plugin-env/index.ts b/packages/astro/src/vite-plugin-env/index.ts index 10309ec46a43..9a6104cb44a9 100644 --- a/packages/astro/src/vite-plugin-env/index.ts +++ b/packages/astro/src/vite-plugin-env/index.ts @@ -79,6 +79,20 @@ async function replaceDefine( define: Record, config: vite.ResolvedConfig ): Promise<{ code: string; map: string | null }> { + // Since esbuild doesn't support replacing complex expressions, we replace `import.meta.env` + // with a marker string first, then postprocess and apply the `Object.assign` code. + const replacementMarkers: Record = {}; + const env = define['import.meta.env']; + if (env) { + // Compute the marker from the length of the replaced code. We do this so that esbuild generates + // the sourcemap with the right column offset when we do the postprocessing. + const marker = `__astro_import_meta_env${'_'.repeat( + env.length - 23 /* length of preceding string */ + )}`; + replacementMarkers[marker] = env; + define = { ...define, 'import.meta.env': marker }; + } + const esbuildOptions = config.esbuild || {}; const result = await transform(code, { @@ -90,6 +104,10 @@ async function replaceDefine( sourcemap: config.command === 'build' ? !!config.build.sourcemap : true, }); + for (const marker in replacementMarkers) { + result.code = result.code.replaceAll(marker, replacementMarkers[marker]); + } + return { code: result.code, map: result.map || null, @@ -135,7 +153,7 @@ export default function envVitePlugin({ settings }: EnvPluginOptions): vite.Plug } } }, - async transform(source, id, options) { + transform(source, id, options) { if (!options?.ssr || !source.includes('import.meta.env')) { return; } @@ -154,36 +172,20 @@ export default function envVitePlugin({ settings }: EnvPluginOptions): vite.Plug // If reference the `import.meta.env` object directly, we want to inject private env vars // into Vite's injected `import.meta.env` object. To do this, we use `Object.assign` and keeping // the `import.meta.env` identifier so Vite sees it. - // However, since esbuild doesn't support replacing complex expressions, we replace `import.meta.env` - // with a marker string first, then postprocess and apply the `Object.assign` code. - let importMetaEnvMarker: string | undefined; - let importMetaEnvReplacement: string | undefined; if (importMetaEnvOnlyRe.test(source)) { const references = getReferencedPrivateKeys(source, privateEnv); - // Create the `Object.assign` code - importMetaEnvReplacement = `(Object.assign(import.meta.env,{`; + let replacement = `(Object.assign(import.meta.env,{`; for (const key of references.values()) { - importMetaEnvReplacement += `${key}:${privateEnv[key]},`; + replacement += `${key}:${privateEnv[key]},`; } - importMetaEnvReplacement += '}))'; - // Compute the marker from the length of the replaced code. We do this so that esbuild generates - // the sourcemap with the right column offset when we do the postprocessing. - importMetaEnvMarker = `__astro_import_meta_env${'_'.repeat( - importMetaEnvReplacement.length - 23 /* length of preceding string */ - )}`; + replacement += '}))'; defines = { ...defaultDefines, - 'import.meta.env': importMetaEnvMarker, + 'import.meta.env': replacement, }; } - const result = await replaceDefine(source, id, defines, viteConfig); - - if (importMetaEnvMarker) { - result.code = result.code.replaceAll(importMetaEnvMarker, importMetaEnvReplacement!); - } - - return result; + return replaceDefine(source, id, defines, viteConfig); }, }; } From c0421c8a68cc2352c8ba32642127132a288eaaed Mon Sep 17 00:00:00 2001 From: bluwy Date: Fri, 5 Jan 2024 22:51:32 +0800 Subject: [PATCH 3/9] Improve dev perf --- packages/astro/src/vite-plugin-env/index.ts | 25 ++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/astro/src/vite-plugin-env/index.ts b/packages/astro/src/vite-plugin-env/index.ts index 9a6104cb44a9..36c826ef245b 100644 --- a/packages/astro/src/vite-plugin-env/index.ts +++ b/packages/astro/src/vite-plugin-env/index.ts @@ -2,6 +2,7 @@ import { fileURLToPath } from 'node:url'; import type * as vite from 'vite'; import { loadEnv } from 'vite'; import { transform } from 'esbuild'; +import MagicString from 'magic-string'; import type { AstroConfig, AstroSettings } from '../@types/astro.js'; interface EnvPluginOptions { @@ -117,11 +118,14 @@ async function replaceDefine( export default function envVitePlugin({ settings }: EnvPluginOptions): vite.Plugin { let privateEnv: Record; let defaultDefines: Record; + let isDev: boolean; + let devImportMetaEnvPrepend: string; let viteConfig: vite.ResolvedConfig; const { config: astroConfig } = settings; return { name: 'astro:vite-plugin-env', - config() { + config(_, { command }) { + isDev = command !== 'build'; return { define: { 'import.meta.env.BASE_URL': astroConfig.base @@ -160,6 +164,25 @@ export default function envVitePlugin({ settings }: EnvPluginOptions): vite.Plug // Find matches for *private* env and do our own replacement. privateEnv ??= getPrivateEnv(viteConfig, astroConfig); + + // In dev, we can assign the private env vars to `import.meta.env` directly for performance + if (isDev) { + const s = new MagicString(source); + if (!devImportMetaEnvPrepend) { + devImportMetaEnvPrepend = `Object.assign(import.meta.env,{`; + for (const key in privateEnv) { + devImportMetaEnvPrepend += `${key}:${privateEnv[key]},`; + } + devImportMetaEnvPrepend += '});'; + } + s.prepend(devImportMetaEnvPrepend); + return { + code: s.toString(), + map: s.generateMap({ hires: 'boundary' }), + }; + } + + // Compute the default defines for esbuild. It could be extended by `import.meta.env` later. if (!defaultDefines) { defaultDefines = {}; for (const key in privateEnv) { From adc6f247d7f08e3c354a1ce8da0b6da67a18cb9c Mon Sep 17 00:00:00 2001 From: bluwy Date: Tue, 9 Jan 2024 22:01:36 +0800 Subject: [PATCH 4/9] Update comment --- packages/astro/src/vite-plugin-env/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/astro/src/vite-plugin-env/index.ts b/packages/astro/src/vite-plugin-env/index.ts index 671aa60675f3..22e341fcfeb5 100644 --- a/packages/astro/src/vite-plugin-env/index.ts +++ b/packages/astro/src/vite-plugin-env/index.ts @@ -166,7 +166,8 @@ export default function envVitePlugin({ settings }: EnvPluginOptions): vite.Plug }; } - // Compute the default defines for esbuild. It could be extended by `import.meta.env` later. + // In build, use esbuild to perform replacements. Compute the default defines for esbuild here as a + // separate object as it could be extended by `import.meta.env` later. if (!defaultDefines) { defaultDefines = {}; for (const key in privateEnv) { From 588ad63c4deb26370ed4f8987a6008b5bc05595a Mon Sep 17 00:00:00 2001 From: bluwy Date: Tue, 9 Jan 2024 22:31:44 +0800 Subject: [PATCH 5/9] Fix mdx replace --- packages/integrations/mdx/src/index.ts | 11 ++--------- .../mdx/src/recma-inject-import-meta-env.ts | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/packages/integrations/mdx/src/index.ts b/packages/integrations/mdx/src/index.ts index 3092ad51f02b..1b38da48820e 100644 --- a/packages/integrations/mdx/src/index.ts +++ b/packages/integrations/mdx/src/index.ts @@ -129,7 +129,7 @@ export default function mdx(partialMdxOptions: Partial = {}): AstroI const compiled = await processor.process(vfile); return { - code: escapeViteEnvReferences(String(compiled.value)), + code: String(compiled.value), map: compiled.map, }; } catch (e: any) { @@ -215,7 +215,7 @@ export default function mdx(partialMdxOptions: Partial = {}): AstroI import.meta.hot.decline(); }`; } - return { code: escapeViteEnvReferences(code), map: null }; + return { code, map: null }; }, }, ] as VitePlugin[], @@ -262,10 +262,3 @@ function applyDefaultOptions({ optimize: options.optimize ?? defaults.optimize, }; } - -// Converts the first dot in `import.meta.env` to its Unicode escape sequence, -// which prevents Vite from replacing strings like `import.meta.env.SITE` -// in our JS representation of loaded Markdown files -function escapeViteEnvReferences(code: string) { - return code.replace(/import\.meta\.env/g, 'import\\u002Emeta.env'); -} diff --git a/packages/integrations/mdx/src/recma-inject-import-meta-env.ts b/packages/integrations/mdx/src/recma-inject-import-meta-env.ts index 00578535de4e..df753ef4c194 100644 --- a/packages/integrations/mdx/src/recma-inject-import-meta-env.ts +++ b/packages/integrations/mdx/src/recma-inject-import-meta-env.ts @@ -11,7 +11,7 @@ export function recmaInjectImportMetaEnv({ if (node.type === 'MemberExpression') { // attempt to get "import.meta.env" variable name const envVarName = getImportMetaEnvVariableName(node); - if (typeof envVarName === 'string') { + if (typeof envVarName === 'string' && importMetaEnv[envVarName] != null) { // clear object keys to replace with envVarLiteral for (const key in node) { delete (node as any)[key]; From b5f20cf1676c681e646516fa20cf742b626ee992 Mon Sep 17 00:00:00 2001 From: bluwy Date: Tue, 9 Jan 2024 22:48:45 +0800 Subject: [PATCH 6/9] Add test --- .../mdx/test/fixtures/mdx-vite-env-vars/astro.config.mjs | 7 +++++++ .../mdx-vite-env-vars/src/pages/vite-env-vars.mdx | 8 ++++++++ packages/integrations/mdx/test/mdx-vite-env-vars.test.js | 3 +++ 3 files changed, 18 insertions(+) diff --git a/packages/integrations/mdx/test/fixtures/mdx-vite-env-vars/astro.config.mjs b/packages/integrations/mdx/test/fixtures/mdx-vite-env-vars/astro.config.mjs index df0e781939e8..717d379c01cd 100644 --- a/packages/integrations/mdx/test/fixtures/mdx-vite-env-vars/astro.config.mjs +++ b/packages/integrations/mdx/test/fixtures/mdx-vite-env-vars/astro.config.mjs @@ -6,4 +6,11 @@ export default { syntaxHighlight: false, }, integrations: [mdx()], + vite: { + build: { + // Enabling sourcemap may crash the build when using `import.meta.env.UNKNOWN_VAR` + // https://github.com/withastro/astro/issues/9012 + sourcemap: true, + }, + }, } diff --git a/packages/integrations/mdx/test/fixtures/mdx-vite-env-vars/src/pages/vite-env-vars.mdx b/packages/integrations/mdx/test/fixtures/mdx-vite-env-vars/src/pages/vite-env-vars.mdx index dae32aed2d8f..7fb9960ce0db 100644 --- a/packages/integrations/mdx/test/fixtures/mdx-vite-env-vars/src/pages/vite-env-vars.mdx +++ b/packages/integrations/mdx/test/fixtures/mdx-vite-env-vars/src/pages/vite-env-vars.mdx @@ -5,6 +5,8 @@ title: Let's talk about my import.meta.env.SITE export const modeWorks = import.meta.env.MODE === 'production' ? 'MODE works' : 'MODE does not work!'; +export const unknownVar = import.meta.env.UNKNOWN_VAR; + # About my import.meta.env.SITE My `import.meta.env.SITE` is so cool, I can put env variables in code! @@ -27,6 +29,12 @@ I can also use `import.meta.env` in variable exports: {modeWorks} +
+ +I can also use `import.meta.env.UNKNOWN_VAR` through exports: "{unknownVar}" + +
+ I can also use vars as HTML attributes:
{ expect(document.querySelector('[data-env-variable-exports]')?.innerHTML).to.contain( 'MODE works' ); + expect(document.querySelector('[data-env-variable-exports-unknown]')?.innerHTML).to.contain( + 'exports: ””' // NOTE: these double quotes are special unicode quotes emitted in the HTML file + ); }); it('Transforms `import.meta.env` in HTML attributes', async () => { const html = await fixture.readFile('/vite-env-vars/index.html'); From d26dfa1831e92085f304c4892b710d78eb87ce4b Mon Sep 17 00:00:00 2001 From: bluwy Date: Tue, 9 Jan 2024 22:53:09 +0800 Subject: [PATCH 7/9] Add changeset --- .changeset/lazy-pandas-pretend.md | 5 +++++ .changeset/silent-pandas-rush.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/lazy-pandas-pretend.md create mode 100644 .changeset/silent-pandas-rush.md diff --git a/.changeset/lazy-pandas-pretend.md b/.changeset/lazy-pandas-pretend.md new file mode 100644 index 000000000000..4787c2e5412d --- /dev/null +++ b/.changeset/lazy-pandas-pretend.md @@ -0,0 +1,5 @@ +--- +"@astrojs/mdx": patch +--- + +Removes environment variables workaround that broke project builds with sourcemaps diff --git a/.changeset/silent-pandas-rush.md b/.changeset/silent-pandas-rush.md new file mode 100644 index 000000000000..d3c9b7dba8ff --- /dev/null +++ b/.changeset/silent-pandas-rush.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +Improves environment variables handling by using esbuild to perform replacements From 849cc7880e15f64dc43ac16a8e6a4a55d5a2b9cf Mon Sep 17 00:00:00 2001 From: bluwy Date: Tue, 9 Jan 2024 23:12:01 +0800 Subject: [PATCH 8/9] Fix CI --- packages/astro/src/vite-plugin-env/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/astro/src/vite-plugin-env/index.ts b/packages/astro/src/vite-plugin-env/index.ts index 22e341fcfeb5..7ca5195d779e 100644 --- a/packages/astro/src/vite-plugin-env/index.ts +++ b/packages/astro/src/vite-plugin-env/index.ts @@ -10,6 +10,7 @@ interface EnvPluginOptions { } const importMetaEnvOnlyRe = /import\.meta\.env\b(?!\.)/; +const isValidIdentifierRe = /^[_$a-zA-Z][_$a-zA-Z0-9]*$/; function getPrivateEnv( viteConfig: vite.ResolvedConfig, @@ -32,7 +33,7 @@ function getPrivateEnv( const privateEnv: Record = {}; for (const key in fullEnv) { // Ignore public env var - if (envPrefixes.every((prefix) => !key.startsWith(prefix))) { + if (isValidIdentifierRe.test(key) && envPrefixes.every((prefix) => !key.startsWith(prefix))) { if (typeof process.env[key] !== 'undefined') { let value = process.env[key]; // Replacements are always strings, so try to convert to strings here first From fe167737aa01834e63754951297542ab8fd4fad3 Mon Sep 17 00:00:00 2001 From: bluwy Date: Wed, 10 Jan 2024 22:57:08 +0800 Subject: [PATCH 9/9] Add comment --- packages/astro/src/vite-plugin-env/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/astro/src/vite-plugin-env/index.ts b/packages/astro/src/vite-plugin-env/index.ts index 7ca5195d779e..7d91b3552491 100644 --- a/packages/astro/src/vite-plugin-env/index.ts +++ b/packages/astro/src/vite-plugin-env/index.ts @@ -9,7 +9,10 @@ interface EnvPluginOptions { settings: AstroSettings; } -const importMetaEnvOnlyRe = /import\.meta\.env\b(?!\.)/; +// Match `import.meta.env` directly without trailing property access +const importMetaEnvOnlyRe = /\bimport\.meta\.env\b(?!\.)/; +// Match valid JS variable names (identifiers), which accepts most alphanumeric characters, +// except that the first character cannot be a number. const isValidIdentifierRe = /^[_$a-zA-Z][_$a-zA-Z0-9]*$/; function getPrivateEnv(