Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

import.meta.env.DEV and PROD are incorrect if a custom mode is provided programmatically #9203

Closed
7 tasks done
Rich-Harris opened this issue Jul 18, 2022 · 17 comments
Closed
7 tasks done
Labels
breaking change enhancement New feature or request p2-to-be-discussed Enhancement under consideration (priority)
Milestone

Comments

@Rich-Harris
Copy link
Contributor

Describe the bug

Ordinarily, building a Vite app results in import.meta.env.DEV === false and import.meta.env.PROD === true regardless of the mode configuration.

If you set mode when calling vite.build(...) programmatically, however, DEV and PROD are true and false unless the mode happens to be production.

Reproduction

https://github.com/Rich-Harris/vite-mode-repro

System Info

System:
    OS: macOS 12.0.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 779.03 MB / 32.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.15.1 - ~/.nvm/versions/node/v16.15.1/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v16.15.1/bin/yarn
    npm: 8.11.0 - ~/.nvm/versions/node/v16.15.1/bin/npm
  Browsers:
    Chrome: 103.0.5060.114
    Chrome Canary: 105.0.5187.0
    Firefox: 102.0.1
    Safari: 15.1
  npmPackages:
    vite: ^3.0.2 => 3.0.2

Used Package Manager

npm

Logs

No response

Validations

@bluwy
Copy link
Member

bluwy commented Jul 19, 2022

I think this is expected behaviour per the docs. You'd need to set NODE_ENV=production in .env.[mode] to bring back the prod behaviour. Maybe it make sense to default to production for builds but it would be a breaking change.

@cedeber
Copy link
Contributor

cedeber commented Jul 19, 2022

We have the same issue here. The NODE_ENV=production doesn't set import.meta.env.PROD to true, unlike with Vite 2.

@bluwy
Copy link
Member

bluwy commented Jul 19, 2022

@cedeber can you provide a repro for that? Using the repro in this issue, adding .env.custom-programmatic with NODE_ENV=production fixed it for me.

@cedeber
Copy link
Contributor

cedeber commented Jul 19, 2022

Unfortunately no. But I think I've found the change (not sure it's an issue though).
We use Node workspaces but the run script, the vite config file and the .env file are on the root of the project.
So vite.config.ts contains root: "./packages/application/src".

If I move the env.staging file in this folder (instead of the root of the project /), then it works again. I also tried to log VITE_SOME_KEY=123 as in the example and it works.

@benmccann
Copy link
Collaborator

I'll go ahead and close this since I agree with @bluwy that it's working as intended

@Rich-Harris
Copy link
Contributor Author

Hang on a sec @benmccann — it's not working as intended. Either dev should be true in both cases where a custom mode is provided, or in neither. That's a matter for debate — personally I think it's bizarre that DEV is basically an alias for MODE !== 'production', and that it should instead reflect command — but either way there's a bug here.

@benmccann benmccann reopened this Jul 19, 2022
@Rich-Harris
Copy link
Contributor Author

I think this is expected behaviour per the docs

The docs are a bit ambiguous, I think:

image

A lot hinges on the interpretation of 'running in production'. If it means 'running in production' — i.e. MODE is "production" — then PROD should indeed be false if MODE === 'custom'. But by that logic, so should DEV! That's incompatible with "(always the opposite of import.meta.env.PROD)".

If instead 'production' means 'the output of vite build rather than vite dev' — which I think makes a lot more sense — then the docs are internally coherent, if slightly ambiguously worded.

I'd argue that since the observed behaviour depends entirely on whether mode is provided via vite.config.js or programmatically, it's effectively undefined, meaning we have the opportunity to choose the semantics that make the most sense and characterise it as a bugfix :)

@benmccann
Copy link
Collaborator

Here's the logic as implemented, which looks at a few different variables to figure out if it's production:

const isProduction =

@benmccann
Copy link
Collaborator

benmccann commented Jul 19, 2022

I'm not sure it should reflect command. E.g. I think you should be able to test serving in production mode. If you want to know what command was run then it's probably safest to look at command.

But it does sounds like there's a bug here if passing the mode programatically and via vite.config.js are not behaving the same.

@benmccann benmccann added bug p3-downstream-blocker Blocking the downstream ecosystem to work properly (priority) and removed pending triage labels Jul 19, 2022
@cedeber
Copy link
Contributor

cedeber commented Jul 19, 2022

