Proposal, specs, and reference implementation for global.env
, a standard representation of the current runtime environment.
Spec drafted by @milesj and @kesne.
Requires the global proposal by @ljharb.
There's no standardized, cross-platform, developer-friendly way to detect what environment you're running code in. The JavaScript community has generally centered around using process.env.NODE_ENV
, but this statement feels out of place in the browser, within mobile, and any other non-Node.js environment.
Furthermore, consistently typing process.env.NODE_ENV !== 'production'
is rather verbose, and using __DEV__
flags require a transpilation step. This proposal aims to provide a straight-forward and improved developer experience.
Using the global
object allows for instant access and evaluation within any scope, and once the global proposal lands, this object will further allow for cross-platform consistency and interoperability.
The global.env
property is currently undefined across all platforms. Please refer to the Naming chapter for more information.
The global.env
property is an object that provides the current environment as a constant, an is()
method for comparison, and additional boolean flags for easy lookup.
Object.defineProperty(global, 'env', {
configurable: false,
enumerable: false,
writable: false,
value: Object.freeze({
current: ENV_FLAG,
development: (ENV_FLAG === 'development'),
production: (ENV_FLAG === 'production'),
is(name) {
return (ENV_FLAG === name);
},
}),
});
ENV_FLAG
will resolve to"production"
in a browser (unless built otherwise), andprocess.env.NODE_ENV
in Node.js.
All properties on the global.env
object are immutable and cannot be modified at runtime.
The current environment as a string. Defaults to "production"
.
A boolean flag for detecting the development
environment. A shorthand for global.env.is('development')
.
A boolean flag for detecting the production
environment. A shorthand for global.env.is('production')
.
A function for comparing an argument against the current environment name. Can be used for situations where the environment name is not development
or production
.
global.env.is('staging');
Since the global
object is, well, global, we can omit the global
object path and simply use env
. Below are a few examples of real world usage.
if (env.production) {
// In production
}
if (env.is('test')) {
// Unit testing
}
We can also replace verbose process.env
Node.js conditionals and app-specific __DEV__
constants.
// Before
if (__DEV__) {}
if (process.env.NODE_ENV !== 'production') {}
if (process.env.NODE_ENV === 'development') {}
// After
if (!env.production) {}
if (!env.production) {}
if (env.development) {}
We chose the name env
, as it's short, and most programming languages, build tools, and developers are familiar with this term -- e.g., .env
files, ENV
variables, etc. Additionally, window.env
is available in the browser, and global.env
in Node.js (and ReactNative).
Platform | global defined? |
global.env available? |
Current env detection |
---|---|---|---|
Node.js | Yes | Yes | process.env.NODE_ENV |
Electron (uses Node.js) | ~ | ~ | ~ |
JavaScriptCore (Safari) | With window |
Yes | |
ReactNative (uses JSC) | ~ | ~ | __DEV__ |
V8 (Chrome) | With window |
Yes | |
SpiderMonkey (Firefox) | With window |
Yes | |
ChakraCore (IE/Edge) | With window |
Yes |
The tilde (~) inherits from the parent.
- How to set
global.env.current
in the browser? Should this be mutable? - If mutable, how do we restrict modification to the current application? And not from third-party modules?