-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
new __DEV__ handling #10915
new __DEV__ handling #10915
Conversation
🦋 Changeset detectedLatest commit: 03ff6c4 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
/release:pr |
Please add a changeset via |
✅ Deploy Preview for apollo-client-docs ready!
To edit notification comments on pull requests, go to your Netlify site settings. |
/release:pr |
A new release has been made for this PR. You can install it with |
size-limit report 📦
|
as the `undefined` check only works in the built lib, not the sources
/release:pr |
A new release has been made for this PR. You can install it with |
/release:pr |
A new release has been made for this PR. You can install it with |
So the good news is that even removing that
Uploaded test files are here:
Unfortunately, the server will run into CORS problems, so for more testing you'll have to download them and run them from The question is if it also works in all the other envs... |
For now, I will remove the |
Here is a diff of all built files: differences in *.js files
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes look good to me. Just had a couple questions in here. Thanks for tackling this difficult problem!
@@ -4,6 +4,7 @@ on: | |||
branches: | |||
- main | |||
- release-* | |||
- pr/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming this was for testing this branch. Do you still need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will generally be useful for PRs against other PR branches.
reverts #10521 (Simplify DEV polyfill to use imports instead of global scope)
more changes to come here, I just want to have a CI build already
Checklist:
On handling of
process.env.NODE_ENV
or__DEV__
I am trying to find a way here that doesn't crash, doesn't need us to globally polyfill
process.env.NODE_ENV
or__DEV__
,and still can be tree-shaken away in production builds.
Since we cannot assume that one of those values is always defined, we would want the "undefined" case to be handles as if
__DEV__
wastrue
.Problems
process.env.NODE_ENV
or__DEV__
are not defined in the browserThis is our baseline problem - a bundle with a naive check for either of those can be handled very gracefully by the bundler,
but will crash in-browser ESM imports.
Bundlers are stupid
Usually, bundlers rely on plain string replacement to replace
process.env.NODE_ENV
or__DEV__
with a primitive value.That means that in the case of
process.env.NODE_ENV
, the bundler will replaceprocess.env.NODE_ENV
with"production"
or
"development"
- but it will not fill in forprocess
orprocess.env
.So the bundler could not statically analyze "resilient" code like
typeof process !== "undefined" && process.env.NODE_ENV === "development"
.In the case of
__DEV__
, things become a bit easier since we don't have to check forprocess
orprocess.env
- simply replacing__DEV__
inthe statement
typeof __DEV__ == "undefined" || __DEV__
will for example result intypeof false == "undefined" || false
.Now, it depends on what the bundler does with
typeof false == "undefined"
.Unfortunately, most bundlers will handle this as non-evaluated runtime statement. In that case, it could not tree-shake.
We could now try to let the bundler replace
typeof __DEV__
with"undefined"
- but not all bundlers allow for string replacement on that level. (esbuild has no option for this)Defeating it just with logic
Finding a logical statement that, naively replaced by the bundler, can eliminate the
typeof
would work if we would only go for__DEV__ === true
, but not for__DEV__ === true || __DEV__ === undefined
- in the latter case, there will always be some "runtime-type" statement left that the bundler cannot eliminate.Getting rid of the
typeof
This is the strategy I'm settling on now: If we can get rid of the
typeof
, we get something that can always be replaced by bundlers.My current approach for that is to use
globalThis.__DEV__
- this will not by default be replaced by most bundlers, but at least they can be configured to be replaced.The logical statement I've ended up is
globalThis.__DEV__ !== false
.In the wild
.swcrc
:next.config.js
:vite.config.ts
using craco
craco.config.js
See this later comment for more detail