Skip to content

Commit c061f58

Browse files
authored
fix: replace import.meta.env with null (closes #3078) (#3082)
BREAKING CHANGE: Bare `import.meta.env` expression is replaced with `null` — use `import.meta.env.SONE_ENV` instead, see [vike.dev/env](https://vike.dev/env)
1 parent 2bf9f5c commit c061f58

5 files changed

Lines changed: 31 additions & 13 deletions

File tree

docs/pages/blog/vike-server/+Page.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Link } from '@brillout/docpress'
1+
import { Link, ImportMeta } from '@brillout/docpress'
22
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs'
33
import '../../../components/tabs.css'
44
import { BlogHeader } from '../BlogHeader'
@@ -8,7 +8,7 @@ import { BlogHeader } from '../BlogHeader'
88
We (<Link href="/team">Joël, Dani, and Rom</Link>) have been working on a <Link href="/vike-server">new Vike extension `vike-server`</Link> which can integrate Vite with any server (Express.js, Hono, Fastify, Elysia, H3, ...) and any deployment (VPS, Netlify, Cloudflare, Vercel, ...).
99

1010
With `vike-server` you get:
11-
- Server code **transpiled by Vite** (say goodbye to `ts-node`/`tsx`/`vavite` and hello to Vite utilities such as `import.meta.env`)
11+
- Server code **transpiled by Vite** (say goodbye to `ts-node`/`tsx`/`vavite` and hello to Vite utilities such as <ImportMeta prop="env" />)
1212
- **Zero-config** (Vike is automatically added to your server)
1313
- **HMR** (no more full server reloads)
1414

docs/pages/env/+Page.mdx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ DATABASE_URL=postgresql://database.example.com:5432
4343

4444
## Access
4545

46-
Use `import.meta.env` to access environment variables.
46+
Use <ImportMeta prop="env"/> to access environment variables.
4747

4848
```ts
4949
// /pages/movies/+data.ts
@@ -79,12 +79,12 @@ function ContactUs() {
7979

8080
> Keep in mind that <code>{'import.meta.env.SOME_ENV'}</code> <Link href="#static-replacement">is statically replaced</Link>:
8181
> ```ts
82+
> // ✅ Works
83+
> import.meta.env.SOME_ENV
8284
> // ❌ Won't work
8385
> import.meta.env['SOME_ENV']
8486
> // ❌ Won't work
8587
> const { SOME_ENV } = import.meta.env
86-
> // ✅ Works
87-
> import.meta.env.SOME_ENV
8888
> ```
8989
9090
@@ -102,7 +102,7 @@ For improved DX, consider using [`zod`](https://github.com/colinhacks/zod), for
102102
For better [tree shaking](https://rollupjs.org/introduction/#tree-shaking) (aka dead code elimination), `import.meta.env.SOME_ENV` is statically replaced with its value. For example:
103103
104104
```js
105-
// src/someFile.js [source code in Git repository]
105+
// src/someFile.js [source code in your Git repository]
106106
107107
console.log('value:', import.meta.env.DISABLE_TRACKING)
108108
@@ -128,14 +128,14 @@ console.log("value:", "true");
128128
console.log("Tracking is disabled");
129129
```
130130

131-
Note how the `import()` is completely removed, resulting in more lightweight production bundles.
131+
Note how `import()` is completely removed, resulting in a more lightweight production bundle.
132132

133133

134134
## Config files
135135

136-
In config files, [`import.meta.env` isn't available](https://github.com/vikejs/vike/issues/1726#issuecomment-2208626928) (neither `vite.config.js` nor `+config.js`).
136+
In config files, [<ImportMeta prop="env"/> isn't available](https://github.com/vikejs/vike/issues/1726#issuecomment-2208626928) (neither `vite.config.js` nor `+config.js`).
137137

138-
Use [`process.env`](https://nodejs.org/en/learn/command-line/how-to-read-environment-variables-from-nodejs) instead of `import.meta.env`.
138+
Use [`process.env`](https://nodejs.org/en/learn/command-line/how-to-read-environment-variables-from-nodejs) instead of <ImportMeta prop="env"/>.
139139

140140

141141
## Public allowlist

packages/vike/src/node/vite/plugins/pluginReplaceConstantsEnvVars.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { getFilePathToShowToUserModule } from '../shared/getFilePath.js'
1414
import { normalizeId } from '../shared/normalizeId.js'
1515
import { isViteServerSide_extraSafe } from '../shared/isViteServerSide.js'
1616
import { getMagicString } from '../shared/getMagicString.js'
17+
import pc from '@brillout/picocolors'
1718

1819
const PUBLIC_ENV_PREFIX = 'PUBLIC_ENV__'
1920
const PUBLIC_ENV_ALLOWLIST = [
@@ -29,7 +30,7 @@ const PUBLIC_ENV_ALLOWLIST = [
2930
// - Or stop using Vite's `mode` implementation and have Vike implement its own `mode` feature? (So that the only dependencies are `$ vike build --mode staging` and `$ MODE=staging vike build`.)
3031

3132
// === Rolldown filter
32-
const skipIrrelevant = 'import.meta.env.'
33+
const skipIrrelevant = 'import.meta.env'
3334
const filterRolldown = {
3435
/* We don't do that, because vike-react-sentry uses import.meta.env.PUBLIC_ENV__SENTRY_DSN
3536
id: {
@@ -118,6 +119,22 @@ function pluginReplaceConstantsEnvVars(): Plugin[] {
118119
magicString.replaceAll(new RegExp(regExpStr, 'g'), JSON.stringify(replacement))
119120
})
120121

122+
// Replace bare `import.meta.env` expression with `null` in the user-land.
123+
// - Otherwise Vite replaces it with an object missing PUBLIC_ENV__ variables which is confusing for users.
124+
// - We purposely don't support replacing `import.meta.env` with an object to incentivize users to write tree-shaking friendly code.
125+
// - `define: { 'import.meta.env': JSON.stringify(null) }` doesn't work because it also replaces `import.meta.env` inside `import.meta.env.SONE_ENV`
126+
const bareImportMetaEnvRegex = /\bimport\.meta\.env(?!\.)/g
127+
const isUserLand = !id.includes('node_modules') && id.startsWith(config.root) // skip node_modules/ as well as linked dependencies
128+
if (isUserLand && bareImportMetaEnvRegex.test(code)) {
129+
assertWarning(
130+
false,
131+
`The bare ${pc.cyan('import.meta.env')} expression in ${getFilePathToShowToUserModule(id, config)} is replaced with ${pc.cyan('null')} — use ${pc.cyan('import.meta.env.SONE_ENV')} instead ${pc.underline('https://vike.dev/env')}`,
132+
{ onlyOnce: true },
133+
)
134+
bareImportMetaEnvRegex.lastIndex = 0 // Reset state after .test() since the /g flag makes the RegExp stateful
135+
magicString.replaceAll(bareImportMetaEnvRegex, JSON.stringify(null))
136+
}
137+
121138
return getMagicStringResult()
122139
},
123140
},

packages/vike/src/node/vite/plugins/pluginReplaceConstantsGlobalThis.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ declare global {
2222
/** Like `import.meta.env.SSR` but works for `node_modules/` packages with `ssr.external` */
2323
var __VIKE__IS_CLIENT: boolean
2424
var __VIKE__IS_DEBUG: boolean
25+
/** Whether the code is processed by Vite, e.g. `true` when server code is `ssr.noExternal` */
26+
var __VIKE__NO_EXTERNAL: true | undefined
2527
}
2628

2729
const VIRTUAL_FILE_ID_constantsGlobalThis = 'virtual:vike:server:constantsGlobalThis'
@@ -55,6 +57,7 @@ function pluginReplaceConstantsGlobalThis(): Plugin[] {
5557
define: {
5658
'globalThis.__VIKE__IS_DEV': JSON.stringify(isDev),
5759
'globalThis.__VIKE__IS_DEBUG': JSON.stringify(isDebugVal),
60+
'globalThis.__VIKE__NO_EXTERNAL': 'true',
5861
},
5962
}
6063
},

packages/vike/src/shared-server-client/route/abort.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,13 +265,11 @@ function assertStatusCode(statusCode: number, expected: number[], caller: 'rende
265265
assert(import.meta.env.DEV === globalThis.__VIKE__IS_DEV)
266266
} else {
267267
assert(!isBrowser())
268-
if (import.meta.env) {
268+
if (globalThis.__VIKE__NO_EXTERNAL) {
269269
assert(typeof globalThis.__VIKE__IS_DEV === 'boolean')
270270
assert(typeof globalThis.__VIKE__IS_CLIENT === 'boolean')
271271
assert(import.meta.env.SSR === true)
272272
assert(import.meta.env.DEV === globalThis.__VIKE__IS_DEV)
273-
} else {
274-
// import.meta.env isn't defined when 'vike' is ssr.external
275273
}
276274
}
277275

0 commit comments

Comments
 (0)