Skip to main content

部署

npm run build 创建一个 build 目录,其中包含你的应用程序的生产版本。 设置你最喜欢的 HTTP 服务器,以便为你网站的访问者提供 index.html,并为对 /static/js/main.<hash>.js 等静态路径的请求提供 /static/js/main.<hash>.js 文件的内容。 有关详细信息,请参阅 生产构建 部分。

静态服务器

对于使用 Node 的环境,处理此问题的最简单方法是安装 serve 并让它处理其余部分:

npm install -g serve
serve -s build

上面显示的最后一个命令将在端口 3000 上为你的静态站点提供服务。 与 serve 的许多内部设置一样,可以使用 -l--listen 标志调整端口:

serve -s build -l 4000

运行此命令以获取可用选项的完整列表:

serve -h

其他解决方案

你不一定需要静态服务器才能在生产环境中运行 Create React App 项目。 当集成到现有的服务器端应用程序中时,它也能很好地工作。

这是一个使用 NodeExpress 的编程示例:

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);

服务器软件的选择也不重要。 由于 Create React App 完全与平台无关,因此无需显式使用 Node.js。

带有静态资产的 build 文件夹是 Create React App 产生的唯一输出。

但是,如果你使用客户端路由,这还不够。 如果你想在单页应用程序中支持像 /todos/42 这样的 URL,请阅读下一节。

使用客户端路由服务应用程序

如果你使用在引擎盖下使用 HTML5 pushState 历史 API 的路由(例如,React RouterbrowserHistory),许多静态文件服务器将失败。 例如,如果你将 React Router 与 /todos/42 的路由一起使用,开发服务器将正确响应 localhost:3000/todos/42,但服务于上述生产构建的 Express 则不会。

这是因为当 /todos/42 有新的页面加载时,服务器查找文件 build/todos/42 但没有找到。 服务器需要配置为通过服务 index.html 来响应对 /todos/42 的请求。 例如,我们可以修改上面的 Express 示例,为任何未知路径提供 index.html

 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'));
});

如果你使用的是 HTTP 服务器,则需要在 public 文件夹中创建一个 .htaccess 文件,如下所示:

    Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

当你运行 npm run build 时,它将被复制到 build 文件夹。

如果你使用 Apache Tomcat,则需要遵循 此 Stack Overflow 答案

现在,对 /todos/42 的请求将在开发和生产中得到正确处理。

在生产版本中,当你拥有 opted-in 时,服务工作线程 将通过提供 index.html 的缓存副本来自动处理所有导航请求,例如 /todos/42。 这个service worker导航路由可以通过ejecting配置或者禁用,然后修改SWPrecachePlugin配置的navigateFallbacknavigateFallbackWhitelist选项。

当用户将你的应用程序安装到他们设备的主屏幕时,默认配置会创建一个指向 /index.html 的快捷方式。 这可能不适用于希望从 / 提供应用程序的客户端路由。 编辑 public/manifest.json 处的 Web 应用程序清单并更改 start_url 以匹配所需的 URL 方案,例如:

  "start_url": ".",

构建相对路径

默认情况下,Create React App 会生成一个构建,假设你的应用程序托管在服务器根目录下。

要覆盖它,请在 package.json 中指定 homepage,例如:

  "homepage": "http://mywebsite.com/relativepath",

这将使 Create React App 正确推断要在生成的 HTML 文件中使用的根路径。

注意: 如果你使用的是 react-router@^4,则可以在任何 <Router> 上使用 basename 属性来 root <Link>

更多信息 here

例如:

<BrowserRouter basename="/calendar"/>
<Link to="/today"/> // renders <a href="/calendar/today">

从不同的路径提供相同的构建

注意: react-scripts@0.9.0 及更高版本提供此功能。

如果你不使用 HTML5 pushState history API 或根本不使用客户端路由,则无需指定将从中提供你的应用程序的 URL。 相反,你可以将其放入你的 package.json

  "homepage": ".",

