diff --git a/docs/pages/blog/vike-server/+Page.mdx b/docs/pages/blog/vike-server/+Page.mdx
index 2dad7c053ab..3c8725407ec 100644
--- a/docs/pages/blog/vike-server/+Page.mdx
+++ b/docs/pages/blog/vike-server/+Page.mdx
@@ -1,4 +1,4 @@
-import { Link } from '@brillout/docpress'
+import { Link, ImportMeta } from '@brillout/docpress'
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs'
import '../../../components/tabs.css'
import { BlogHeader } from '../BlogHeader'
@@ -8,7 +8,7 @@ import { BlogHeader } from '../BlogHeader'
We (Joël, Dani, and Rom) have been working on a new Vike extension `vike-server` which can integrate Vite with any server (Express.js, Hono, Fastify, Elysia, H3, ...) and any deployment (VPS, Netlify, Cloudflare, Vercel, ...).
With `vike-server` you get:
- - Server code **transpiled by Vite** (say goodbye to `ts-node`/`tsx`/`vavite` and hello to Vite utilities such as `import.meta.env`)
+ - Server code **transpiled by Vite** (say goodbye to `ts-node`/`tsx`/`vavite` and hello to Vite utilities such as )
- **Zero-config** (Vike is automatically added to your server)
- **HMR** (no more full server reloads)
diff --git a/docs/pages/env/+Page.mdx b/docs/pages/env/+Page.mdx
index a97bf9bd9d2..0e456e9fd50 100644
--- a/docs/pages/env/+Page.mdx
+++ b/docs/pages/env/+Page.mdx
@@ -43,7 +43,7 @@ DATABASE_URL=postgresql://database.example.com:5432
## Access
-Use `import.meta.env` to access environment variables.
+Use to access environment variables.
```ts
// /pages/movies/+data.ts
@@ -79,12 +79,12 @@ function ContactUs() {
> Keep in mind that {'import.meta.env.SOME_ENV'} is statically replaced:
> ```ts
+> // ✅ Works
+> import.meta.env.SOME_ENV
> // ❌ Won't work
> import.meta.env['SOME_ENV']
> // ❌ Won't work
> const { SOME_ENV } = import.meta.env
-> // ✅ Works
-> import.meta.env.SOME_ENV
> ```
@@ -102,7 +102,7 @@ For improved DX, consider using [`zod`](https://github.com/colinhacks/zod), for
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:
```js
-// src/someFile.js [source code in Git repository]
+// src/someFile.js [source code in your Git repository]
console.log('value:', import.meta.env.DISABLE_TRACKING)
@@ -128,14 +128,14 @@ console.log("value:", "true");
console.log("Tracking is disabled");
```
-Note how the `import()` is completely removed, resulting in more lightweight production bundles.
+Note how `import()` is completely removed, resulting in a more lightweight production bundle.
## Config files
-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`).
+In config files, [ isn't available](https://github.com/vikejs/vike/issues/1726#issuecomment-2208626928) (neither `vite.config.js` nor `+config.js`).
-Use [`process.env`](https://nodejs.org/en/learn/command-line/how-to-read-environment-variables-from-nodejs) instead of `import.meta.env`.
+Use [`process.env`](https://nodejs.org/en/learn/command-line/how-to-read-environment-variables-from-nodejs) instead of .
## Public allowlist
diff --git a/packages/vike/src/node/vite/plugins/pluginReplaceConstantsEnvVars.ts b/packages/vike/src/node/vite/plugins/pluginReplaceConstantsEnvVars.ts
index 2dd3e053b76..cb8ebbce656 100644
--- a/packages/vike/src/node/vite/plugins/pluginReplaceConstantsEnvVars.ts
+++ b/packages/vike/src/node/vite/plugins/pluginReplaceConstantsEnvVars.ts
@@ -14,6 +14,7 @@ import { getFilePathToShowToUserModule } from '../shared/getFilePath.js'
import { normalizeId } from '../shared/normalizeId.js'
import { isViteServerSide_extraSafe } from '../shared/isViteServerSide.js'
import { getMagicString } from '../shared/getMagicString.js'
+import pc from '@brillout/picocolors'
const PUBLIC_ENV_PREFIX = 'PUBLIC_ENV__'
const PUBLIC_ENV_ALLOWLIST = [
@@ -29,7 +30,7 @@ const PUBLIC_ENV_ALLOWLIST = [
// - 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`.)
// === Rolldown filter
-const skipIrrelevant = 'import.meta.env.'
+const skipIrrelevant = 'import.meta.env'
const filterRolldown = {
/* We don't do that, because vike-react-sentry uses import.meta.env.PUBLIC_ENV__SENTRY_DSN
id: {
@@ -118,6 +119,22 @@ function pluginReplaceConstantsEnvVars(): Plugin[] {
magicString.replaceAll(new RegExp(regExpStr, 'g'), JSON.stringify(replacement))
})
+ // Replace bare `import.meta.env` expression with `null` in the user-land.
+ // - Otherwise Vite replaces it with an object missing PUBLIC_ENV__ variables which is confusing for users.
+ // - We purposely don't support replacing `import.meta.env` with an object to incentivize users to write tree-shaking friendly code.
+ // - `define: { 'import.meta.env': JSON.stringify(null) }` doesn't work because it also replaces `import.meta.env` inside `import.meta.env.SONE_ENV`
+ const bareImportMetaEnvRegex = /\bimport\.meta\.env(?!\.)/g
+ const isUserLand = !id.includes('node_modules') && id.startsWith(config.root) // skip node_modules/ as well as linked dependencies
+ if (isUserLand && bareImportMetaEnvRegex.test(code)) {
+ assertWarning(
+ false,
+ `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')}`,
+ { onlyOnce: true },
+ )
+ bareImportMetaEnvRegex.lastIndex = 0 // Reset state after .test() since the /g flag makes the RegExp stateful
+ magicString.replaceAll(bareImportMetaEnvRegex, JSON.stringify(null))
+ }
+
return getMagicStringResult()
},
},
diff --git a/packages/vike/src/node/vite/plugins/pluginReplaceConstantsGlobalThis.ts b/packages/vike/src/node/vite/plugins/pluginReplaceConstantsGlobalThis.ts
index 3ab34518da7..c2fba67272c 100644
--- a/packages/vike/src/node/vite/plugins/pluginReplaceConstantsGlobalThis.ts
+++ b/packages/vike/src/node/vite/plugins/pluginReplaceConstantsGlobalThis.ts
@@ -22,6 +22,8 @@ declare global {
/** Like `import.meta.env.SSR` but works for `node_modules/` packages with `ssr.external` */
var __VIKE__IS_CLIENT: boolean
var __VIKE__IS_DEBUG: boolean
+ /** Whether the code is processed by Vite, e.g. `true` when server code is `ssr.noExternal` */
+ var __VIKE__NO_EXTERNAL: true | undefined
}
const VIRTUAL_FILE_ID_constantsGlobalThis = 'virtual:vike:server:constantsGlobalThis'
@@ -55,6 +57,7 @@ function pluginReplaceConstantsGlobalThis(): Plugin[] {
define: {
'globalThis.__VIKE__IS_DEV': JSON.stringify(isDev),
'globalThis.__VIKE__IS_DEBUG': JSON.stringify(isDebugVal),
+ 'globalThis.__VIKE__NO_EXTERNAL': 'true',
},
}
},
diff --git a/packages/vike/src/shared-server-client/route/abort.ts b/packages/vike/src/shared-server-client/route/abort.ts
index fbbaba21046..de3917db7b5 100644
--- a/packages/vike/src/shared-server-client/route/abort.ts
+++ b/packages/vike/src/shared-server-client/route/abort.ts
@@ -265,13 +265,11 @@ function assertStatusCode(statusCode: number, expected: number[], caller: 'rende
assert(import.meta.env.DEV === globalThis.__VIKE__IS_DEV)
} else {
assert(!isBrowser())
- if (import.meta.env) {
+ if (globalThis.__VIKE__NO_EXTERNAL) {
assert(typeof globalThis.__VIKE__IS_DEV === 'boolean')
assert(typeof globalThis.__VIKE__IS_CLIENT === 'boolean')
assert(import.meta.env.SSR === true)
assert(import.meta.env.DEV === globalThis.__VIKE__IS_DEV)
- } else {
- // import.meta.env isn't defined when 'vike' is ssr.external
}
}