Skip to content

Commit e686d74

Browse files
yuzheng14bluwy
andauthoredAug 15, 2024··
fix(build): avoid re-define __vite_import_meta_env__ (#17876)
Co-authored-by: bluwy <bjornlu.dev@gmail.com>
1 parent 1b3b702 commit e686d74

File tree

2 files changed

+72
-17
lines changed

2 files changed

+72
-17
lines changed
 

‎packages/vite/src/node/__tests__/plugins/define.spec.ts

+27
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,31 @@ describe('definePlugin', () => {
109109
/const __vite_import_meta_env__ = .*;\nconst env = __vite_import_meta_env__;/,
110110
)
111111
})
112+
113+
test('already has marker', async () => {
114+
const transform = await createDefinePluginTransform()
115+
expect(
116+
await transform(
117+
'console.log(__vite_import_meta_env__);\nconst env = import.meta.env;',
118+
),
119+
).toMatch(
120+
/const __vite_import_meta_env__1 = .*;\nconsole.log\(__vite_import_meta_env__\);\nconst env = __vite_import_meta_env__1;/,
121+
)
122+
123+
expect(
124+
await transform(
125+
'console.log(__vite_import_meta_env__, __vite_import_meta_env__1);\n const env = import.meta.env;',
126+
),
127+
).toMatch(
128+
/const __vite_import_meta_env__2 = .*;\nconsole.log\(__vite_import_meta_env__, __vite_import_meta_env__1\);\nconst env = __vite_import_meta_env__2;/,
129+
)
130+
131+
expect(
132+
await transform(
133+
'console.log(__vite_import_meta_env__);\nconst env = import.meta.env;\nconsole.log(import.meta.env.UNDEFINED);',
134+
),
135+
).toMatch(
136+
/const __vite_import_meta_env__1 = .*;\nconsole.log\(__vite_import_meta_env__\);\nconst env = __vite_import_meta_env__1;\nconsole.log\(undefined {26}\);/,
137+
)
138+
})
112139
})

‎packages/vite/src/node/plugins/define.ts

+45-17
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ import { isHTMLRequest } from './html'
99
const nonJsRe = /\.json(?:$|\?)/
1010
const isNonJsRequest = (request: string): boolean => nonJsRe.test(request)
1111
const importMetaEnvMarker = '__vite_import_meta_env__'
12-
const bareImportMetaEnvRe = new RegExp(`${importMetaEnvMarker}(?!\\.)\\b`)
13-
const importMetaEnvKeyRe = new RegExp(`${importMetaEnvMarker}\\..+?\\b`, 'g')
12+
const importMetaEnvKeyReCache = new Map<string, RegExp>()
1413

1514
export function definePlugin(config: ResolvedConfig): Plugin {
1615
const isBuild = config.command === 'build'
@@ -80,7 +79,6 @@ export function definePlugin(config: ResolvedConfig): Plugin {
8079
SSR: ssr + '',
8180
...userDefineEnv,
8281
})
83-
const banner = `const ${importMetaEnvMarker} = ${importMetaEnvVal};\n`
8482

8583
// Create regex pattern as a fast check before running esbuild
8684
const patternKeys = Object.keys(userDefine)
@@ -94,7 +92,7 @@ export function definePlugin(config: ResolvedConfig): Plugin {
9492
? new RegExp(patternKeys.map(escapeRegex).join('|'))
9593
: null
9694

97-
return [define, pattern, banner] as const
95+
return [define, pattern, importMetaEnvVal] as const
9896
}
9997

10098
const defaultPattern = generatePattern(false)
@@ -122,28 +120,49 @@ export function definePlugin(config: ResolvedConfig): Plugin {
122120
return
123121
}
124122

125-
const [define, pattern, banner] = ssr ? ssrPattern : defaultPattern
123+
let [define, pattern, importMetaEnvVal] = ssr
124+
? ssrPattern
125+
: defaultPattern
126126
if (!pattern) return
127127

128128
// Check if our code needs any replacements before running esbuild
129129
pattern.lastIndex = 0
130130
if (!pattern.test(code)) return
131131

132-
const result = await replaceDefine(code, id, define, config)
132+
const hasDefineImportMetaEnv = 'import.meta.env' in define
133+
let marker = importMetaEnvMarker
133134

134-
// Replace `import.meta.env.*` with undefined
135-
result.code = result.code.replaceAll(importMetaEnvKeyRe, (m) =>
136-
'undefined'.padEnd(m.length),
137-
)
135+
if (hasDefineImportMetaEnv && code.includes(marker)) {
136+
// append a number to the marker until it's unique, to avoid if there is a
137+
// marker already in the code
138+
let i = 1
139+
do {
140+
marker = importMetaEnvMarker + i++
141+
} while (code.includes(marker))
138142

139-
// If there's bare `import.meta.env` references, prepend the banner
140-
if (bareImportMetaEnvRe.test(result.code)) {
141-
result.code = banner + result.code
143+
if (marker !== importMetaEnvMarker) {
144+
define = { ...define, 'import.meta.env': marker }
145+
}
146+
}
142147

143-
if (result.map) {
144-
const map = JSON.parse(result.map)
145-
map.mappings = ';' + map.mappings
146-
result.map = map
148+
const result = await replaceDefine(code, id, define, config)
149+
150+
if (hasDefineImportMetaEnv) {
151+
// Replace `import.meta.env.*` with undefined
152+
result.code = result.code.replaceAll(
153+
getImportMetaEnvKeyRe(marker),
154+
(m) => 'undefined'.padEnd(m.length),
155+
)
156+
157+
// If there's bare `import.meta.env` references, prepend the banner
158+
if (result.code.includes(marker)) {
159+
result.code = `const ${marker} = ${importMetaEnvVal};\n` + result.code
160+
161+
if (result.map) {
162+
const map = JSON.parse(result.map)
163+
map.mappings = ';' + map.mappings
164+
result.map = map
165+
}
147166
}
148167
}
149168

@@ -219,3 +238,12 @@ function handleDefineValue(value: any): string {
219238
if (typeof value === 'string') return value
220239
return JSON.stringify(value)
221240
}
241+
242+
function getImportMetaEnvKeyRe(marker: string): RegExp {
243+
let re = importMetaEnvKeyReCache.get(marker)
244+
if (!re) {
245+
re = new RegExp(`${marker}\\..+?\\b`, 'g')
246+
importMetaEnvKeyReCache.set(marker, re)
247+
}
248+
return re
249+
}

0 commit comments

Comments
 (0)
Please sign in to comment.