这将确保所有资产路径都与 index.html 相关。 然后,你将能够将你的应用程序从 http://mywebsite.com 移动到 http://mywebsite.com/relativepath 甚至 http://mywebsite.com/relative/path,而无需重新构建它。

为任意构建环境自定义环境变量

你可以通过创建自定义 .env 文件并使用 env-cmd 加载它来创建任意构建环境。

例如,要为暂存环境创建构建环境:

  1. 创建一个名为 .env.staging 的文件
  2. 像设置任何其他 .env 文件(例如 REACT_APP_API_URL=http://api-staging.example.com)一样设置环境变量
  3. 安装 env-cmd
    $ npm install env-cmd --save
    $ # or
    $ yarn add env-cmd
  4. 将新脚本添加到你的 package.json,使用你的新环境进行构建:
    {
    "scripts": {
    "build:staging": "env-cmd -f .env.staging npm run build"
    }
    }

现在你可以运行 npm run build:staging 以使用暂存环境配置进行构建。 你可以以相同的方式指定其他环境。

.env.production 中的变量将用作回退,因为 NODE_ENV 将始终设置为 production 以进行构建。

AWS 放大

AWS Amplify 控制台为具有无服务器后端的现代 Web 应用程序(单页应用程序和静态站点生成器)提供持续部署和托管。 Amplify 控制台提供全球可用的 CDN、自定义域设置、功能分支部署和密码保护。

  1. 登录到 Amplify 控制台 here
  2. 连接你的 Create React App 存储库并选择一个分支。 如果你正在寻找 Create React App+Amplify 启动器,请尝试演示使用 Create React App 在 10 分钟内设置身份验证的 create-react-app-auth-amplify 启动器
  3. Amplify 控制台会自动检测构建设置。 选择下一步。
  4. 选择保存并部署。

如果构建成功,应用程序将部署并托管在具有 amplifyapp.com 域的全球 CDN 上。 你现在可以持续将更改部署到你的前端或后端。 持续部署允许开发人员在每次代码提交到他们的 Git 存储库时将更新部署到他们的前端和后端。

Azure

Azure 静态 Web 应用程序为由 GitHub Actions 提供支持的 React 应用程序创建一个自动构建和部署管道。 默认情况下,应用程序是地理分布的,具有多个存在点。 PR 是为暂存环境预览自动构建的。

  1. 创建一个新的静态 Web 应用程序 here
  2. 添加详细信息并连接到你的 GitHub 存储库。
  3. 确保在 "build" 选项卡上正确设置构建文件夹并创建资源。

Azure 静态 Web 应用程序将自动在你的存储库中配置 GitHub 操作并开始部署。

有关路由、API、身份验证和授权、自定义域等的更多信息,请参阅 Azure 静态 Web 应用文档

Firebase

如果你还没有通过运行 npm install -g firebase-tools 安装 Firebase CLI。 注册 Firebase 账户 并创建一个新项目。 运行 firebase login 并使用你之前创建的 Firebase 账户登录。

然后从项目的根目录运行 firebase init 命令。 你需要选择 Hosting: Configure and deploy Firebase Hosting sites 并选择你在上一步中创建的 Firebase 项目。 你需要同意创建 database.rules.json,选择 build 作为公共目录,并通过回复 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 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 你需要为 firebase.json 文件中的 service-worker.js 文件设置正确的 HTTP 缓存标头,否则你将无法在首次部署 (issue #2440) 后看到更改。 它应该像下面一样添加到 "hosting" 键中:

{
"hosting": {
...
"headers": [
{"source": "/service-worker.js", "headers": [{"key": "Cache-Control", "value": "no-cache"}]}
]
...

现在,在使用 npm run build 创建生产版本后,你可以通过运行 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

有关详细信息,请参阅 Firebase 托管

GitHub 页面

注意: react-scripts@0.2.0 及更高版本提供此功能。

第 1 步:将 homepage 添加到 package.json

下面的步骤很重要!

如果你跳过它,你的应用将无法正确部署。

打开你的 package.json 并为你的项目添加一个 homepage 字段:

  "homepage": "https://myusername.github.io/my-app",

或者对于 GitHub 用户页面:

  "homepage": "https://myusername.github.io",

或自定义域页面:

  "homepage": "https://mywebsite.com",

Create React App 使用 homepage 字段来确定构建的 HTML 文件中的根 URL。

第二步:安装 gh-pages,将 deploy 添加到 package.json 中的 scripts

现在,无论何时运行 npm run build,你都会看到一张备忘单,其中包含有关如何部署到 GitHub Pages 的说明。

要在 https://myusername.github.io/my-app 上发布它,请运行:

npm install --save gh-pages

或者你可以使用 yarn

yarn add gh-pages

在你的 package.json 中添加以下脚本:

  "scripts": {
+ "predeploy": "npm run build",
+ "deploy": "gh-pages -d build",
"start": "react-scripts start",
"build": "react-scripts build",

predeploy 脚本将在 deploy 运行之前自动运行。

如果你要部署到 GitHub 用户页面而不是项目页面,你需要进行一项额外的修改:

  1. 调整你的 package.json 脚本以将部署推送到 main
  "scripts": {
"predeploy": "npm run build",
- "deploy": "gh-pages -d build",
+ "deploy": "gh-pages -b main -d build",

第 3 步:通过运行 npm run deploy 部署站点

然后运行:

npm run deploy

第 4 步:对于项目页面,确保项目的设置使用 gh-pages

最后,确保 GitHub 项目设置中的 GitHub Pages 选项设置为使用 gh-pages 分支:

gh-pages branch setting

第 5 步:(可选)配置域

你可以通过将 CNAME 文件添加到 public/ 文件夹来使用 GitHub Pages 配置自定义域。

你的 CNAME 文件应如下所示:

mywebsite.com

客户端路由注意事项

GitHub Pages 不支持在后台使用 HTML5 pushState 历史记录 API 的路由(例如,使用 browserHistory 的 React Router)。 这是因为当像 http://user.github.io/todomvc/todos/42 这样的 url 有新的页面加载时,其中 /todos/42 是前端路由,GitHub Pages 服务器返回 404,因为它对 /todos/42 一无所知。 如果你想将路由添加到 GitHub Pages 上托管的项目,这里有几个解决方案:

  • 你可以从使用 HTML5 历史 API 切换到使用哈希路由。 如果你使用 React Router,你可以切换到 hashHistory 来实现这个效果,但是 URL 会更长更冗长(例如,http://user.github.io/todomvc/#/todos/42?_k=yknaj)。 阅读更多 关于 React Router 中不同的历史实现。
  • 或者,你可以使用一个技巧来教 GitHub Pages 处理 404,方法是使用自定义重定向参数重定向到你的 index.html 页面。 在部署项目之前,你需要将带有重定向代码的 404.html 文件添加到 build 文件夹,并且你需要将处理重定向参数的代码添加到 index.html。 你可以找到此技术的详细说明 in this guide

故障排除

"/dev/tty: No such a device or address"

如果在部署时出现 /dev/tty: No such a device or address 或类似错误,请尝试以下操作:

  1. 创建一个新的 个人访问令牌
  2. git remote set-url origin https://<user>:<token>@github.com/<user>/<repo>
  3. 再试试 npm run deploy

"Cannot read property 'email' of null"

如果在部署时获得 Cannot read property 'email' of null,请尝试以下操作:

  1. git config --global user.name '<your_name>'
  2. git config --global user.email '<your_email>'
  3. 再试试 npm run deploy

Heroku

使用 用于创建 React 应用程序的 Heroku Buildpack

你可以在 零配置部署 React 中找到说明。

解决 Heroku 部署错误

有时 npm run build 在本地工作,但在通过 Heroku 部署期间失败。 以下是最常见的情况。

"Module not found: Error: Cannot resolve 'file' or 'directory'"

如果你得到这样的东西:

remote: Failed to create a production build. Reason:
remote: Module not found: Error: Cannot resolve 'file' or 'directory'
MyDirectory in /tmp/build_1234/src

这意味着你需要确保你 import 的文件或目录的字母大小写与你在文件系统或 GitHub 上看到的相匹配。

这很重要,因为 Linux(Heroku 使用的操作系统)区分大小写。 所以 MyDirectorymydirectory 是两个不同的目录,因此,即使项目在本地构建,大小写上的差异也会破坏 Heroku 遥控器上的 import 语句。

"Could not find a required file."

如果你从包中排除或忽略必要的文件,你将看到类似以下的错误:

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"

在这种情况下,请确保该文件以正确的字母大小写存在,并且不会在你的本地 .gitignore~/.gitignore_global 上被忽略。

Netlify

手动部署到 Netlify 的 CDN:

npm install netlify-cli -g
netlify deploy

选择 build 作为部署路径。

设置持续交付:

使用此设置,当你推送到 git 或打开拉取请求时,Netlify 将构建和部署:

  1. 开始一个新的 netlify 项目
  2. 选择你的 Git 托管服务并选择你的存储库
  3. 点击 Build your site

支持客户端路由:

要支持 pushState,请确保创建具有以下重写规则的 public/_redirects 文件:

/*  /index.html  200

当你构建项目时,Create React App 会将 public 文件夹内容放入构建输出中。

Vercel

Vercel 是一个云平台,使开发人员能够托管 Jamstack 网站和 Web 服务,这些网站和 Web 服务可即时部署、自动扩展且无需监督,所有这些均采用零配置。 它们提供全球边缘网络、SSL 加密、资产压缩、缓存失效等。

第 1 步:将 React 项目部署到 Vercel

要使用 用于 Git 集成的 Vercel 部署 React 项目,请确保它已被推送到 Git 存储库。

使用 导入流程 将项目导入 Vercel。 在导入过程中,你会发现所有相关的 options 都已为你预先配置,并且可以根据需要进行更改。

导入项目后,所有后续的分支推送都会生成 预览部署,对 生产分支(通常为 "master" 或 "main")所做的所有更改都会生成 生产部署

部署后,你将获得一个 URL 以实时查看你的应用程序,例如: https://create-react-app-example.vercel.app/ .

第 2 步(可选):使用自定义域

如果你想在 Vercel 部署中使用自定义域,你可以通过 Vercel 账户域设置。 添加转移你的域

要将你的域添加到你的项目,请从 Vercel 仪表板导航到你的 项目。 选择项目后,单击 "设置" 选项卡,然后选择 Domains 菜单项。 在你的项目 Domain 页面中,输入你希望添加到项目中的域。

添加域后,你将看到不同的配置方法。

部署一个新的 React 项目

你可以部署一个新的 React 项目,为你设置一个 Git 存储库,使用以下部署按钮:

使用 Vercel 部署

Vercel 参考资料:

渲染

Render 提供免费的 static site 托管,具有完全托管的 SSL、全球 CDN 和来自 GitHub 的持续自动部署。

按照 创建 React App 部署指南 在几分钟内部署你的应用程序。

使用邀请码 cra 注册或使用 this link

S3CloudFront

请参阅此 blog post,了解如何将 React 应用程序部署到 Amazon Web Services S3 和 CloudFront。 如果你希望添加自定义域、HTTPS 和持续部署,请参阅此 blog post

Surge

如果你还没有通过运行 npm install -g surge 安装 Surge CLI。 运行 surge 命令并登录你或创建一个新账户。

当询问项目路径时,确保指定 build 文件夹,例如:

       project path: /path/to/project/build

请注意,为了支持使用 HTML5 pushState API 的路由,你可能需要在部署到 Surge 之前将构建文件夹中的 index.html 重命名为 200.html。 这个确保每个 URL 回退到该文件

发布组件到 npm

Create React App 不提供任何将组件发布到 npm 的内置功能。 如果你准备好从你的项目中提取一个组件以便其他人可以使用它,我们建议你将它移动到你项目之外的一个单独的目录,然后使用像 nwb 这样的工具来准备发布。