vite
vite copied to clipboard
Dev server is stateful in regards to env vars
Describe the bug
Bit of a weird one, but the dev server seems to be stateful in its handling of env vars, in that you must access the the root (/) before the env vars are inserted into (say) a JS asset. This shouldn't happen, served assets shouldn't change depending on the order of access.
Note: Stackblitz seems to always redirect to / upon starting a dev server, or at least I couldn't figure out how to get it to not, hence the GitHub repo reproduction.
Reproduction
https://github.com/rschristian/bug__vite-env-vars
Steps to reproduce
npm install&&npm run dev- navigate to http://localhost:5173/main.js
- Notice the returned asset looks like this:
/main.js
console.log(`vite mode: ${import.meta.env.MODE}`);
- navigate to http://localhost:5173
- navigate back to http://localhost:5173/main.js
- Notice the return asset looks like this:
/main.js
import.meta.env = {"BASE_URL": "/", "MODE": "development", "DEV": true, "PROD": false, "SSR": false};console.log(`vite mode: ${import.meta.env.MODE}`);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm1haW4uanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0Lm1ldGEuZW52ID0ge1wiQkFTRV9VUkxcIjogXCIvXCIsIFwiTU9ERVwiOiBcImRldmVsb3BtZW50XCIsIFwiREVWXCI6IHRydWUsIFwiUFJPRFwiOiBmYWxzZSwgXCJTU1JcIjogZmFsc2V9O2NvbnNvbGUubG9nKGB2aXRlIG1vZGU6ICR7aW1wb3J0Lm1ldGEuZW52Lk1PREV9YCk7XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQzsifQ==
System Info
System:
OS: Linux 6.8 EndeavourOS
CPU: (4) x64 AMD Ryzen 7 5800X 8-Core Processor
Memory: 6.44 GB / 11.65 GB
Container: Yes
Shell: 5.9 - /usr/bin/zsh
Binaries:
Node: 18.20.2 - /usr/bin/node
Yarn: 1.22.22 - /usr/bin/yarn
npm: 10.7.0 - /usr/bin/npm
pnpm: 9.1.2 - /usr/bin/pnpm
Browsers:
firefox-developer-edition: 127.0b4
npmPackages:
vite: ^5.2.0 => 5.2.12
Used Package Manager
npm
Logs
No response
Validations
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to vuejs/core instead.
- [X] Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- [X] The provided reproduction is a minimal reproducible example of the bug.
It looks like what's happening is that Vite's transformMiddleware changes response based on Accept: text/html request header (which Browser sets when opening a page directly):
https://github.com/vitejs/vite/blob/dbd6214f6fa5d35647cbd00580c76788ce894e9e/packages/vite/src/node/server/middlewares/transform.ts#L198-L200
but this affects only when there's no vite server module cache, so the behavior looks inconsistent.
https://github.com/vitejs/vite/blob/dbd6214f6fa5d35647cbd00580c76788ce894e9e/packages/vite/src/node/server/transformRequest.ts#L251-L255
When there's no cache, Vite fallbacks to viteServeStaticMiddleware and it responds plain js file content. Another factor is that Vite also has cachedTransformMiddleware which returns early based on etag and if-none-match.
Here is a simpler repro using curl:
$ curl -H 'Accept: text/html' http://localhost:5173/main.js
console.log(`vite mode: ${import.meta.env.MODE}`);
$ curl http://localhost:5173/main.js
import.meta.env = {"BASE_URL": "/", "DEV": true, "MODE": "development", "PROD": false, "SSR": false};console.log(`vite mode: ${import.meta.env.MODE}`);
//# sourceMappingURL=data:application/json;base64,eyJ2Z...
$ curl -H 'Accept: text/html' http://localhost:5173/main.js
import.meta.env = {"BASE_URL": "/", "DEV": true, "MODE": "development", "PROD": false, "SSR": false};console.log(`vite mode: ${import.meta.env.MODE}`);
//# sourceMappingURL=data:application/json;base64,eyJ2Z...