Wow, it was not clear for me that vite build --mode production would switch to PROD without the .env file.
I always found weird that vite build switched to DEV by default because a --mode is set. I always consider mode to be a way to manipulate a bit the config but never that it will switch the PROD/END env vars.
What happens then if you use it the other way, with --mode development and set a .env with NODE_ENV=production?

I believe the mode should stay a string and don't change the behavior with some hidden keywords. And I understand better that a build is always production except if you force it via the NODE_ENV=development, disregarding the meaning of the mode string.

@Rich-Harris
Copy link
Contributor Author

I'm not sure it should reflect command

That's a valid position, but it's often very useful to know if you're in vite dev or vite build (without juggling mode), so if that's the conclusion then I'd propose the addition of a new value:

import.meta.env.COMMAND; // 'build' or 'serve'

@cedeber
Copy link
Contributor

cedeber commented Jul 19, 2022

So vite dev gives COMMAND == "serve". That's how to make it even more confusing, imho.

@bluwy
Copy link
Member

bluwy commented Jul 20, 2022

Either dev should be true in both cases where a custom mode is provided, or in neither. That's a matter for debate — personally I think it's bizarre that DEV is basically an alias for MODE !== 'production', and that it should instead reflect command — but either way there's a bug here.

DEV isn't an alias for MODE !== 'production', it's more of an alias for process.env.NODE_ENV !== 'production', but only using MODE if process.env.NODE_ENV is not defined, since we need a value as a fallback (which IIUC this issue proposes to fallback with command === 'serve' or command === 'build' instead).

And according to https://vitejs.dev/guide/env-and-mode.html#modes:

However, it is important to understand that mode is a wider concept than just development vs. production. A typical example is you may want to have a "staging" mode where it should have production-like behavior, but with slightly different env variables from production.

It further explains that mode isn't something that affects dev / prod, it's just another "mode" your app is in, you have to configure what the "environment" is to affect dev / prod. Just that production "mode" gets special treatment as a prod "environment" by default.

So I think this isn't a bug. Maybe we could improve the docs, or implement a good fallback as proposed (which I think make sense, but for Vite 4), but it is still working as intended.

@bluwy bluwy added enhancement New feature or request breaking change and removed bug p3-downstream-blocker Blocking the downstream ecosystem to work properly (priority) labels Jul 21, 2022
@theetrain
Copy link

Thanks for the illuminating discussion. The only way I'm able to get import.meta.env.PROD to be true was with vite build.

Assuming the logic mentioned above:

const isProduction =
(process.env.NODE_ENV || process.env.VITE_USER_NODE_ENV || mode) ===
'production'

I tried running my code in production mode using vite dev, but none of the following worked for me:

  • NODE_ENV=production vite dev
  • vite dev --mode production
  • Contents of .env includes NODE_ENV=production and VITE_USER_NODE_ENV=production then I run vite dev

Is it safe to say that configuring production mode is only possible with vite build? I propose the current behaviour should be documented so it's clearer how to use Vite in production mode. I'm happy to contribute to the docs once I have a solid understanding of current config behaviour.

@bluwy
Copy link
Member

bluwy commented Aug 2, 2022

Is it safe to say that configuring production mode is only possible with vite build? I propose the current behaviour should be documented so it's clearer how to use Vite in production mode. I'm happy to contribute to the docs once I have a solid understanding of current config behaviour.

Yes, you can't set production in dev as some integrations only apply HMR for non-prod environments. This behaviour is set at:

if (command === 'serve' && process.env.NODE_ENV === 'production') {
process.env.NODE_ENV = 'development'
}

I agree that we could probably mention this somewhere in the docs.

@benmccann
Copy link
Collaborator

Discussion here: #9274

@benmccann benmccann moved this to Discussing in Team Board Oct 19, 2022
@benmccann benmccann added the p2-to-be-discussed Enhancement under consideration (priority) label Oct 19, 2022
@benmccann benmccann moved this from Discussing to P2 - 4 in Team Board Oct 19, 2022
@benmccann benmccann added this to the 4.0 milestone Oct 25, 2022
@bluwy
Copy link
Member

bluwy commented Nov 28, 2022

I believe this is fixed in #10996. Vite build will always default to prod by default, unless specifically changed with NODE_ENV=development in the env file, or in process.env.

@bluwy bluwy closed this as completed Nov 28, 2022
@github-actions github-actions bot locked and limited conversation to collaborators Dec 13, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
breaking change enhancement New feature or request p2-to-be-discussed Enhancement under consideration (priority)
Projects
Archived in project
Development

No branches or pull requests

5 participants