diff --git a/packages/playground/ssr-react/__tests__/ssr-react.spec.ts b/packages/playground/ssr-react/__tests__/ssr-react.spec.ts
index d7c3313b38e57a..2235d4ae4d0edf 100644
--- a/packages/playground/ssr-react/__tests__/ssr-react.spec.ts
+++ b/packages/playground/ssr-react/__tests__/ssr-react.spec.ts
@@ -4,6 +4,15 @@ import fetch from 'node-fetch'
const url = `http://localhost:${port}`
+test('/env', async () => {
+ await page.goto(url + '/env')
+ expect(await page.textContent('h1')).toMatch('default message here')
+
+ // raw http request
+ const envHtml = await (await fetch(url + '/env')).text()
+ expect(envHtml).toMatch('API_KEY_qwertyuiop')
+})
+
test('/about', async () => {
await page.goto(url + '/about')
expect(await page.textContent('h1')).toMatch('About')
diff --git a/packages/playground/ssr-react/server.js b/packages/playground/ssr-react/server.js
index 6e04104181ba56..1876439c18fa88 100644
--- a/packages/playground/ssr-react/server.js
+++ b/packages/playground/ssr-react/server.js
@@ -5,6 +5,8 @@ const express = require('express')
const isTest = process.env.NODE_ENV === 'test' || !!process.env.VITE_TEST_BUILD
+process.env.MY_CUSTOM_SECRET = 'API_KEY_qwertyuiop'
+
async function createServer(
root = process.cwd(),
isProd = process.env.NODE_ENV === 'production'
diff --git a/packages/playground/ssr-react/src/pages/Env.jsx b/packages/playground/ssr-react/src/pages/Env.jsx
new file mode 100644
index 00000000000000..1102990f11c8cb
--- /dev/null
+++ b/packages/playground/ssr-react/src/pages/Env.jsx
@@ -0,0 +1,7 @@
+export default function Env() {
+ let msg = 'default message here'
+ try {
+ msg = process.env.MY_CUSTOM_SECRET || msg
+ } catch {}
+ return
{msg}
+}
diff --git a/packages/vite/src/node/plugins/define.ts b/packages/vite/src/node/plugins/define.ts
index bc466cc3daae0a..3b7307b21851ba 100644
--- a/packages/vite/src/node/plugins/define.ts
+++ b/packages/vite/src/node/plugins/define.ts
@@ -7,6 +7,16 @@ import { isCSSRequest } from './css'
export function definePlugin(config: ResolvedConfig): Plugin {
const isBuild = config.command === 'build'
+ const processNodeEnv: Record = {
+ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || config.mode),
+ 'global.process.env.NODE_ENV': JSON.stringify(
+ process.env.NODE_ENV || config.mode
+ ),
+ 'globalThis.process.env.NODE_ENV': JSON.stringify(
+ process.env.NODE_ENV || config.mode
+ )
+ }
+
const userDefine: Record = {}
for (const key in config.define) {
const val = config.define[key]
@@ -30,32 +40,42 @@ export function definePlugin(config: ResolvedConfig): Plugin {
})
}
- const replacements: Record = {
- 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || config.mode),
- 'global.process.env.NODE_ENV': JSON.stringify(
- process.env.NODE_ENV || config.mode
- ),
- 'globalThis.process.env.NODE_ENV': JSON.stringify(
- process.env.NODE_ENV || config.mode
- ),
- ...userDefine,
- ...importMetaKeys,
- 'process.env.': `({}).`,
- 'global.process.env.': `({}).`,
- 'globalThis.process.env.': `({}).`
+ function generatePattern(
+ ssr: boolean
+ ): [Record, RegExp] {
+ const processEnv: Record = {}
+ if (!ssr || config.ssr?.target === 'webworker') {
+ Object.assign(processEnv, {
+ 'process.env.': `({}).`,
+ 'global.process.env.': `({}).`,
+ 'globalThis.process.env.': `({}).`
+ })
+ }
+
+ const replacements: Record = {
+ ...processNodeEnv,
+ ...userDefine,
+ ...importMetaKeys,
+ ...processEnv
+ }
+
+ const pattern = new RegExp(
+ // Do not allow preceding '.', but do allow preceding '...' for spread operations
+ '(? {
+ return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&')
+ })
+ .join('|') +
+ ')\\b',
+ 'g'
+ )
+
+ return [replacements, pattern]
}
- const pattern = new RegExp(
- // Do not allow preceding '.', but do allow preceding '...' for spread operations
- '(? {
- return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&')
- })
- .join('|') +
- ')\\b',
- 'g'
- )
+ const defaultPattern = generatePattern(false)
+ const ssrPattern = generatePattern(true)
return {
name: 'vite:define',
@@ -74,6 +94,8 @@ export function definePlugin(config: ResolvedConfig): Plugin {
return
}
+ const [replacements, pattern] = ssr ? ssrPattern : defaultPattern
+
if (ssr && !isBuild) {
// ssr + dev, simple replace
return code.replace(pattern, (_, match) => {