检测 React/ReactDOM development/production 构建
Detect React/ReactDOM development/production build
React 开发构建的行为不同于生产构建,例如错误处理。
可以从环境中判断出使用哪一个,但仅限于模块化环境,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');
}
可能process.env
不适用的情况是React全局用作UMD模块,window.React
和window.ReactDOM
:
<script src="some-unknown-react-version.js"></script>
<script>
React // is it in production mode?
</script>
可能的用途是:
一个可以在模块化和全局环境中工作的组件(作为 UMD 发布)并在生产中以不同方式呈现
浏览器扩展或用户脚本,其中 build/production 模式是从 React
或 ReactDOM
对象
检测到的
如何在不借助环境的情况下,在运行时准确检测 React development/production 构建?
我正在寻找适用于 React 15 和 React 16(如果可能)的可靠且干净的解决方案。
这不是类似问题的重复,因为现有答案通过 process.env
解决了问题。
React 提供开发版和生产版 react.js 链接:
发展:
<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>
生产:
<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>
并且要知道它是处于开发模式还是生产模式没有环境变量,你必须通过分配显式声明一些变量它的模式:(包括以下脚本和反应脚本)
<script>
var devMode = 'development';
</script>
并在必要时检查 devMode。
或者,您可以像这样检查它的模式:(您必须在脚本标签中添加 id)
var script_id = document.getElementById('script-attached-id');
console.log(script_id.getAttribute('src').includes('development'));
这样只需要更新源路径和检测模式即可
最后一个选项,我可以考虑读取文件本身并检测其模式,因为 React 在其评论中提到:
发展:
/** @license React v16.5.2
* react.development.js
生产:
/** @license React v16.5.2
* react.production.min.js
因此,读取文件后,只需在第二行检查它的模式。或者您可以测试 react.development.js
而无需逐行检查。
使用 umd 构建在客户端检测 dev/production 构建似乎是一个漫长的过程。
如果存在这样的要求,为什么不使用 create-react-app
构建您的应用程序?
我不会评判你的决定,所以这里有一些有用的东西。
react-dev-tools
facebook
提供的插件检测构建类型。
这里是上述插件的相关部分:
希望你能使它有用。
有一点 'hack' 可以检查已加载的 React 版本。
React 对象在全局变量中可用,并且 React 的生产版本与开发版本至少有一点不同:它通常被缩小。所以我们可以尝试检查我们是否正在使用缩小版本。
要检查,您可以将函数名称与某些 React 对象方法的 属性 名称进行比较,例如:
let func = 'Component'
if (React[func].name === func) {
// non-minified -> development build
}
这种方法不是检查生产和开发,而是检查缩小,而且由于生产构建通常是缩小的,所以它真的很有帮助。
您的部署设置如何?没有 "correct" 方法可以做您想做的事。我会关注 production/development 构建和创建我自己的辅助函数之间的差异。
编辑: 看起来无法从 React
class.
中检测到 prod/dev 版本
两个想法:
- 我不确定应用程序是如何构建的,但
PropTypes
应该是一个很好的 ENV 标识符。
- 如果您的生产 React 应用程序被缩小,那么您可以简单地检测 React 代码是否被缩小。(这将是 hacky 但它应该工作,关注一些空格或线长,... )
我注意到你在下面的评论中说 minified !== production
如果你能做到这一点,那么这可能是你最好的选择。无论如何,您不需要缩小开发反应代码。
你的问题很明确,但是你没有说明你的构建系统,你用的是webpack
还是parcel
?你有没有Server Side Rendering
?您 运行 是 node
还是 pm2
构建的应用程序?或者你只是构建你的应用程序,然后将构建的捆绑文件放入你的页面中,该文件是由 PHP
或 C#
?
等其他技术制作的
其实上面的问题就可以决定你的答案了,但是你肯定使用了module bundler,所以我建议在你的项目中使用解析一个config
文件。
如果我是你的位置,毫无疑问,我使用webpack
,两个webpack配置文件,一个用于开发,一个用于生产模式。然后我创建了一个文件夹,其中包含两个文件 config.dev.js
和 config.prod.js
。在开发webpack中:
~~~
module.exports = {
~~~
resolve: {
extensions: ['.js', '.jsx'],
alias: {
~~~
Config: `${srcDir}/config/config.dev.js`,
// srcDir is a defined variable for source directory
}
},
~~~
在生产 webpack 中:
~~~
module.exports = {
~~~
resolve: {
extensions: ['.js', '.jsx'],
alias: {
~~~
Config: `${srcDir}/config/config.prod.js`,
// srcDir is a defined variable for source directory
}
},
~~~
现在您可以为您的构建类型放置每个 dev
和 prod
数据。例如在你的 config.dev.js
中可以写:
module.exports = {
buildType: "dev"
};
当然可以,在你的config.prod.js
中可以写:
module.exports = {
buildType: "prod"
};
绝对可以在 react
文件中使用以下代码访问配置数据:
import config from 'Config';
并且使用此解决方案,您可以在应用程序的实时执行中了解您的构建类型。
注意:有关更多信息,您可以查看我的 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,其中包含配置。
有些人谈到了使用生产总是会被缩小而开发不会被缩小的事实。这是一个使用它的具体解决方案:
<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>
我已经在从 v14 到 v16 的大约十几个版本的 React 上测试了这个。从 here 你可以看到这段代码自第一次编写以来没有被修改过,除了一年前的一次小修改(这不会影响这个答案,因为它的字符太少了,虽然我已经无论如何,在 11 个月前测试过版本并且存在相当大的差距)。
备注
Dev 为 200 个字符,Prod 为 70 个字符,因此 3:1 字符比率为 Dev:Prod 字符比率。我选择了 100,因为添加 90 个字符的代码会给产品添加 30 行,所以 100 是给定信息的最佳位置(技术上~105 左右)。这么简单的功能(5年才接触过一次20个字符编辑的功能),添加90个字符或删除100个字符是极不可能的,所以我认为这应该是稳定的。
为了提高稳定性,或者至少了解它是否损坏,您可以检查它是否在 70 和 200 之间的 25 个字符以内,如果不在则抛出错误。这应该会捕捉到任何大的变化(我几乎 100% 地确定该选项永远不会隐藏错误),但您可能会得到误报。你想要哪一个取决于你的用例。
编辑:
关于缩小,这是一个正则表达式,可以推断函数是否已缩小,因此您可以安全地使用它。如果 React.Children.map
不是一个函数(几乎肯定永远不会发生),它也会崩溃,您可以捕获或不捕获它,具体取决于您想要处理不太可能发生的错误事件的严格程度(或者只是忽略它,因为他们为什么要改变它)。函数签名仍然存在,即使它被缩小到 [native code]
,所以它是面向未来的 imo。不过为了简单起见,我会选择第一个。
const reactInfo = {
version: React.version,
development: !/function\s?\w?\(\w(,\w)*\)/.test(String((new React.Children.map()).constructor).split("{")[0])
};
有区别。在开发模式下,React 元素定义了 属性 _self
,而在生产模式下 属性 未定义。
因此,一个解决方案是使用如下代码测试此 属性:
function ReactIsInDevelomentMode(){
return '_self' in React.createElement('div');
}
React 开发构建的行为不同于生产构建,例如错误处理。
可以从环境中判断出使用哪一个,但仅限于模块化环境,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');
}
可能process.env
不适用的情况是React全局用作UMD模块,window.React
和window.ReactDOM
:
<script src="some-unknown-react-version.js"></script>
<script>
React // is it in production mode?
</script>
可能的用途是:
一个可以在模块化和全局环境中工作的组件(作为 UMD 发布)并在生产中以不同方式呈现
浏览器扩展或用户脚本,其中 build/production 模式是从
React
或ReactDOM
对象 检测到的
如何在不借助环境的情况下,在运行时准确检测 React development/production 构建?
我正在寻找适用于 React 15 和 React 16(如果可能)的可靠且干净的解决方案。
这不是类似问题的重复,因为现有答案通过 process.env
解决了问题。
React 提供开发版和生产版 react.js 链接:
发展:
<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>
生产:
<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>
并且要知道它是处于开发模式还是生产模式没有环境变量,你必须通过分配显式声明一些变量它的模式:(包括以下脚本和反应脚本)
<script>
var devMode = 'development';
</script>
并在必要时检查 devMode。
或者,您可以像这样检查它的模式:(您必须在脚本标签中添加 id)
var script_id = document.getElementById('script-attached-id');
console.log(script_id.getAttribute('src').includes('development'));
这样只需要更新源路径和检测模式即可
最后一个选项,我可以考虑读取文件本身并检测其模式,因为 React 在其评论中提到:
发展:
/** @license React v16.5.2
* react.development.js
生产:
/** @license React v16.5.2
* react.production.min.js
因此,读取文件后,只需在第二行检查它的模式。或者您可以测试 react.development.js
而无需逐行检查。
使用 umd 构建在客户端检测 dev/production 构建似乎是一个漫长的过程。
如果存在这样的要求,为什么不使用 create-react-app
构建您的应用程序?
我不会评判你的决定,所以这里有一些有用的东西。
react-dev-tools
facebook
提供的插件检测构建类型。
这里是上述插件的相关部分:
希望你能使它有用。
有一点 'hack' 可以检查已加载的 React 版本。
React 对象在全局变量中可用,并且 React 的生产版本与开发版本至少有一点不同:它通常被缩小。所以我们可以尝试检查我们是否正在使用缩小版本。
要检查,您可以将函数名称与某些 React 对象方法的 属性 名称进行比较,例如:
let func = 'Component'
if (React[func].name === func) {
// non-minified -> development build
}
这种方法不是检查生产和开发,而是检查缩小,而且由于生产构建通常是缩小的,所以它真的很有帮助。
您的部署设置如何?没有 "correct" 方法可以做您想做的事。我会关注 production/development 构建和创建我自己的辅助函数之间的差异。
编辑: 看起来无法从 React
class.
两个想法:
- 我不确定应用程序是如何构建的,但
PropTypes
应该是一个很好的 ENV 标识符。 - 如果您的生产 React 应用程序被缩小,那么您可以简单地检测 React 代码是否被缩小。(这将是 hacky 但它应该工作,关注一些空格或线长,... )
我注意到你在下面的评论中说 minified !== production
如果你能做到这一点,那么这可能是你最好的选择。无论如何,您不需要缩小开发反应代码。
你的问题很明确,但是你没有说明你的构建系统,你用的是webpack
还是parcel
?你有没有Server Side Rendering
?您 运行 是 node
还是 pm2
构建的应用程序?或者你只是构建你的应用程序,然后将构建的捆绑文件放入你的页面中,该文件是由 PHP
或 C#
?
其实上面的问题就可以决定你的答案了,但是你肯定使用了module bundler,所以我建议在你的项目中使用解析一个config
文件。
如果我是你的位置,毫无疑问,我使用webpack
,两个webpack配置文件,一个用于开发,一个用于生产模式。然后我创建了一个文件夹,其中包含两个文件 config.dev.js
和 config.prod.js
。在开发webpack中:
~~~
module.exports = {
~~~
resolve: {
extensions: ['.js', '.jsx'],
alias: {
~~~
Config: `${srcDir}/config/config.dev.js`,
// srcDir is a defined variable for source directory
}
},
~~~
在生产 webpack 中:
~~~
module.exports = {
~~~
resolve: {
extensions: ['.js', '.jsx'],
alias: {
~~~
Config: `${srcDir}/config/config.prod.js`,
// srcDir is a defined variable for source directory
}
},
~~~
现在您可以为您的构建类型放置每个 dev
和 prod
数据。例如在你的 config.dev.js
中可以写:
module.exports = {
buildType: "dev"
};
当然可以,在你的config.prod.js
中可以写:
module.exports = {
buildType: "prod"
};
绝对可以在 react
文件中使用以下代码访问配置数据:
import config from 'Config';
并且使用此解决方案,您可以在应用程序的实时执行中了解您的构建类型。
注意:有关更多信息,您可以查看我的 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,其中包含配置。
有些人谈到了使用生产总是会被缩小而开发不会被缩小的事实。这是一个使用它的具体解决方案:
<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>
我已经在从 v14 到 v16 的大约十几个版本的 React 上测试了这个。从 here 你可以看到这段代码自第一次编写以来没有被修改过,除了一年前的一次小修改(这不会影响这个答案,因为它的字符太少了,虽然我已经无论如何,在 11 个月前测试过版本并且存在相当大的差距)。
备注
Dev 为 200 个字符,Prod 为 70 个字符,因此 3:1 字符比率为 Dev:Prod 字符比率。我选择了 100,因为添加 90 个字符的代码会给产品添加 30 行,所以 100 是给定信息的最佳位置(技术上~105 左右)。这么简单的功能(5年才接触过一次20个字符编辑的功能),添加90个字符或删除100个字符是极不可能的,所以我认为这应该是稳定的。
为了提高稳定性,或者至少了解它是否损坏,您可以检查它是否在 70 和 200 之间的 25 个字符以内,如果不在则抛出错误。这应该会捕捉到任何大的变化(我几乎 100% 地确定该选项永远不会隐藏错误),但您可能会得到误报。你想要哪一个取决于你的用例。
编辑:
关于缩小,这是一个正则表达式,可以推断函数是否已缩小,因此您可以安全地使用它。如果 React.Children.map
不是一个函数(几乎肯定永远不会发生),它也会崩溃,您可以捕获或不捕获它,具体取决于您想要处理不太可能发生的错误事件的严格程度(或者只是忽略它,因为他们为什么要改变它)。函数签名仍然存在,即使它被缩小到 [native code]
,所以它是面向未来的 imo。不过为了简单起见,我会选择第一个。
const reactInfo = {
version: React.version,
development: !/function\s?\w?\(\w(,\w)*\)/.test(String((new React.Children.map()).constructor).split("{")[0])
};
有区别。在开发模式下,React 元素定义了 属性 _self
,而在生产模式下 属性 未定义。
因此,一个解决方案是使用如下代码测试此 属性:
function ReactIsInDevelomentMode(){
return '_self' in React.createElement('div');
}