'Detect React/ReactDOM development/production build
React development build behaves differently than production build, e.g. error handling.
It can be figured out which one is used from the environment but only in modular environment, due to how process.env.NODE_ENV
is used by React package:
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react.production.min.js');
} else {
module.exports = require('./cjs/react.development.js');
}
The case when process.env
may be inapplicable is React used globally as UMD module, window.React
and window.ReactDOM
:
<script src="some-unknown-react-version.js"></script>
<script>
React // is it in production mode?
</script>
Possible uses are:
a component that can work in modular and global environments (published as UMD) and renders differently in production
browser extension or user script where build/production mode is detected from
React
orReactDOM
object
How can React development/production build be accurately detected at runtime without resorting to the environment?
I'm looking for reliable and clean solution that would be applicable to React 15 and React 16 if possible.
This is not a duplicate of similar questions because existing answers address the problem through process.env
.
Solution 1:[1]
There is difference. In the development mode, React elements have the property _self
defined, whereas in production mode that property is not defined.
So, a solution is to test for this property with a code like this:
function ReactIsInDevelomentMode(){
return '_self' in React.createElement('div');
}
Solution 2:[2]
Your question is clear but you do not clarify your build system, do you use webpack
or parcel
? do you have Server Side Rendering
or not? do you run your built application by node
or pm2
? or you just build your application and then put the built bundled file inside your page that made by other technology like PHP
or C#
?
Actually, the above questions can determine your answer, but surely, you use module bundler, so I proffer use resolving a config
file in your project.
If I was your place, undoubtedly, I use webpack
, two webpack configuration files, one for development and one for production mode. then I create a folder that contains two files with config.dev.js
and config.prod.js
. In the development webpack:
~~~
module.exports = {
~~~
resolve: {
extensions: ['.js', '.jsx'],
alias: {
~~~
Config: `${srcDir}/config/config.dev.js`,
// srcDir is a defined variable for source directory
}
},
~~~
In the production webpack:
~~~
module.exports = {
~~~
resolve: {
extensions: ['.js', '.jsx'],
alias: {
~~~
Config: `${srcDir}/config/config.prod.js`,
// srcDir is a defined variable for source directory
}
},
~~~
And now you can put each dev
and prod
data for your build types. for example in your config.dev.js
can write:
module.exports = {
buildType: "dev"
};
Surely, in your config.prod.js
can write:
module.exports = {
buildType: "prod"
};
Absolutely you can access to the config data with below code inside your react
files:
import config from 'Config';
And with this solution, you can understand the type of your build in the real-time execution of your application.
Note: For more information, you can see my medium article, And if you are not familiar with long reads see the article repository Also the newer version of the example of my answer repository that contains configs.
Solution 3:[3]
Detecting dev/production build at client using a umd build seems like a long stretch.
If such a requirement exists why not build your app with create-react-app
?
I am not to judge your decisions, so here is something useful.
react-dev-tools
plugin provided by facebook
detects the build type.
Here is the relevant part of the above mentioned plugin:
Hope you could make it useful.
Solution 4:[4]
There'is a little 'hack' which can be done for checking which version of React has been loaded.
React object is available in global variables, and the production build of the React differs from the development version by at least one thing: it's usually minified. So we can try to check if we are working with minified version or not.
To check you can compare function name with the property name of some React object's method, e.g.:
let func = 'Component'
if (React[func].name === func) {
// non-minified -> development build
}
This method is not about checking production and development but about check the minification, and since production build is usually minified it can really help.
Solution 5:[5]
React provides both development and production version of react.js links:
Development:
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
Production:
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
And to know if it is in development mode or production mode without environment variable, you have to explicitly declare some variable by assigning its mode: (include the following script along with react script)
<script>
var devMode = 'development';
</script>
and check for the devMode whenever necessary.
Alternatively, you may check for its mode like: (you have to add id in the script tag)
var script_id = document.getElementById('script-attached-id');
console.log(script_id.getAttribute('src').includes('development'));
This way, you only need to update the source path and detect the mode.
And the final option, I can think of reading the file itself and detect its mode since react has mentioned in its comment like:
Development:
/** @license React v16.5.2
* react.development.js
Production:
/** @license React v16.5.2
* react.production.min.js
So, after reading the file, just check for it's mode in second line. Or you may test for react.development.js
without line by line check.
Solution 6:[6]
How does your deployment setup look like? There is no "correct" way to do what you want to do. I would focus on differences between production/development build and create my own helper function.
EDIT: It looks like it is not possible to detect prod/dev version from React
class.
Two ideas:
- I am not sure how is the application built but
PropTypes
should be a good ENV identifier. - If your production React application is minified then you can simply detect if the react code is minified. (this will be hacky but it should work, focus on a number of spaces or line length, ... )
I noticed in the comments below that you say that minified !== production
if you can make it this way then this is probably your best bet. You don't need to minify development react code anyway.
Solution 7:[7]
Some have touched on using the fact that production will always be minified and development won't be minified. Here's a concrete solution that uses this:
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react.js"></script>
<script>
const reactInfo = {
version: React.version,
development: (String((new React.Children.map()).constructor).length > 100)
};
console.log(reactInfo);
</script>
<div id="content"></div>
I've tested this on about a dozen versions of react from v14 to v16. From here you can see that this code hasn't been touched since it was first written, except for one small edit from a year ago (Which wouldn't effect this answer because it's too few characters, though I've tested versions before 11mo ago anyway and there's a decent gap).
Note
Dev is 200 characters and Prod is 70, so there's a 3:1 ratio for a Dev:Prod character ratio. I picked 100 because adding 90 characters of code will add 30 lines to prod, so 100 is the best location with the information given (Technically ~105 or something). Adding 90 characters or removing 100 characters is extremely unlikely for such a simple function (a function that has been touched only once in 5 years with a 20 character edit), so I think this should be stable.
For more stability, or at least knowledge if it breaks, you can check if it's within 25 characters of 70 and 200, and throw an error if it's not. That should catch any big changes (I'd give that option near 100% certainty that it'll never hide a bug), but you might get false positives. Which one you want depends on your use case.
EDIT:
Looking into minification, this is a regex that'll deduce if a function has been minified, so you can use this one safely. It'll also crash if React.Children.map
is not a function (Will almost certainly never happen), which you can either catch or not catch depending on how strict you want to handle the unlikely event of an error (Or just ignore it, becuase like, why would they ever change it). The function signature remains, even if it gets minified into [native code]
, so it's rather future-proof imo. I'd go with the first one for simplicity though.
const reactInfo = {
version: React.version,
development: !/function\s?\w?\(\w(,\w)*\)/.test(String((new React.Children.map()).constructor).split("{")[0])
};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Constantin Galbenu |
Solution 2 | AmerllicA |
Solution 3 | Arun Karunagath |
Solution 4 | Dolf Barr |
Solution 5 | |
Solution 6 | |
Solution 7 |