Skip to content

Commit

Permalink
refactor: make define option perform direct replacement instead
Browse files Browse the repository at this point in the history
BREAKING CHANGE: `define` option no longer calls `JSON.stringify` on
string values. This means string define values will be now treated as
raw expressions. To define a string constant, explicit quotes are now
required.
  • Loading branch information
yyx990803 committed Feb 13, 2021
1 parent 26d409b commit 059070e
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 19 deletions.
3 changes: 2 additions & 1 deletion packages/playground/define/__tests__/define.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
test('string', async () => {
const defines = require('../vite.config.js').define

expect(await page.textContent('.string')).toBe(String(defines.__STRING__))
expect(await page.textContent('.exp')).toBe(String(eval(defines.__EXP__)))
expect(await page.textContent('.string')).toBe(JSON.parse(defines.__STRING__))
expect(await page.textContent('.number')).toBe(String(defines.__NUMBER__))
expect(await page.textContent('.boolean')).toBe(String(defines.__BOOLEAN__))
expect(await page.textContent('.object')).toBe(
Expand Down
2 changes: 2 additions & 0 deletions packages/playground/define/index.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<h1>Define</h1>

<p>Raw Expression <code class="exp"></code></p>
<p>String <code class="string"></code></p>
<p>Number <code class="number"></code></p>
<p>Boolean <code class="boolean"></code></p>
<p>Object <span class="pre object"></span></p>

<script type="module">
text('.exp', __EXP__)
text('.string', __STRING__)
text('.number', __NUMBER__)
text('.boolean', __BOOLEAN__)
Expand Down
3 changes: 2 additions & 1 deletion packages/playground/define/vite.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = {
define: {
__STRING__: 'hello',
__EXP__: '1 + 1',
__STRING__: '"hello"',
__NUMBER__: 123,
__BOOLEAN__: true,
__OBJ__: {
Expand Down
9 changes: 0 additions & 9 deletions packages/vite/src/node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,15 +269,6 @@ export async function resolveConfig(

// load .env files
const userEnv = loadEnv(mode, resolvedRoot)
// check if user defined any import.meta.env variables
if (config.define) {
const prefix = `import.meta.env.`
for (const key in config.define) {
if (key.startsWith(prefix)) {
userEnv[key.slice(prefix.length)] = config.define[key]
}
}
}

// Note it is possible for user to have a custom mode, e.g. `staging` where
// production-like behavior is expected. This is indicated by NODE_ENV=production
Expand Down
13 changes: 12 additions & 1 deletion packages/vite/src/node/plugins/clientInjections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export function clientInjectionsPlugin(config: ResolvedConfig): Plugin {
.replace(`__MODE__`, JSON.stringify(config.mode))
.replace(`__BASE__`, JSON.stringify(config.base))
.replace(`__ROOT__`, JSON.stringify(config.root))
.replace(`__DEFINES__`, JSON.stringify(config.define || {}))
.replace(`__DEFINES__`, serializeDefine(config.define || {}))
.replace(`__HMR_PROTOCOL__`, JSON.stringify(protocol))
.replace(`__HMR_HOSTNAME__`, JSON.stringify(host))
.replace(`__HMR_PORT__`, JSON.stringify(port))
Expand All @@ -60,3 +60,14 @@ export function clientInjectionsPlugin(config: ResolvedConfig): Plugin {
}
}
}

function serializeDefine(define: Record<string, any>): string {
let res = `{`
for (const key in define) {
const val = define[key]
res += `${JSON.stringify(key)}: ${
typeof val === 'string' ? `(${val})` : JSON.stringify(val)
}, `
}
return res + `}`
}
3 changes: 2 additions & 1 deletion packages/vite/src/node/plugins/define.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export function definePlugin(config: ResolvedConfig): Plugin {

const userDefine: Record<string, string> = {}
for (const key in config.define) {
userDefine[key] = JSON.stringify(config.define[key])
const val = config.define[key]
userDefine[key] = typeof val === 'string' ? val : JSON.stringify(val)
}

// during dev, import.meta properties are handled by importAnalysis plugin
Expand Down
20 changes: 14 additions & 6 deletions packages/vite/src/node/plugins/importAnalysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,12 +411,20 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {

if (hasEnv) {
// inject import.meta.env
str().prepend(
`import.meta.env = ${JSON.stringify({
...config.env,
SSR: !!ssr
})};`
)
let env = `import.meta.env = ${JSON.stringify({
...config.env,
SSR: !!ssr
})};`
// account for user env defines
for (const key in config.define) {
if (key.startsWith(`import.meta.env.`)) {
const val = config.define[key]
env += `${key} = ${
typeof val === 'string' ? val : JSON.stringify(val)
};`
}
}
str().prepend(env)
}

if (hasHMR && !ssr) {
Expand Down

0 comments on commit 059070e

Please sign in to comment.