该项目用Create React应用程序进行了引导。
在下面,您将找到有关如何执行常见任务的一些信息。
您可以在此处找到本指南的最新版本。
<title>
public
文件夹public
文件夹.env
中添加开发环境变量<meta>
标签npm start
未检测到更改npm test
在Macos Sierra上悬挂或撞车npm run build
出口太早npm run build
在Heroku上失败npm run build
无法缩小Create React应用程序分为两个软件包:
create-react-app
是您用于创建新项目的全局命令行实用程序。react-scripts
是生成项目的开发依赖性(包括该项目)。您几乎不需要更新create-react-app
本身:它将所有设置委托给react-scripts
。
当您运行create-react-app
时,它总是使用最新版本的react-scripts
创建项目,因此您将自动获得新创建的应用程序中的所有新功能和改进。
要将现有项目更新为新版本的react-scripts
,请打开ChangElog,查找您当前的版本(如果不确定,请在此文件package.json
中进行检查),并应用较新的迁移说明版本。
在大多数情况下,在package.json
和在此文件夹中运行npm install
(或yarn install
)中的react-scripts
版本应该足够了,但是最好咨询ChangElog以获取潜在的破坏更改。
我们致力于保持最小的破坏变化,以便您可以轻松地升级react-scripts
。
我们总是对您的反馈开放。
创建后,您的项目应该看起来像这样:
my-app/
README.md
node_modules/
package.json
public/
index.html
favicon.ico
src/
App.css
App.js
App.test.js
index.css
index.js
logo.svg
为了构建项目,这些文件必须具有确切的文件名存在:
public/index.html
是页面模板;src/index.js
是JavaScript入口点。您可以删除或重命名其他文件。
您可以在src
内部创建子目录。对于更快的重建,WebPack仅处理src
中的文件。
您需要将所有JS和CSS文件放在src
中,否则WebPack不会看到它们。
只能从public/index.html
中使用public
内部的文件。
阅读下面使用JavaScript和HTML资产的说明。
但是,您可以创建更多顶级目录。
它们将不包括在生产构建中,因此您可以将它们用于文档之类的东西。
在项目目录中,您可以运行:
npm start
在开发模式下运行该应用程序。
打开http:// localhost:3000在浏览器中查看。
如果您进行编辑,该页面将重新加载。
您还将在控制台中看到任何棉绒错误。
npm test
在交互式手表模式下启动测试跑者。
有关更多信息,请参见有关运行测试的部分。
npm run build
将应用程序构建到build
文件夹中。
它正确地捆绑了在生产模式下进行反应,并优化构建以获得最佳性能。
构建被缩小,文件名包括哈希。
您的应用已准备好部署!
有关更多信息,请参见有关部署的部分。
npm run eject
注意:这是一个单向操作。 eject
后,您将无法返回!
如果您对构建工具和配置选择不满意,则可以随时eject
。此命令将从您的项目中删除单个构建依赖关系。
取而代之的是,它将将所有配置文件和传递依赖性(webpack,babel,eslint等)复制到您的项目中,以便您完全控制它们。除eject
以外的所有命令仍然可以工作,但是它们将指向复制的脚本,以便您可以调整它们。在这一点上,您是一个人。
您不必使用eject
。策划的功能集适用于中小型部署,您不应该感到有义务使用此功能。但是,我们知道,如果您在准备好后,您无法自定义该工具,则该工具将没有用。
默认情况下,生成的项目支持所有现代浏览器。
对Internet Explorer 9、10和11的支持需要多填充。
该项目支持最新JavaScript标准的超集。
除了ES6语法功能外,它还支持:
了解有关不同建议阶段的更多信息。
虽然我们建议使用一些谨慎使用实验建议,但Facebook在产品代码中大量使用这些功能,因此我们打算在将来的任何建议中提供CODEMODS。
请注意,默认情况下,该项目不包括多填充。
如果您使用需要运行时支持的任何其他ES6+功能(例如Array.from()
或Symbol
),请确保您手动包含适当的polyfills,或者您针对的浏览器已经支持它们。
要配置您喜欢的文本编辑器中的语法突出显示,请转到相关的Babel文档页面并按照说明进行操作。涵盖了一些最受欢迎的编辑。
注意:此功能可提供
[email protected]
及更高版本。
它还仅适用于NPM 3或更高。
一些编辑器(包括崇高的文本,原子和Visual Studio代码)为ESLINT提供插件。
它们不是覆盖所必需的。您应该在终端以及浏览器控制台中看到Linter输出。但是,如果您希望棉绒结果出现在编辑器中,那么您可以执行一些额外的步骤。
您需要首先为编辑器安装ESLINT插件。然后,将一个名为.eslintrc
的文件添加到项目root:
{
"extends" : "react-app"
}
现在,您的编辑应报告伸缩警告。
请注意,即使您进一步编辑.eslintrc
文件,这些更改也只会影响编辑器集成。它们不会影响终端和浏览器棉绒输出。这是因为创建React应用程序有意提供了一组最小的规则,这些规则会发现常见错误。
如果您想为项目执行编码样式,请考虑使用更漂亮而不是ESLINT样式规则。
目前,此功能仅由Visual Studio Code和WebStorm支持。
Visual Studio代码和WebStorm支持使用Create React应用程序开箱即用。这使您可以作为开发人员在不离开编辑器的情况下编写和调试您的React代码,最重要的是,它使您能够具有连续的开发工作流程,因为您不必在工具之间切换,因此上下文切换很小。
您需要安装最新版本的VS代码和VS代码Chrome调试器扩展名。
然后将下面的块添加到您的launch.json
文件中,然后将其放入应用程序根目录中的.vscode
文件夹中。
{
"version" : " 0.2.0 " ,
"configurations" : [
{
"name" : " Chrome " ,
"type" : " chrome " ,
"request" : " launch " ,
"url" : " http://localhost:3000 " ,
"webRoot" : " ${workspaceRoot}/src " ,
"sourceMapPathOverrides" : {
"webpack:///src/*" : " ${webRoot}/* "
}
}
]
}
注意:如果您通过主机或端口环境变量进行了调整,则URL可能会有所不同。
通过运行npm start
来启动应用程序,并通过按F5
或单击绿色调试图标开始在VS代码中进行调试。现在,您可以编写代码,设置断点,更改代码,并从编辑器中调试您的新修改的代码。
vs代码调试有问题吗?请参阅他们的故障排除指南。
您需要安装WebStorm和Jetbrains IDE支持Chrome扩展。
在WebStorm菜单中Run
选择Edit Configurations...
然后单击+
,然后选择JavaScript Debug
。粘贴http://localhost:3000
进入URL字段并保存配置。
注意:如果您通过主机或端口环境变量进行了调整,则URL可能会有所不同。
通过运行npm start
开始您的应用程序,然后在Windows和Linux上按MACOS或F9
按^D
,或单击Green Debug图标以开始在WebStorm中调试。
您可以在Intellij Ideas Ultimate,PhpStorm,Pycharm Pro和Rubymine中调试应用程序的方式。
Prettier是一种自以为是的代码格式化器,并支持JavaScript,CSS和JSON。借助更漂亮,您可以将您自动编写的代码格式化,以确保项目中的代码样式。有关更多信息,请参见Prettier的GitHub页面,并查看此页面以查看它的作用。
每当我们在git中提交代码时,我们都需要安装以下依赖项:
npm install --save husky lint-staged prettier
或者,您可以使用yarn
:
yarn add husky lint-staged prettier
husky
使使用githooks变得容易,就好像它们是NPM脚本一样。lint-staged
允许我们在git中的分阶段文件上运行脚本。请参阅此博客文章有关绒毛片段的文章,以了解有关它的更多信息。prettier
是我们将在提交之前运行的JavaScript格式化器。现在,我们可以通过在项目root中的package.json
中添加几行来确保每个文件正确格式化。
将以下字段添加到package.json
部分:
+ "husky": {
+ "hooks": {
+ "pre-commit": "lint-staged"
+ }
+ }
接下来,我们将“绒毛级”字段添加到package.json
。
"dependencies": {
// ...
},
+ "lint-staged": {
+ "src/**/*.{js,jsx,json,css}": [
+ "prettier --single-quote --write",
+ "git add"
+ ]
+ },
"scripts": {
现在,每当您进行提交时,Prettier都会自动格式化更改的文件。您也可以运行./node_modules/.bin/prettier --single-quote --write "src/**/*.{js,jsx}"
以首次格式化整个项目。
接下来,您可能需要将更漂亮的编辑整合到您喜欢的编辑中。在Prettier GitHub页面上阅读有关编辑器集成的部分。
<title>
您可以在生成项目的public
文件夹中找到源HTML文件。您可以在其中编辑<title>
标签,以将标题从“ React App”更改为其他任何内容。
请注意,通常您不会经常在public
文件夹中编辑文件。例如,添加样式表是在不触摸HTML的情况下完成的。
如果您需要根据内容动态更新页面标题,则可以使用浏览器document.title
。标题API。对于更复杂的方案,当您想从React组件中更改标题时,可以使用第三方库React Helmet。
如果您在生产中使用自定义服务器为应用程序使用,并希望在将标题发送到浏览器之前对其进行修改,则可以在本节中遵循建议。另外,您可以将每个页面预先构建为静态HTML文件,然后加载JavaScript捆绑包,此处介绍。
生成的项目包括React和Reactdom作为依赖关系。它还包括创建React应用程序作为开发依赖性的一组脚本。您可以使用npm
安装其他依赖项(例如React Router):
npm install --save react-router-dom
或者,您可以使用yarn
:
yarn add react-router-dom
这适用于任何库,而不仅仅是react-router-dom
。
由于WebPack,该项目设置支持ES6模块。
虽然您仍然可以使用require()
和module.exports
,但我们鼓励您使用import
和export
。
例如:
Button.js
import React , { Component } from 'react' ;
class Button extends Component {
render ( ) {
// ...
}
}
export default Button ; // Don’t forget to use export default!
DangerButton.js
import React , { Component } from 'react' ;
import Button from './Button' ; // Import a component from another file
class DangerButton extends Component {
render ( ) {
return < Button color = "red" / > ;
}
}
export default DangerButton ;
请注意默认和命名导出之间的区别。这是错误的常见来源。
我们建议您在模块仅导出单个东西(例如组件)时坚持使用默认的导入和导出。这就是您使用export default Button
和import Button from './Button'
时得到的。
命名导出对于导出多个功能的实用程序模块很有用。一个模块最多可能具有一个默认导出,并且随心所欲。
了解有关ES6模块的更多信息:
代码拆分,代替用户可以使用它,而不是在用户使用之前下载整个应用程序,而是可以将代码拆分为小块,然后可以按需加载代码。
该项目设置支持通过Dynamic import()
分裂代码。它的建议在阶段3中。 import()
函数式表单将模块名称作为参数,并返回一个始终解决模块名称空间对象的Promise
。
这是一个示例:
moduleA.js
const moduleA = 'Hello' ;
export { moduleA } ;
App.js
import React , { Component } from 'react' ;
class App extends Component {
handleClick = ( ) => {
import ( './moduleA' )
. then ( ( { moduleA } ) => {
// Use moduleA
} )
. catch ( err => {
// Handle failure
} ) ;
} ;
render ( ) {
return (
< div >
< button onClick = { this . handleClick } > Load < / button >
< / div >
) ;
}
}
export default App ;
这将使moduleA.js
及其所有独特的依赖项作为单独的块,仅在用户单击“加载”按钮之后加载。
如果您愿意,也可以将其与async
/ await
语法一起使用。
如果您使用的是React路由器,请查看有关如何使用代码分配的教程。您可以在此处找到同伴GitHub存储库。
还要查看React文档中的代码分裂部分。
该项目设置使用WebPack来处理所有资产。 WebPack提供了一种自定义方法,可以“扩展”超出JavaScript的import
概念。为了表明JavaScript文件取决于CSS文件,您需要从JavaScript文件导入CSS :
Button.css
. Button {
padding : 20 px ;
}
Button.js
import React , { Component } from 'react' ;
import './Button.css' ; // Tell Webpack that Button.js uses these styles
class Button extends Component {
render ( ) {
// You can use them as regular CSS styles
return < div className = "Button" / > ;
}
}
React并不需要这一点,但是许多人发现此功能方便。您可以在此处阅读有关此方法的好处。但是,您应该意识到,这会使您的代码与WebPack相比,您的代码较低于其他构建工具和环境。
在开发中,以这种方式表达依赖关系可以使您的样式在编辑时即可随时重新加载。在生产中,所有CSS文件都将在构建输出中加入单个缩小的.css
文件。
如果您担心使用特定于WebPack的语义,则可以将所有CSS直接放入src/index.css
中。它仍将从src/index.js
导入,但是如果您以后迁移到其他构建工具,则可以随时删除该导入。
注意:此功能可提供
[email protected]
及更高版本。
该项目使用[name].module.css
文件命名约定以及常规样式表支持CSS模块。 CSS模块允许通过自动创建格式[filename]_[classname]__[hash]
的唯一className来范围。
提示:如果您想用SASS预处理样式表,请确保遵循安装说明,然后按以下方式更改样式表文件扩展名:
[name].module.scss
或[name].module.sass
。
CSS模块可让您在不同文件中使用相同的CSS类名称,而不必担心命名冲突。在此处了解有关CSS模块的更多信息。
Button.module.css
. error {
background-color : red;
}
another-stylesheet.css
. error {
color : red;
}
Button.js
import React , { Component } from 'react' ;
import styles from './Button.module.css' ; // Import css modules stylesheet as styles
import './another-stylesheet.css' ; // Import regular stylesheet
class Button extends Component {
render ( ) {
// reference as a js object
return < button className = { styles . error } > Error Button < / button > ;
}
}
没有其他冲突.error
<!-- This button has red background but not red text -->
< button class =" Button_error_ax7yz " > </ div >
这是一个可选功能。常规<link>
样式表和CSS文件得到了充分支持。 CSS模块以.module.css
扩展为结尾的文件打开。
注意:此功能可提供
[email protected]
及更高版本。
通常,我们建议您不要在不同组件上重复使用相同的CSS课程。例如,我们建议使用自己的.Button
样式创建一个.Button
css类,而是在<AcceptButton>
and <RejectButton>
组件中使用<Button>
components, <AcceptButton>
and <ackeptbutton> and <RejectButton>
都可以呈现(但不要继承)。
遵循此规则通常会使CSS预处理器的用处降低,因为Mixins和Nesting之类的功能由组件组成代替。但是,如果您发现它很有价值,则可以集成CSS预处理器。
要使用SASS,请首先安装node-sass
:
$ npm install node-sass --save
$ # or
$ yarn add node-sass
现在,您可以将src/App.css
重命名为src/App.scss
,然后更新src/App.js
以导入src/App.scss
。如果用Extension .scss
或.sass
导入此文件和任何其他文件,将自动编译。
要在SASS文件之间共享变量,您可以使用SASS导入。例如, src/App.scss
和其他组件样式文件可以包括@import "./shared.scss";
具有可变定义。
这将使您像
@import ' styles/_colors.scss ' ; // assuming a styles directory under src/
@import ' ~nprogress/nprogress ' ; // importing a css file from the nprogress node module
提示:您也可以选择与CSS模块一起使用此功能!
注意:您必须从
node_modules
导入~
,如上所述。
该项目设置可将您的CSS缩小,并通过自动改装器自动添加供应商前缀,因此您无需担心它。
支持新的CSS功能,例如all
属性, break
属性,自定义属性和媒体查询范围自动填充,以增加对较旧浏览器的支持。
您可以通过调整package.json
中的browserslist
键来自定义目标支持浏览器。
例如,这个:
. App {
display : flex;
flex-direction : row;
align-items : center;
}
变成了:
. App {
display : -webkit-box;
display : -ms-flexbox;
display : flex;
-webkit-box-orient : horizontal;
-webkit-box-direction : normal;
-ms-flex-direction : row;
flex-direction : row;
-webkit-box-align : center;
-ms-flex-align : center;
align-items : center;
}
如果由于某种原因需要禁用自动修复,请遵循本节。
默认情况下禁用CSS网格布局前缀,但不会剥离手动前缀。如果您想选择进入CSS网格前缀,请首先熟悉其限制。
要启用CSS网格前缀,请添加/* autoprefixer grid: on */
到CSS文件的顶部。
使用WebPack,使用图像和字体之类的静态资产与CSS相似。
您可以在JavaScript模块中直接import
文件。这告诉WebPack将该文件包含在捆绑包中。与CSS导入不同,导入文件为您提供字符串值。此值是您可以在代码中引用的最终路径,例如,作为图像的src
属性或链接到PDF的href
。
为了减少服务器的请求数量,导入少于10,000个字节的图像返回数据URI而不是路径。这适用于以下文件扩展:BMP,GIF,JPG,JPEG和PNG。由于#1153,SVG文件被排除在外。
这是一个示例:
import React from 'react' ;
import logo from './logo.png' ; // Tell Webpack this JS file uses this image
console . log ( logo ) ; // /logo.84287d09.png
function Header ( ) {
// Import result is the URL of your image
return < img src = { logo } alt = "Logo" / > ;
}
export default Header ;
这样可以确保构建项目时,WebPack将正确将图像移至构建文件夹中,并为我们提供正确的路径。
这也在CSS中起作用:
. Logo {
background-image : url (. / logo.png);
}
WebPack在CSS中找到所有相对模块的参考(它们以./
开头),并用编译捆绑包的最终路径代替它们。如果您制作错别字或意外删除重要文件,则会看到汇编错误,就像导入不存在的JavaScript模块时一样。编译捆绑包中的最终文件名是由WebPack从内容哈希生成的。如果将来文件内容更改,则WebPack将在生产中给它一个不同的名称,因此您不必担心资产的长期缓存。
请注意,这也是WebPack的自定义功能。
反应不是必需的,但许多人喜欢它(React Antial使用类似的图像机制)。
下一部分将描述一种处理静态资产的替代方法。
注意:此功能可提供
[email protected]
及更高版本。
上面的部分描述了添加SVG文件的一种方法。您也可以直接导入SVG作为React组件。您可以使用两种方法中的任何一种。在您的代码中,它看起来像这样:
import { ReactComponent as Logo } from './logo.svg' ;
const App = ( ) => (
< div >
{ /* Logo is an actual React component */ }
< Logo / >
< / div >
) ;
如果您不想将SVG加载为单独的文件,这很方便。不要忘记导入中的卷曲牙套! ReactComponent
导入名称很特别,并告诉创建React应用程序,您需要一个呈现SVG而不是其文件名的React组件。
public
文件夹注意:此功能可提供
[email protected]
及更高版本。
public
文件夹包含HTML文件,因此您可以对其进行调整以设置页面标题。带有编译代码的<script>
标签将在构建过程中自动添加到其。
您还可以将其他资产添加到public
文件夹中。
请注意,我们通常鼓励您import
JavaScript文件中的资产。例如,请参见有关添加样式表并添加图像和字体的部分。该机制提供了许多好处:
但是,有一个逃生舱口可以用来在模块系统外添加资产。
如果将文件放入public
文件夹中,则不会由WebPack处理。取而代之的是,它将被复制到构建文件夹中。要在public
文件夹中参考资产,您需要使用一个称为PUBLIC_URL
的特殊变量。
内部index.html
,您可以这样使用:
< link rel =" shortcut icon " href =" %PUBLIC_URL%/favicon.ico " >
%PUBLIC_URL%
前缀只能访问public
文件夹中的文件。如果您需要使用src
或node_modules
中的文件,则必须在此处复制它,以明确指定您的意图使该文件成为构建的一部分。
当您运行npm run build
时,创建React App将用正确的绝对路径替换%PUBLIC_URL%
因此即使您使用客户端路由或在非根系URL中使用客户端路由,您的项目也可以使用。
在JavaScript代码中,您可以使用process.env.PUBLIC_URL
进行类似目的:
render ( ) {
// Note: this is an escape hatch and should be used sparingly!
// Normally we recommend using `import` for getting asset URLs
// as described in “Adding Images and Fonts” above this section.
return < img src = { process . env . PUBLIC_URL + '/img/logo.png' } / > ;
}
请记住这种方法的弊端:
public
文件夹中的任何文件都没有得到后处理或缩小。public
文件夹通常,我们建议从JavaScript导入样式表,图像和字体。 public
文件夹可作为许多不常见情况的解决方法:
manifest.webmanifest
。pace.js
<script>
标签中。请注意,如果添加声明全局变量的<script>
,您还需要阅读有关使用它们的下一部分。
当您在HTML文件中包含一个定义全局变量并尝试在代码中使用这些变量之一的脚本时,Linter会抱怨,因为它看不到变量的定义。
您可以通过从window
对象明确读取全局变量来避免这种情况,例如:
const $ = window . $ ;
这很明显您是故意使用全局变量的,而不是由于错别字。
另外,您可以强迫Linter在其后通过添加// eslint-disable-line
来忽略任何线路。
您不必将ReactStrap与React一起使用,但它是将引导程序与React应用集成的流行库。如果需要,可以按照以下步骤将其与Create React应用程序集成:
从NPM安装ReactStrap和Bootstrap。 ReactStrap不包括Bootstrap CSS,因此也需要安装:
npm install --save reactstrap bootstrap@4
或者,您可以使用yarn
:
yarn add bootstrap@4 reactstrap
在您的src/index.js
文件的开头中导入Bootstrap CSS和Bootstrap主题CSS:
import 'bootstrap/dist/css/bootstrap.css' ;
// Put any other imports below so that CSS from your
// components takes precedence over default styles.
导入src/App.js
文件或您的自定义组件文件中所需的ReactStrap组件:
import { Button } from 'reactstrap' ;
现在,您准备在渲染方法中定义的组件层次结构中使用导入的ReactStrap组件。这是使用ReactStrap的示例App.js
重做。
注意:此功能可提供
[email protected]
及更高版本。
有时,您可能需要调整自举的视觉样式(或等效软件包)。
从[email protected]
开始,您可以导入.scss
文件。这使得可以将软件包的内置SASS变量用于全局样式首选项。
要自定义Bootstrap,请创建一个名为src/custom.scss
(或类似)的文件,然后导入Bootstrap源样式表。在导入文件之前添加任何覆盖。您可以为可用变量的名称引用Bootstrap的文档。
// Override default variables before the import
$body-bg : #000 ;
// Import Bootstrap and its default variables
@import ' ~bootstrap/scss/bootstrap.scss ' ;
注意:您必须从
node_modules
导入~
,如上所述。
最后,在src/index.js
文件的开头中导入新创建的.scss
文件,而不是默认的bootstrap .css
:
import './custom.scss' ;
Flow是一种静态类型的检查器,可帮助您使用更少的错误编写代码。如果您是此概念的新手,请查看此介绍,以使用JavaScript中的静态类型。
开箱即用的Flow Work的最新版本使用创建React App Projects。
要添加到创建React App项目的流程,请按照以下步骤:
npm install --save flow-bin
(或yarn add flow-bin
)。"flow": "flow"
添加到您的package.json
的scripts
部分。npm run flow init
(或yarn flow init
),以在根目录中创建.flowconfig
文件。// @flow
到您要输入检查的任何文件(例如, src/App.js
)。现在,您可以运行npm run flow
(或yarn flow
)来检查文件是否类型错误。您可以选择使用IDE之类的核素来获得更好的集成体验。将来,我们计划将其集成到创建React应用程序中。
要了解有关流的更多信息,请查看其文档。
继电器是构建由GraphQl供电的数据驱动的反应应用程序的框架。当前的接力赛候选人使用Babel Macros开箱即用的Create React App Projects使用。只需按照继电器文档中布置的项目设置您的项目,然后确保您拥有提供宏的Babel插件的版本。
要添加它,请运行:
npm install --save --dev babel-plugin-relay@dev
或者,您可以使用yarn
:
yarn upgrade babel-plugin-relay@dev
然后,无论何处使用graphql
模板标签,都会导入宏:
import graphql from 'babel-plugin-relay/macro' ;
// instead of:
// import { graphql } from "babel-plugin-relay"
graphql `
query UserQuery {
viewer {
id
}
}
` ;
要了解有关继电器的更多信息,请查看其文档。
Create React应用程序没有规定特定的路由解决方案,但React路由器是最受欢迎的路由器。
要添加它,请运行:
npm install --save react-router-dom
或者,您可以使用yarn
:
yarn add react-router-dom
要尝试一下,请在src/App.js
中删除所有代码,然后用其网站上的任何示例替换它。基本示例是一个好地方。
请注意,在部署应用程序之前,您可能需要配置生产服务器以支持客户端路由。
注意:此功能可提供
[email protected]
及更高版本。
您的项目可以消耗在您的环境中声明的变量,就好像它们是在JS文件中本地声明的一样。默认情况下,您将为您定义NODE_ENV
,以及以REACT_APP_
开头的任何其他环境变量。
环境变量在构建时间内嵌入。由于Create React应用程序会产生静态HTML/CSS/JS捆绑包,因此无法在运行时读取它们。要在运行时读取它们,您需要将HTML加载到服务器上的内存中,并在运行时替换占位符,就像此处所述。另外,您可以随时更改服务器上的应用程序。
注意:您必须创建以
REACT_APP_
开头的自定义环境变量。除了NODE_ENV
之外,所有其他变量都将被忽略,以避免在计算机上意外暴露出可能具有相同名称的私钥。更改任何环境变量将需要您在运行开发服务器时重新启动。
这些环境变量将在process.env
上为您定义。例如,具有名为REACT_APP_SECRET_CODE
的环境变量将在您的js中以process.env.REACT_APP_SECRET_CODE
形式公开。
还有一个特殊的内置环境变量,称为NODE_ENV
。您可以从process.env.NODE_ENV
读取它。当您运行npm start
时,它始终等于'development'
,当您运行npm test
时,它始终等于'test'
,当您运行npm run build
以制造生产捆绑包时,它始终等于'production'
。您不能手动覆盖NODE_ENV
。这样可以防止开发人员意外将缓慢的开发构建部署到生产中。
这些环境变量可用于根据部署项目的位置或消耗在版本控制之外的敏感数据的何处来显示信息很有用。
首先,您需要定义环境变量。例如,假设您想消耗<form>
内部环境中定义的秘密:
render ( ) {
return (
< div >
< small > You are running this application in < b > { process . env . NODE_ENV } < / b > mode. < / small >
< form >
< input type = "hidden" defaultValue = { process . env . REACT_APP_SECRET_CODE } / >
< / form >
< / div >
) ;
}
在构建过程中, process.env.REACT_APP_SECRET_CODE
将被REACT_APP_SECRET_CODE
环境变量的当前值替换。请记住, NODE_ENV
变量将自动为您设置。
当您将应用程序加载到浏览器中并检查<input>
时,您会看到其值设置为abcdef
,并且BOLD文本将显示使用npm start
时提供的环境:
< div >
< small > You are running this application in < b > development </ b > mode. </ small >
< form >
< input type =" hidden " value =" abcdef " />
</ form >
</ div >
上面的形式正在寻找一个从环境中寻找称为REACT_APP_SECRET_CODE
的变量。为了消耗此值,我们需要在环境中定义它。这可以使用两种方法完成:在您的外壳或.env
文件中。在接下来的几节中描述了这两种方式。
访问NODE_ENV
也可用于有条件地执行操作:
if ( process . env . NODE_ENV !== 'production' ) {
analytics . disable ( ) ;
}
当您使用npm run build
编译应用程序时,缩小步骤将剥离此条件,并且所得的捆绑包将较小。
注意:此功能可提供
[email protected]
及更高版本。
您还可以在public/index.html
中以REACT_APP_
开头的环境变量访问环境变量。例如:
< title > %REACT_APP_WEBSITE_NAME% </ title >
请注意,上面的警告适用:
NODE_ENV
和PUBLIC_URL
)之外,变量名称必须以REACT_APP_
开头才能工作。定义环境变量在OS之间可能会有所不同。同样重要的是要知道这种方式在壳会议的生活中是暂时的。
set " REACT_APP_SECRET_CODE = abcdef " && npm start
(注意:需要围绕变量分配的引号才能避免落后的空格。)
( $ env: REACT_APP_SECRET_CODE = " abcdef " ) -and (npm start)
REACT_APP_SECRET_CODE=abcdef npm start
.env
中添加开发环境变量注意:此功能可提供
[email protected]
及更高版本。
要定义永久环境变量,请在项目根部创建一个名为.env
的文件:
REACT_APP_SECRET_CODE=abcdef
注意:您必须创建以
REACT_APP_
开头的自定义环境变量。除了NODE_ENV
之外,所有其他变量都将被忽略,以避免在计算机上意外暴露出可能具有相同名称的私钥。更改任何环境变量将需要您在运行开发服务器时重新启动。
.env
文件应将其检查到源控件中(排除.env*.local
)。
.env
文件?注意:此功能可提供
[email protected]
及更高版本。
.env
:默认。.env.local
:本地覆盖。此文件已为除测试外的所有环境加载。.env.development
.env.test
.env.production
.env.development.local
.env.test.local
.env.production.local
左侧的文件比右边的文件更优先:
npm start
: .env.development.local
, .env.development
, .env.local
, .env
npm run build
: .env.production.local
, .env.production
, .env.local
, .env
npm test
: .env.test.local
, .env.test
, .env
(note .env.local
缺少)如果机器未明确设置它们,这些变量将充当默认值。
有关更多详细信息,请参考Dotenv文档。
注意:如果您定义了开发环境变量,则您的CI和/或托管平台很可能也需要定义。咨询他们的文档如何执行此操作。例如,请参阅Travis CI或Heroku的文档。
.env
中扩展环境变量注意:此功能可提供
[email protected]
及更高版本。
扩展机器上的变量已在.env
文件中使用(使用dotenv-expand)。
例如,获取环境变量npm_package_version
:
REACT_APP_VERSION=$npm_package_version
# also works:
# REACT_APP_VERSION=${npm_package_version}
或将变量本地扩展到当前.env
文件:
DOMAIN=www.example.com
REACT_APP_FOO=$DOMAIN/foo
REACT_APP_BAR=$DOMAIN/bar
一些受欢迎的图书馆在其文档中使用装饰商。
Create React App intentionally doesn't support decorator syntax at the moment because:
However in many cases you can rewrite decorator-based code without decorators just as fine.
Please refer to these two threads for reference:
Create React App will add decorator support when the specification advances to a stable stage.
React doesn't prescribe a specific approach to data fetching, but people commonly use either a library like axios or the fetch()
API provided by the browser.
The global fetch
function allows you to easily make AJAX requests. It takes in a URL as an input and returns a Promise
that resolves to a Response
object. You can find more information about fetch
here.
A Promise represents the eventual result of an asynchronous operation, you can find more information about Promises here and here. Both axios and fetch()
use Promises under the hood. You can also use the async / await
syntax to reduce the callback nesting.
Make sure the fetch()
API and Promises are available in your target audience's browsers. For example, support in Internet Explorer requires a polyfill.
You can learn more about making AJAX requests from React components in the FAQ entry on the React website.
These tutorials will help you to integrate your app with an API backend running on another port, using fetch()
to access it.
Check out this tutorial. You can find the companion GitHub repository here.
Check out this tutorial. You can find the companion GitHub repository here.
API Platform is a framework designed to build API-driven projects. It allows to create hypermedia and GraphQL APIs in minutes. It is shipped with an official Progressive Web App generator as well as a dynamic administration interface, both built for Create React App. Check out this tutorial.
Note: this feature is available with
[email protected]
and higher.
People often serve the front-end React app from the same host and port as their backend implementation.
For example, a production setup might look like this after the app is deployed:
/ - static server returns index.html with React app
/todos - static server returns index.html with React app
/api/todos - server handles any /api/* requests using the backend implementation
Such setup is not required. However, if you do have a setup like this, it is convenient to write requests like fetch('/api/todos')
without worrying about redirecting them to another host or port during development.
To tell the development server to proxy any unknown requests to your API server in development, add a proxy
field to your package.json
, for example:
"proxy" : "http://localhost:4000" ,
This way, when you fetch('/api/todos')
in development, the development server will recognize that it's not a static asset, and will proxy your request to http://localhost:4000/api/todos
as a fallback. The development server will only attempt to send requests without text/html
in its Accept
header to the proxy.
Conveniently, this avoids CORS issues and error messages like this in development:
Fetch API cannot load http://localhost:4000/api/todos. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Keep in mind that proxy
only has effect in development (with npm start
), and it is up to you to ensure that URLs like /api/todos
point to the right thing in production. You don't have to use the /api
prefix. Any unrecognized request without a text/html
accept header will be redirected to the specified proxy
.
The proxy
option supports HTTP, HTTPS and WebSocket connections.
If the proxy
option is not flexible enough for you, alternatively you can:
When you enable the proxy
option, you opt into a more strict set of host checks. This is necessary because leaving the backend open to remote hosts makes your computer vulnerable to DNS rebinding attacks. The issue is explained in this article and this issue.
This shouldn't affect you when developing on localhost
, but if you develop remotely like described here, you will see this error in the browser after enabling the proxy
option:
Invalid Host header
To work around it, you can specify your public development host in a file called .env.development
in the root of your project:
HOST=mypublicdevhost.com
If you restart the development server now and load the app from the specified host, it should work.
If you are still having issues or if you're using a more exotic environment like a cloud editor, you can bypass the host check completely by adding a line to .env.development.local
. Note that this is dangerous and exposes your machine to remote code execution from malicious websites:
# NOTE: THIS IS DANGEROUS!
# It exposes your machine to attacks from the websites you visit.
DANGEROUSLY_DISABLE_HOST_CHECK=true
We don't recommend this approach.
Note: this feature is available with
[email protected]
and higher.
If the proxy
option is not flexible enough for you, you can get direct access to the Express app instance and hook up your own proxy middleware.
You can use this feature in conjunction with the proxy
property in package.json
, but it is recommended you consolidate all of your logic into src/setupProxy.js
.
First, install http-proxy-middleware
using npm or Yarn:
$ npm install http-proxy-middleware --save
$ # or
$ yarn add http-proxy-middleware
Next, create src/setupProxy.js
and place the following contents in it:
const proxy = require ( 'http-proxy-middleware' ) ;
module . exports = function ( app ) {
// ...
} ;
You can now register proxies as you wish! Here's an example using the above http-proxy-middleware
:
const proxy = require ( 'http-proxy-middleware' ) ;
module . exports = function ( app ) {
app . use ( proxy ( '/api' , { target : 'http://localhost:5000/' } ) ) ;
} ;
Note: You do not need to import this file anywhere. It is automatically registered when you start the development server.
Note: This file only supports Node's JavaScript syntax. Be sure to only use supported language features (ie no support for Flow, ES Modules, etc).
Note: Passing the path to the proxy function allows you to use globbing and/or pattern matching on the path, which is more flexible than the express route matching.
Note: this feature is available with
[email protected]
and higher.
You may require the dev server to serve pages over HTTPS. One particular case where this could be useful is when using the "proxy" feature to proxy requests to an API server when that API server is itself serving HTTPS.
To do this, set the HTTPS
environment variable to true
, then start the dev server as usual with npm start
:
set HTTPS = true && npm start
(Note: the lack of whitespace is intentional.)
( $ env: HTTPS = $true ) -and (npm start)
HTTPS=true npm start
Note that the server will use a self-signed certificate, so your web browser will almost definitely display a warning upon accessing the page.
<meta>
Tags on the Server Since Create React App doesn't support server rendering, you might be wondering how to make <meta>
tags dynamic and reflect the current URL. To solve this, we recommend to add placeholders into the HTML, like this:
<!doctype html >
< html lang =" en " >
< head >
< meta property =" og:title " content =" __OG_TITLE__ " >
< meta property =" og:description " content =" __OG_DESCRIPTION__ " >
Then, on the server, regardless of the backend you use, you can read index.html
into memory and replace __OG_TITLE__
, __OG_DESCRIPTION__
, and any other placeholders with values depending on the current URL. Just make sure to sanitize and escape the interpolated values so that they are safe to embed into HTML!
If you use a Node server, you can even share the route matching logic between the client and the server. However duplicating it also works fine in simple cases.
If you're hosting your build
with a static hosting provider you can use react-snapshot or react-snap to generate HTML pages for each route, or relative link, in your application. These pages will then seamlessly become active, or “hydrated”, when the JavaScript bundle has loaded.
There are also opportunities to use this outside of static hosting, to take the pressure off the server when generating and caching routes.
The primary benefit of pre-rendering is that you get the core content of each page with the HTML payload—regardless of whether or not your JavaScript bundle successfully downloads. It also increases the likelihood that each route of your application will be picked up by search engines.
You can read more about zero-configuration pre-rendering (also called snapshotting) here.
Similarly to the previous section, you can leave some placeholders in the HTML that inject global variables, for example:
< ! doctype html >
< html lang = "en" >
< head >
< script >
window.SERVER_DATA = __SERVER_DATA__;
< / script >
Then, on the server, you can replace __SERVER_DATA__
with a JSON of real data right before sending the response. The client code can then read window.SERVER_DATA
to use it. Make sure to sanitize the JSON before sending it to the client as it makes your app vulnerable to XSS attacks.
Note: this feature is available with
[email protected]
and higher.
Read the migration guide to learn how to enable it in older projects!
Create React App uses Jest as its test runner. To prepare for this integration, we did a major revamp of Jest so if you heard bad things about it years ago, give it another try.
Jest is a Node-based runner. This means that the tests always run in a Node environment and not in a real browser. This lets us enable fast iteration speed and prevent flakiness.
While Jest provides browser globals such as window
thanks to jsdom, they are only approximations of the real browser behavior. Jest is intended to be used for unit tests of your logic and your components rather than the DOM quirks.
We recommend that you use a separate tool for browser end-to-end tests if you need them. They are beyond the scope of Create React App.
Jest will look for test files with any of the following popular naming conventions:
.js
suffix in __tests__
folders..test.js
suffix..spec.js
suffix. The .test.js
/ .spec.js
files (or the __tests__
folders) can be located at any depth under the src
top level folder.
We recommend to put the test files (or __tests__
folders) next to the code they are testing so that relative imports appear shorter. For example, if App.test.js
and App.js
are in the same folder, the test just needs to import App from './App'
instead of a long relative path. Colocation also helps find tests more quickly in larger projects.
When you run npm test
, Jest will launch in the watch mode. Every time you save a file, it will re-run the tests, just like npm start
recompiles the code.
The watcher includes an interactive command-line interface with the ability to run all tests, or focus on a search pattern. It is designed this way so that you can keep it open and enjoy fast re-runs. You can learn the commands from the “Watch Usage” note that the watcher prints after every run:
By default, when you run npm test
, Jest will only run the tests related to files changed since the last commit. This is an optimization designed to make your tests run fast regardless of how many tests you have. However it assumes that you don't often commit the code that doesn't pass the tests.
Jest will always explicitly mention that it only ran tests related to the files changed since the last commit. You can also press a
in the watch mode to force Jest to run all tests.
Jest will always run all tests on a continuous integration server or if the project is not inside a Git or Mercurial repository.
To create tests, add it()
(or test()
) blocks with the name of the test and its code. You may optionally wrap them in describe()
blocks for logical grouping but this is neither required nor recommended.
Jest provides a built-in expect()
global function for making assertions. A basic test could look like this:
import sum from './sum' ;
it ( 'sums numbers' , ( ) => {
expect ( sum ( 1 , 2 ) ) . toEqual ( 3 ) ;
expect ( sum ( 2 , 2 ) ) . toEqual ( 4 ) ;
} ) ;
All expect()
matchers supported by Jest are extensively documented here.
You can also use jest.fn()
and expect(fn).toBeCalled()
to create “spies” or mock functions.
There is a broad spectrum of component testing techniques. They range from a “smoke test” verifying that a component renders without throwing, to shallow rendering and testing some of the output, to full rendering and testing component lifecycle and state changes.
Different projects choose different testing tradeoffs based on how often components change, and how much logic they contain. If you haven't decided on a testing strategy yet, we recommend that you start with creating simple smoke tests for your components:
import React from 'react' ;
import ReactDOM from 'react-dom' ;
import App from './App' ;
it ( 'renders without crashing' , ( ) => {
const div = document . createElement ( 'div' ) ;
ReactDOM . render ( < App / > , div ) ;
} ) ;
This test mounts a component and makes sure that it didn't throw during rendering. Tests like this provide a lot of value with very little effort so they are great as a starting point, and this is the test you will find in src/App.test.js
.
When you encounter bugs caused by changing components, you will gain a deeper insight into which parts of them are worth testing in your application. This might be a good time to introduce more specific tests asserting specific expected output or behavior.
If you'd like to test components in isolation from the child components they render, we recommend using shallow()
rendering API from Enzyme.要安装它,请运行:
npm install --save enzyme enzyme-adapter-react-16 react-test-renderer
Alternatively you may use yarn
:
yarn add enzyme enzyme-adapter-react-16 react-test-renderer
As of Enzyme 3, you will need to install Enzyme along with an Adapter corresponding to the version of React you are using. (The examples above use the adapter for React 16.)
The adapter will also need to be configured in your global setup file:
src/setupTests.js
import { configure } from 'enzyme' ;
import Adapter from 'enzyme-adapter-react-16' ;
configure ( { adapter : new Adapter ( ) } ) ;
Note: Keep in mind that if you decide to "eject" before creating
src/setupTests.js
, the resultingpackage.json
file won't contain any reference to it. Read here to learn how to add this after ejecting.
Now you can write a smoke test with it:
import React from 'react' ;
import { shallow } from 'enzyme' ;
import App from './App' ;
it ( 'renders without crashing' , ( ) => {
shallow ( < App / > ) ;
} ) ;
Unlike the previous smoke test using ReactDOM.render()
, this test only renders <App>
and doesn't go deeper. For example, even if <App>
itself renders a <Button>
that throws, this test will pass. Shallow rendering is great for isolated unit tests, but you may still want to create some full rendering tests to ensure the components integrate correctly. Enzyme supports full rendering with mount()
, and you can also use it for testing state changes and component lifecycle.
You can read the Enzyme documentation for more testing techniques. Enzyme documentation uses Chai and Sinon for assertions but you don't have to use them because Jest provides built-in expect()
and jest.fn()
for spies.
Here is an example from Enzyme documentation that asserts specific output, rewritten to use Jest matchers:
import React from 'react' ;
import { shallow } from 'enzyme' ;
import App from './App' ;
it ( 'renders welcome message' , ( ) => {
const wrapper = shallow ( < App / > ) ;
const welcome = < h2 > Welcome to React < / h2 > ;
// expect(wrapper.contains(welcome)).toBe(true);
expect ( wrapper . contains ( welcome ) ) . toEqual ( true ) ;
} ) ;
All Jest matchers are extensively documented here.
Nevertheless you can use a third-party assertion library like Chai if you want to, as described below.
Additionally, you might find jest-enzyme helpful to simplify your tests with readable matchers. The above contains
code can be written more simply with jest-enzyme.
expect ( wrapper ) . toContainReact ( welcome ) ;
To enable this, install jest-enzyme
:
npm install --save jest-enzyme
Alternatively you may use yarn
:
yarn add jest-enzyme
Import it in src/setupTests.js
to make its matchers available in every test:
import 'jest-enzyme' ;
We recommend that you use expect()
for assertions and jest.fn()
for spies. If you are having issues with them please file those against Jest, and we'll fix them. We intend to keep making them better for React, supporting, for example, pretty-printing React elements as JSX.
However, if you are used to other libraries, such as Chai and Sinon, or if you have existing code using them that you'd like to port over, you can import them normally like this:
import sinon from 'sinon' ;
import { expect } from 'chai' ;
and then use them in your tests like you normally do.
Note: this feature is available with
[email protected]
and higher.
If your app uses a browser API that you need to mock in your tests or if you just need a global setup before running your tests, add a src/setupTests.js
to your project. It will be automatically executed before running your tests.
例如:
src/setupTests.js
const localStorageMock = {
getItem : jest . fn ( ) ,
setItem : jest . fn ( ) ,
clear : jest . fn ( ) ,
} ;
global . localStorage = localStorageMock ;
Note: Keep in mind that if you decide to "eject" before creating
src/setupTests.js
, the resultingpackage.json
file won't contain any reference to it, so you should manually create the propertysetupTestFrameworkScriptFile
in the configuration for Jest, something like the following:
"jest" : { // ... "setupTestFrameworkScriptFile" : "<rootDir>/src/setupTests.js" }
You can replace it()
with xit()
to temporarily exclude a test from being executed.
Similarly, fit()
lets you focus on a specific test without running any other tests.
Jest has an integrated coverage reporter that works well with ES6 and requires no configuration.
Run npm test -- --coverage
(note extra --
in the middle) to include a coverage report like this:
Note that tests run much slower with coverage so it is recommended to run it separately from your normal workflow.
The default Jest coverage configuration can be overridden by adding any of the following supported keys to a Jest config in your package.json.
Supported overrides:
collectCoverageFrom
coverageReporters
coverageThreshold
snapshotSerializers
Example package.json:
{
"name" : " your-package " ,
"jest" : {
"collectCoverageFrom" : [
" src/**/*.{js,jsx} " ,
" !<rootDir>/node_modules/ " ,
" !<rootDir>/path/to/dir/ "
],
"coverageThreshold" : {
"global" : {
"branches" : 90 ,
"functions" : 90 ,
"lines" : 90 ,
"statements" : 90
}
},
"coverageReporters" : [ " text " ],
"snapshotSerializers" : [ " my-serializer-module " ]
}
}
By default npm test
runs the watcher with interactive CLI. However, you can force it to run tests once and finish the process by setting an environment variable called CI
.
When creating a build of your application with npm run build
linter warnings are not checked by default. Like npm test
, you can force the build to perform a linter warning check by setting the environment variable CI
. If any warnings are encountered then the build fails.
Popular CI servers already set the environment variable CI
by default but you can do this yourself too:
.travis.yml
file to your git repository. language: node_js
node_js:
- 8
cache:
directories:
- node_modules
script:
- npm run build
- npm test
Follow this article to set up CircleCI with a Create React App project.
set CI = true && npm test
set CI = true && npm run build
(Note: the lack of whitespace is intentional.)
( $ env: CI = $true ) -and (npm test)
( $ env: CI = $true ) -and (npm run build)
CI=true npm test
CI=true npm run build
The test command will force Jest to run tests once instead of launching the watcher.
If you find yourself doing this often in development, please file an issue to tell us about your use case because we want to make watcher the best experience and are open to changing how it works to accommodate more workflows.
The build command will check for linter warnings and fail if any are found.
If you know that none of your tests depend on jsdom, you can safely set --env=node
, and your tests will run faster:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
- "test": "react-scripts test"
+ "test": "react-scripts test --env=node"
To help you make up your mind, here is a list of APIs that need jsdom :
window
and document
ReactDOM.render()
TestUtils.renderIntoDocument()
(a shortcut for the above)mount()
in EnzymeIn contrast, jsdom is not needed for the following APIs:
TestUtils.createRenderer()
(shallow rendering)shallow()
in EnzymeFinally, jsdom is also not needed for snapshot testing.
Snapshot testing is a feature of Jest that automatically generates text snapshots of your components and saves them on the disk so if the UI output changes, you get notified without manually writing any assertions on the component output. Read more about snapshot testing.
If you use Visual Studio Code, there is a Jest extension which works with Create React App out of the box. This provides a lot of IDE-like features while using a text editor: showing the status of a test run with potential fail messages inline, starting and stopping the watcher automatically, and offering one-click snapshot updates.
There are various ways to setup a debugger for your Jest tests. We cover debugging in Chrome and Visual Studio Code.
Note: debugging tests requires Node 8 or higher.
Add the following to the scripts
section in your project's package.json
"scripts" : {
"test:debug" : " react-scripts --inspect-brk test --runInBand "
}
Place debugger;
statements in any test and run:
$ npm run test:debug
This will start running your Jest tests, but pause before executing to allow a debugger to attach to the process.
Open the following in Chrome
about:inspect
After opening that link, the Chrome Developer Tools will be displayed. Select inspect
on your process and a breakpoint will be set at the first line of the react script (this is done simply to give you time to open the developer tools and to prevent Jest from executing before you have time to do so). Click the button that looks like a "play" button in the upper right hand side of the screen to continue execution. When Jest executes the test that contains the debugger statement, execution will pause and you can examine the current scope and call stack.
Note: the --runInBand cli option makes sure Jest runs test in the same process rather than spawning processes for individual tests. Normally Jest parallelizes test runs across processes but it is hard to debug many processes at the same time.
Debugging Jest tests is supported out of the box for Visual Studio Code.
Use the following launch.json
configuration file:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug CRA Tests",
"type": "node",
"request": "launch",
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/react-scripts",
"args": [
"test",
"--runInBand",
"--no-cache"
],
"cwd": "${workspaceRoot}",
"protocol": "inspector",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}
Usually, in an app, you have a lot of UI components, and each of them has many different states. For an example, a simple button component could have following states:
Usually, it's hard to see these states without running a sample app or some examples.
Create React App doesn't include any tools for this by default, but you can easily add Storybook for React (source) or React Styleguidist (source) to your project. These are third-party tools that let you develop components and see all their states in isolation from your app .
You can also deploy your Storybook or style guide as a static app. This way, everyone in your team can view and review different states of UI components without starting a backend server or creating an account in your app.
Storybook is a development environment for React UI components.它允许您浏览组件库,查看每个组件的不同状态,并进行交互开发和测试组件。
First, install the following npm package globally:
npm install -g @storybook/cli
Then, run the following command inside your app's directory:
getstorybook
After that, follow the instructions on the screen.
Learn more about React Storybook:
Styleguidist combines a style guide, where all your components are presented on a single page with their props documentation and usage examples, with an environment for developing components in isolation, similar to Storybook. In Styleguidist you write examples in Markdown, where each code snippet is rendered as a live editable playground.
First, install Styleguidist:
npm install --save react-styleguidist
Alternatively you may use yarn
:
yarn add react-styleguidist
Then, add these scripts to your package.json
:
"scripts": {
+ "styleguide": "styleguidist server",
+ "styleguide:build": "styleguidist build",
"start": "react-scripts start",
Then, run the following command inside your app's directory:
npm run styleguide
After that, follow the instructions on the screen.
Learn more about React Styleguidist:
Create React App doesn't provide any built-in functionality to publish a component to npm. If you're ready to extract a component from your project so other people can use it, we recommend moving it to a separate directory outside of your project and then using a tool like nwb to prepare it for publishing.
The production build has all the tools necessary to generate a first-class Progressive Web App, but the offline/cache-first behavior is opt-in only . By default, the build process will generate a service worker file, but it will not be registered, so it will not take control of your production web app.
In order to opt-in to the offline-first behavior, developers should look for the following in their src/index.js
file:
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker . unregister ( ) ;
As the comment states, switching serviceWorker.unregister()
to serviceWorker.register()
will opt you in to using the service worker.
Offline-first Progressive Web Apps are faster and more reliable than traditional web pages, and provide an engaging mobile experience:
However, they can make debugging deployments more challenging so, starting with Create React App 2, service workers are opt-in.
The workbox-webpack-plugin
is integrated into production configuration, and it will take care of generating a service worker file that will automatically precache all of your local assets and keep them up to date as you deploy updates. The service worker will use a cache-first strategy for handling all requests for local assets, including navigation requests for your HTML, ensuring that your web app is consistently fast, even on a slow or unreliable network.
If you do decide to opt-in to service worker registration, please take the following into account:
Service workers require HTTPS, although to facilitate local testing, that policy does not apply to localhost
. If your production web server does not support HTTPS, then the service worker registration will fail, but the rest of your web app will remain functional.
Service workers are not supported in older web browsers. Service worker registration won't be attempted on browsers that lack support.
The service worker is only enabled in the production environment, eg the output of npm run build
. It's recommended that you do not enable an offline-first service worker in a development environment, as it can lead to frustration when previously cached assets are used and do not include the latest changes you've made locally.
If you need to test your offline-first service worker locally, build the application (using npm run build
) and run a simple http server from your build directory. After running the build script, create-react-app
will give instructions for one way to test your production build locally and the deployment instructions have instructions for using other methods. Be sure to always use an incognito window to avoid complications with your browser cache.
Users aren't always familiar with offline-first web apps. It can be useful to let the user know when the service worker has finished populating your caches (showing a "This web app works offline!" message) and also let them know when the service worker has fetched the latest updates that will be available the next time they load the page (showing a "New content is available; please refresh." message). Showing this messages is currently left as an exercise to the developer, but as a starting point, you can make use of the logic included in src/registerServiceWorker.js
, which demonstrates which service worker lifecycle events to listen for to detect each scenario, and which as a default, just logs appropriate messages to the JavaScript console.
By default, the generated service worker file will not intercept or cache any cross-origin traffic, like HTTP API requests, images, or embeds loaded from a different domain.
The default configuration includes a web app manifest located at public/manifest.json
, that you can customize with details specific to your web application.
When a user adds a web app to their homescreen using Chrome or Firefox on Android, the metadata in manifest.json
determines what icons, names, and branding colors to use when the web app is displayed. The Web App Manifest guide provides more context about what each field means, and how your customizations will affect your users' experience.
Progressive web apps that have been added to the homescreen will load faster and work offline when there's an active service worker. That being said, the metadata from the web app manifest will still be used regardless of whether or not you opt-in to service worker registration.
Source map explorer analyzes JavaScript bundles using the source maps. This helps you understand where code bloat is coming from.
To add Source map explorer to a Create React App project, follow these steps:
npm install --save source-map-explorer
Alternatively you may use yarn
:
yarn add source-map-explorer
Then in package.json
, add the following line to scripts
:
"scripts": {
+ "analyze": "source-map-explorer build/static/js/main.*",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
Then to analyze the bundle run the production build then run the analyze script.
npm run build
npm run analyze
npm run build
creates a build
directory with a production build of your app. Set up your favorite HTTP server so that a visitor to your site is served index.html
, and requests to static paths like /static/js/main.<hash>.js
are served with the contents of the /static/js/main.<hash>.js
file.
For environments using Node, the easiest way to handle this would be to install serve and let it handle the rest:
npm install -g serve
serve -s build
The last command shown above will serve your static site on the port 5000 . Like many of serve's internal settings, the port can be adjusted using the -p
or --port
flags.
Run this command to get a full list of the options available:
serve -h
You don't necessarily need a static server in order to run a Create React App project in production. It works just as fine integrated into an existing dynamic one.
Here's a programmatic example using Node and Express:
const express = require ( 'express' ) ;
const path = require ( 'path' ) ;
const app = express ( ) ;
app . use ( express . static ( path . join ( __dirname , 'build' ) ) ) ;
app . get ( '/' , function ( req , res ) {
res . sendFile ( path . join ( __dirname , 'build' , 'index.html' ) ) ;
} ) ;
app . listen ( 9000 ) ;
The choice of your server software isn't important either. Since Create React App is completely platform-agnostic, there's no need to explicitly use Node.
The build
folder with static assets is the only output produced by Create React App.
However this is not quite enough if you use client-side routing. Read the next section if you want to support URLs like /todos/42
in your single-page app.
If you use routers that use the HTML5 pushState
history API under the hood (for example, React Router with browserHistory
), many static file servers will fail. For example, if you used React Router with a route for /todos/42
, the development server will respond to localhost:3000/todos/42
properly, but an Express serving a production build as above will not.
This is because when there is a fresh page load for a /todos/42
, the server looks for the file build/todos/42
and does not find it. The server needs to be configured to respond to a request to /todos/42
by serving index.html
. For example, we can amend our Express example above to serve index.html
for any unknown paths:
app.use(express.static(path.join(__dirname, 'build')));
- app.get('/', function (req, res) {
+ app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
If you're using Apache HTTP Server, you need to create a .htaccess
file in the public
folder that looks like this:
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]
It will get copied to the build
folder when you run npm run build
.
If you're using Apache Tomcat, you need to follow this Stack Overflow answer.
Now requests to /todos/42
will be handled correctly both in development and in production.
On a production build, and when you've opted-in, a service worker will automatically handle all navigation requests, like for /todos/42
, by serving the cached copy of your index.html
. This service worker navigation routing can be configured or disabled by eject
ing and then modifying the navigateFallback
and navigateFallbackWhitelist
options of the SWPreachePlugin
configuration.
When users install your app to the homescreen of their device the default configuration will make a shortcut to /index.html
. This may not work for client-side routers which expect the app to be served from /
. Edit the web app manifest at public/manifest.json
and change start_url
to match the required URL scheme, for example:
"start_url" : "." ,
By default, Create React App produces a build assuming your app is hosted at the server root.
To override this, specify the homepage
in your package.json
, for example:
"homepage" : "http://mywebsite.com/relativepath" ,
This will let Create React App correctly infer the root path to use in the generated HTML file.
Note : If you are using react-router@^4
, you can root <Link>
s using the basename
prop on any <Router>
.
更多信息在这里。
例如:
< BrowserRouter basename = "/calendar" / >
< Link to = "/today" / > // renders <a href="/calendar/today">
Note: this feature is available with
[email protected]
and higher.
If you are not using the HTML5 pushState
history API or not using client-side routing at all, it is unnecessary to specify the URL from which your app will be served. Instead, you can put this in your package.json
:
"homepage" : "." ,
This will make sure that all the asset paths are relative to index.html
. You will then be able to move your app from http://mywebsite.com
to http://mywebsite.com/relativepath
or even http://mywebsite.com/relative/path
without having to rebuild it.
You can create an arbitrary build environment by creating a custom .env
file and loading it using env-cmd.
For example, to create a build environment for a staging environment:
.env.staging
.env
file (eg REACT_APP_API_URL=http://api-staging.example.com
)$ npm install env-cmd --save
$ # or
$ yarn add env-cmd
package.json
, building with your new environment: {
"scripts" : {
"build:staging" : " env-cmd .env.staging npm run build "
}
}
Now you can run npm run build:staging
to build with the staging environment config. You can specify other environments in the same way.
Variables in .env.production
will be used as fallback because NODE_ENV
will always be set to production
for a build.
See this blog post on how to deploy your React app to Microsoft Azure.
See this blog post or this repo for a way to use automatic deployment to Azure App Service.
Install the Firebase CLI if you haven't already by running npm install -g firebase-tools
. Sign up for a Firebase account and create a new project. Run firebase login
and login with your previous created Firebase account.
Then run the firebase init
command from your project's root. You need to choose the Hosting: Configure and deploy Firebase Hosting sites and choose the Firebase project you created in the previous step. You will need to agree with database.rules.json
being created, choose build
as the public directory, and also agree to Configure as a single-page app by replying with y
.
=== Project Setup
First, let ' s associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add,
but for now we ' ll just set up a default project.
? What Firebase project do you want to associate as default ? Example app (example-app-fd690)
=== Database Setup
Firebase Realtime Database Rules allow you to define how your data should be
structured and when your data can be read from and written to.
? What file should be used for Database Rules ? database.rules.json
✔ Database Rules for example-app-fd690 have been downloaded to database.rules.json.
Future modifications to database.rules.json will update Database Rules when you run
firebase deploy.
=== Hosting Setup
Your public directory is the folder (relative to your project directory) that
will contain Hosting assets to uploaded with firebase deploy. If you
have a build process for your assets, use your build ' s output directory.
? What do you want to use as your public directory? build
? Configure as a single-page app (rewrite all urls to /index.html)? Yes
✔ Wrote build/index.html
i Writing configuration info to firebase.json...
i Writing project information to .firebaserc...
✔ Firebase initialization complete!
IMPORTANT: you need to set proper HTTP caching headers for service-worker.js
file in firebase.json
file or you will not be able to see changes after first deployment (issue #2440). It should be added inside "hosting"
key like next:
{
"hosting": {
...
"headers": [
{"source": "/service-worker.js", "headers": [{"key": "Cache-Control", "value": "no-cache"}]}
]
...
Now, after you create a production build with npm run build
, you can deploy it by running firebase deploy
.
=== Deploying to ' example-app-fd690 ' ...
i deploying database, hosting
✔ database: rules ready to deploy.
i hosting: preparing build directory for upload...
Uploading: [ ============================== ] 75%✔ hosting: build folder uploaded successfully
✔ hosting: 8 files uploaded successfully
i starting release process (may take several minutes)...
✔ Deploy complete !
Project Console: https://console.firebase.google.com/project/example-app-fd690/overview
Hosting URL: https://example-app-fd690.firebaseapp.com
For more information see Add Firebase to your JavaScript Project.
Note: this feature is available with
[email protected]
and higher.
homepage
to package.json
The step below is important!
If you skip it, your app will not deploy correctly.
Open your package.json
and add a homepage
field for your project:
"homepage" : " https://myusername.github.io/my-app " ,
or for a GitHub user page:
"homepage" : " https://myusername.github.io " ,
or for a custom domain page:
"homepage" : " https://mywebsite.com " ,
Create React App uses the homepage
field to determine the root URL in the built HTML file.
gh-pages
and add deploy
to scripts
in package.json
Now, whenever you run npm run build
, you will see a cheat sheet with instructions on how to deploy to GitHub Pages.
To publish it at https://myusername.github.io/my-app, run:
npm install --save gh-pages
Alternatively you may use yarn
:
yarn add gh-pages
Add the following scripts in your package.json
:
"scripts": {
+ "predeploy": "npm run build",
+ "deploy": "gh-pages -d build",
"start": "react-scripts start",
"build": "react-scripts build",
The predeploy
script will run automatically before deploy
is run.
If you are deploying to a GitHub user page instead of a project page you'll need to make two additional modifications:
package.json
scripts to push deployments to master : "scripts": {
"predeploy": "npm run build",
- "deploy": "gh-pages -d build",
+ "deploy": "gh-pages -b master -d build",
npm run deploy
然后运行:
npm run deploy
gh-pages
Finally, make sure GitHub Pages option in your GitHub project settings is set to use the gh-pages
branch:
您可以通过将CNAME
文件添加到public/
文件夹中,以使用GitHub页面配置自定义域。
Your CNAME file should look like this:
mywebsite.com
GitHub Pages doesn't support routers that use the HTML5 pushState
history API under the hood (for example, React Router using browserHistory
). This is because when there is a fresh page load for a url like http://user.github.io/todomvc/todos/42
, where /todos/42
is a frontend route, the GitHub Pages server returns 404 because it knows nothing of /todos/42
. If you want to add a router to a project hosted on GitHub Pages, here are a couple of solutions:
hashHistory
for this effect, but the URL will be longer and more verbose (for example, http://user.github.io/todomvc/#/todos/42?_k=yknaj
) 。 Read more about different history implementations in React Router.index.html
page with a special redirect parameter. You would need to add a 404.html
file with the redirection code to the build
folder before deploying your project, and you'll need to add code handling the redirect parameter to index.html
. You can find a detailed explanation of this technique in this guide. If, when deploying, you get /dev/tty: No such a device or address
or a similar error, try the following:
git remote set-url origin https://<user>:<token>@github.com/<user>/<repo>
.npm run deploy
again If, when deploying, you get Cannot read property 'email' of null
, try the following:
git config --global user.name '<your_name>'
git config --global user.email '<your_email>'
npm run deploy
again Use the Heroku Buildpack for Create React App.
You can find instructions in Deploying React with Zero Configuration.
Sometimes npm run build
works locally but fails during deploy via Heroku. Following are the most common cases.
If you get something like this:
remote: Failed to create a production build. Reason:
remote: Module not found: Error: Cannot resolve 'file' or 'directory'
MyDirectory in /tmp/build_1234/src
It means you need to ensure that the lettercase of the file or directory you import
matches the one you see on your filesystem or on GitHub.
This is important because Linux (the operating system used by Heroku) is case sensitive. So MyDirectory
and mydirectory
are two distinct directories and thus, even though the project builds locally, the difference in case breaks the import
statements on Heroku remotes.
If you exclude or ignore necessary files from the package you will see a error similar this one:
remote: Could not find a required file.
remote: Name: `index.html`
remote: Searched in: /tmp/build_a2875fc163b209225122d68916f1d4df/public
remote:
remote: npm ERR! Linux 3.13.0-105-generic
remote: npm ERR! argv "/tmp/build_a2875fc163b209225122d68916f1d4df/.heroku/node/bin/node" "/tmp/build_a2875fc163b209225122d68916f1d4df/.heroku/node/bin/npm" "run" "build"
In this case, ensure that the file is there with the proper lettercase and that's not ignored on your local .gitignore
or ~/.gitignore_global
.
To do a manual deploy to Netlify's CDN:
npm install netlify-cli -g
netlify deploy
Choose build
as the path to deploy.
To setup continuous delivery:
With this setup Netlify will build and deploy when you push to git or open a pull request:
Build your site
Support for client-side routing:
To support pushState
, make sure to create a public/_redirects
file with the following rewrite rules:
/* /index.html 200
When you build the project, Create React App will place the public
folder contents into the build output.
Now offers a zero-configuration single-command deployment. You can use now
to deploy your app for free.
Install the now
command-line tool either via the recommended desktop tool or via node with npm install -g now
.
Build your app by running npm run build
.
Move into the build directory by running cd build
.
Run now --name your-project-name
from within the build directory. You will see a now.sh URL in your output like this:
> Ready! https://your-project-name-tpspyhtdtk.now.sh (copied to clipboard)
Paste that URL into your browser when the build is complete, and you will see your deployed app.
Details are available in this article.
See this blog post on how to deploy your React app to Amazon Web Services S3 and CloudFront.
Install the Surge CLI if you haven't already by running npm install -g surge
. Run the surge
command and log in you or create a new account.
When asked about the project path, make sure to specify the build
folder, for example:
project path: /path/to/project/build
Note that in order to support routers that use HTML5 pushState
API, you may want to rename the index.html
in your build folder to 200.html
before deploying to Surge. This ensures that every URL falls back to that file.
You can adjust various development and production settings by setting environment variables in your shell or with .env.
多变的 | 发展 | 生产 | 用法 |
---|---|---|---|
BROWSER | ✅ | By default, Create React App will open the default system browser, favoring Chrome on macOS. Specify a browser to override this behavior, or set it to none to disable it completely. If you need to customize the way the browser is launched, you can specify a node script instead. Any arguments passed to npm start will also be passed to this script, and the url where your app is served will be the last argument. Your script's file name must have the .js extension. | |
主持人 | ✅ | By default, the development web server binds to localhost . You may use this variable to specify a different host. | |
港口 | ✅ | By default, the development web server will attempt to listen on port 3000 or prompt you to attempt the next available port. You may use this variable to specify a different port. | |
https | ✅ | When set to true , Create React App will run the development server in https mode. | |
public_url | ✅ | Create React App assumes your application is hosted at the serving web server's root or a subpath as specified in package.json ( homepage ). Normally, Create React App ignores the hostname. You may use this variable to force assets to be referenced verbatim to the url you provide (hostname included). This may be particularly useful when using a CDN to host your application. | |
CI | ? | ✅ | When set to true , Create React App treats warnings as failures in the build. It also makes the test runner non-watching. Most CIs set this flag by default. |
REACT_EDITOR | ✅ | When an app crashes in development, you will see an error overlay with clickable stack trace. When you click on it, Create React App will try to determine the editor you are using based on currently running processes, and open the relevant source file. You can send a pull request to detect your editor of choice. Setting this environment variable overrides the automatic detection. If you do it, make sure your systems PATH environment variable points to your editor's bin folder. You can also set it to none to disable it completely. | |
CHOKIDAR_USEPOLLING | ✅ | When set to true , the watcher runs in polling mode, as necessary inside a VM. Use this option if npm start isn't detecting changes. | |
GENERATE_SOURCEMAP | ✅ | When set to false , source maps are not generated for a production build. This solves OOM issues on some smaller machines. | |
NODE_PATH | ✅ | ✅ | Same as NODE_PATH in Node.js, but only relative folders are allowed. Can be handy for emulating a monorepo setup by setting NODE_PATH=src . |
npm start
doesn't detect changes When you save a file while npm start
is running, the browser should refresh with the updated code.
If this doesn't happen, try one of the following workarounds:
index.js
and you're referencing it by the folder name, you need to restart the watcher due to a Webpack bug..env
file in your project directory if it doesn't exist, and add CHOKIDAR_USEPOLLING=true
to it. This ensures that the next time you run npm start
, the watcher uses the polling mode, as necessary inside a VM.If none of these solutions help please leave a comment in this thread.
npm test
hangs or crashes on macOS Sierra If you run npm test
and the console gets stuck after printing react-scripts test
to the console there might be a problem with your Watchman installation as described in facebook/create-react-app#713.
We recommend deleting node_modules
in your project and running npm install
(or yarn
if you use it) first. If it doesn't help, you can try one of the numerous workarounds mentioned in these issues:
It is reported that installing Watchman 4.7.0 or newer fixes the issue. If you use Homebrew, you can run these commands to update it:
watchman shutdown-server
brew update
brew reinstall watchman
You can find other installation methods on the Watchman documentation page.
If this still doesn't help, try running launchctl unload -F ~/Library/LaunchAgents/com.github.facebook.watchman.plist
.
There are also reports that uninstalling Watchman fixes the issue. So if nothing else helps, remove it from your system and try again.
npm run build
exits too early It is reported that npm run build
can fail on machines with limited memory and no swap space, which is common in cloud environments. Even with small projects this command can increase RAM usage in your system by hundreds of megabytes, so if you have less than 1 GB of available memory your build is likely to fail with the following message:
The build failed because the process exited too early. This probably means the system ran out of memory or someone called
kill -9
on the process.
If you are completely sure that you didn't terminate the process, consider adding some swap space to the machine you're building on, or build the project locally.
npm run build
fails on HerokuThis may be a problem with case sensitive filenames. Please refer to this section.
If you use a Moment.js, you might notice that only the English locale is available by default. This is because the locale files are large, and you probably only need a subset of all the locales provided by Moment.js.
To add a specific Moment.js locale to your bundle, you need to import it explicitly.
例如:
import moment from 'moment' ;
import 'moment/locale/fr' ;
If you are importing multiple locales this way, you can later switch between them by calling moment.locale()
with the locale name:
import moment from 'moment' ;
import 'moment/locale/fr' ;
import 'moment/locale/es' ;
// ...
moment . locale ( 'fr' ) ;
This will only work for locales that have been explicitly imported before.
npm run build
无法缩小Before [email protected]
, this problem was caused by third party node_modules
using modern JavaScript features because the minifier couldn't handle them during the build. This has been solved by compiling standard modern JavaScript features inside node_modules
in [email protected]
and higher.
If you're seeing this error, you're likely using an old version of react-scripts
. You can either fix it by avoiding a dependency that uses modern syntax, or by upgrading to react-scripts@>=2.0.0
and following the migration instructions in the changelog.
Ejecting lets you customize anything, but from that point on you have to maintain the configuration and scripts yourself. This can be daunting if you have many similar projects. In such cases instead of ejecting we recommend to fork react-scripts
and any other packages you need. This article dives into how to do it in depth. You can find more discussion in this issue.
If you have ideas for more “How To” recipes that should be on this page, let us know or contribute some!