`process.env`, `globalThis`, and `typeof process`
Problem
This is a writeup to discuss this problem in the GraphQL-WG and the GraphQL-JS-WG. Please give feedback in either of those meetings, or here in the issue, until the next GraphQL-JS-WG meeting, where we want to make a final call on this issue. Last year, #3887 was released which changed the dev check in `src/jsutils/instanceOf.ts` from [code block] to [code block] shortly followed by #3923, which changed it to [code block] as some bundlers were choking on the optional chaining syntax. Since then, various issues and PRs have been opened to change into various other forms. I'll try to give an overview over problems, potential solutions and their shortcomings here so we can decide on a way forward. Problems: 1. accessing `process.env.NODE_ENV` directly There is a bunch of environments (e.g. ESM in the browser), where accessing `process.env` directly just crashes, since `process` is not a variable. 2. accessing `globalThis.process.env.NODE_ENV`: bundler replacement Some bundlers do a string replacement of `process.env.NODE_ENV`, which lead to the code being replaced by invalid JavaScript like `globalThis."production"`. (Afaik, most of these have been reported in the upstream bundlers at this point in time and they have fixed their regular expressions) 3. accessing `process.env.NODE_ENV` or `globalThis.process.env.NODE_ENV` while testing for `process`, without checking if the `env` property is set: DOM elements with the id `process` If a DOM element with the `id` `proc
Unverified for your environment
Select your OS to check compatibility.
1 Fix
Refactor Environment Variable Access for Compatibility
The issue arises from the direct access of `process.env.NODE_ENV` in environments where `process` is undefined, such as ESM in the browser. Additionally, bundlers may incorrectly replace `process.env.NODE_ENV`, leading to invalid JavaScript. The presence of DOM elements with the id `process` can also cause conflicts when checking for `process` existence.
Awaiting Verification
Be the first to verify this fix
- 1
Check for Process Availability
Implement a check to determine if `process` is defined before accessing `process.env.NODE_ENV`. This prevents crashes in environments where `process` is not available.
typescriptconst isNodeEnvAvailable = typeof process !== 'undefined' && process.env && process.env.NODE_ENV; - 2
Use GlobalThis Fallback
If `process` is not defined, fallback to `globalThis.process` to ensure compatibility across various environments. This avoids direct access to `process` and mitigates bundler issues.
typescriptconst nodeEnv = isNodeEnvAvailable ? process.env.NODE_ENV : (typeof globalThis.process !== 'undefined' ? globalThis.process.env.NODE_ENV : 'development'); - 3
Avoid DOM ID Conflicts
Ensure that there are no DOM elements with the id `process` to prevent conflicts. Consider renaming any such elements to avoid confusion with the `process` object.
html// Rename any DOM element with id 'process' to avoid conflicts. - 4
Update Bundler Configuration
Review and update the bundler configuration to ensure that it correctly handles `process.env.NODE_ENV` without causing invalid replacements. This may involve adjusting regular expressions used for string replacements.
javascript// Example configuration change in Webpack to handle process.env correctly. - 5
Testing and Validation
Create unit tests to validate that accessing `NODE_ENV` works correctly in various environments, including Node.js, ESM, and browsers. Ensure that tests cover scenarios with and without the `process` object.
typescriptit('should access NODE_ENV correctly', () => { expect(nodeEnv).toBe('development'); });
Validation
Confirm that the application runs without crashing in environments where `process` is not defined, and that `NODE_ENV` is correctly accessed in all scenarios. Run unit tests to ensure all cases are covered.
Sign in to verify this fix
Environment
Submitted by
Alex Chen
2450 rep