mirror of
https://github.com/zhigang1992/create-react-app.git
synced 2026-04-24 05:05:53 +08:00
Move deployment to its own file
This commit is contained in:
458
docusaurus/docs/deployment.md
Normal file
458
docusaurus/docs/deployment.md
Normal file
@@ -0,0 +1,458 @@
|
||||
---
|
||||
id: deployment
|
||||
title: Deployment
|
||||
sidebar_label: Deployment
|
||||
---
|
||||
|
||||
`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.
|
||||
|
||||
### Static Server
|
||||
|
||||
For environments using [Node](https://nodejs.org/), the easiest way to handle this would be to install [serve](https://github.com/zeit/serve) and let it handle the rest:
|
||||
|
||||
```sh
|
||||
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](https://github.com/zeit/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:
|
||||
|
||||
```sh
|
||||
serve -h
|
||||
```
|
||||
|
||||
### Other Solutions
|
||||
|
||||
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](https://nodejs.org/) and [Express](http://expressjs.com/):
|
||||
|
||||
```javascript
|
||||
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.
|
||||
|
||||
### Serving Apps with Client-Side Routing
|
||||
|
||||
If you use routers that use the HTML5 [`pushState` history API](https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries) under the hood (for example, [React Router](https://github.com/ReactTraining/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:
|
||||
|
||||
```diff
|
||||
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](https://httpd.apache.org/), 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](http://tomcat.apache.org/), you need to follow [this Stack Overflow answer](https://stackoverflow.com/a/41249464/4878474).
|
||||
|
||||
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](#why-opt-in),
|
||||
a [service worker](https://developers.google.com/web/fundamentals/primers/service-workers/) 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](#npm-run-eject) and then modifying the
|
||||
[`navigateFallback`](https://github.com/GoogleChrome/sw-precache#navigatefallback-string)
|
||||
and [`navigateFallbackWhitelist`](https://github.com/GoogleChrome/sw-precache#navigatefallbackwhitelist-arrayregexp)
|
||||
options of the `SWPreachePlugin` [configuration](../config/webpack.config.prod.js).
|
||||
|
||||
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`](public/manifest.json) and change `start_url` to match the required URL scheme, for example:
|
||||
|
||||
```js
|
||||
"start_url": ".",
|
||||
```
|
||||
|
||||
### Building for Relative Paths
|
||||
|
||||
By default, Create React App produces a build assuming your app is hosted at the server root.<br>
|
||||
To override this, specify the `homepage` in your `package.json`, for example:
|
||||
|
||||
```js
|
||||
"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>`.<br>
|
||||
More information [here](https://reacttraining.com/react-router/web/api/BrowserRouter/basename-string).<br>
|
||||
<br>
|
||||
For example:
|
||||
|
||||
```js
|
||||
<BrowserRouter basename="/calendar"/>
|
||||
<Link to="/today"/> // renders <a href="/calendar/today">
|
||||
```
|
||||
|
||||
#### Serving the Same Build from Different Paths
|
||||
|
||||
> Note: this feature is available with `react-scripts@0.9.0` 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`:
|
||||
|
||||
```js
|
||||
"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.
|
||||
|
||||
### Customizing Environment Variables for Arbitrary Build Environments
|
||||
|
||||
You can create an arbitrary build environment by creating a custom `.env` file and loading it using [env-cmd](https://www.npmjs.com/package/env-cmd).
|
||||
|
||||
For example, to create a build environment for a staging environment:
|
||||
|
||||
1. Create a file called `.env.staging`
|
||||
1. Set environment variables as you would any other `.env` file (e.g. `REACT_APP_API_URL=http://api-staging.example.com`)
|
||||
1. Install [env-cmd](https://www.npmjs.com/package/env-cmd)
|
||||
```sh
|
||||
$ npm install env-cmd --save
|
||||
$ # or
|
||||
$ yarn add env-cmd
|
||||
```
|
||||
1. Add a new script to your `package.json`, building with your new environment:
|
||||
```json
|
||||
{
|
||||
"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.
|
||||
|
||||
### [Azure](https://azure.microsoft.com/)
|
||||
|
||||
See [this](https://medium.com/@to_pe/deploying-create-react-app-on-microsoft-azure-c0f6686a4321) blog post on how to deploy your React app to Microsoft Azure.
|
||||
|
||||
See [this](https://medium.com/@strid/host-create-react-app-on-azure-986bc40d5bf2#.pycfnafbg) blog post or [this](https://github.com/ulrikaugustsson/azure-appservice-static) repo for a way to use automatic deployment to Azure App Service.
|
||||
|
||||
### [Firebase](https://firebase.google.com/)
|
||||
|
||||
Install the Firebase CLI if you haven’t already by running `npm install -g firebase-tools`. Sign up for a [Firebase account](https://console.firebase.google.com/) 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`.
|
||||
|
||||
```sh
|
||||
=== 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](https://github.com/facebook/create-react-app/issues/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`.
|
||||
|
||||
```sh
|
||||
=== 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](https://firebase.google.com/docs/web/setup).
|
||||
|
||||
### [GitHub Pages](https://pages.github.com/)
|
||||
|
||||
> Note: this feature is available with `react-scripts@0.2.0` and higher.
|
||||
|
||||
#### Step 1: Add `homepage` to `package.json`
|
||||
|
||||
**The step below is important!**<br>
|
||||
**If you skip it, your app will not deploy correctly.**
|
||||
|
||||
Open your `package.json` and add a `homepage` field for your project:
|
||||
|
||||
```json
|
||||
"homepage": "https://myusername.github.io/my-app",
|
||||
```
|
||||
|
||||
or for a GitHub user page:
|
||||
|
||||
```json
|
||||
"homepage": "https://myusername.github.io",
|
||||
```
|
||||
|
||||
or for a custom domain page:
|
||||
|
||||
```json
|
||||
"homepage": "https://mywebsite.com",
|
||||
```
|
||||
|
||||
Create React App uses the `homepage` field to determine the root URL in the built HTML file.
|
||||
|
||||
#### Step 2: Install `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](https://myusername.github.io/my-app), run:
|
||||
|
||||
```sh
|
||||
npm install --save gh-pages
|
||||
```
|
||||
|
||||
Alternatively you may use `yarn`:
|
||||
|
||||
```sh
|
||||
yarn add gh-pages
|
||||
```
|
||||
|
||||
Add the following scripts in your `package.json`:
|
||||
|
||||
```diff
|
||||
"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:
|
||||
|
||||
1. First, change your repository's source branch to be any branch other than **master**.
|
||||
1. Additionally, tweak your `package.json` scripts to push deployments to **master**:
|
||||
|
||||
```diff
|
||||
"scripts": {
|
||||
"predeploy": "npm run build",
|
||||
- "deploy": "gh-pages -d build",
|
||||
+ "deploy": "gh-pages -b master -d build",
|
||||
```
|
||||
|
||||
#### Step 3: Deploy the site by running `npm run deploy`
|
||||
|
||||
Then run:
|
||||
|
||||
```sh
|
||||
npm run deploy
|
||||
```
|
||||
|
||||
#### Step 4: Ensure your project’s settings use `gh-pages`
|
||||
|
||||
Finally, make sure **GitHub Pages** option in your GitHub project settings is set to use the `gh-pages` branch:
|
||||
|
||||
<img src="http://i.imgur.com/HUjEr9l.png" width="500" alt="gh-pages branch setting">
|
||||
|
||||
#### Step 5: Optionally, configure the domain
|
||||
|
||||
You can configure a custom domain with GitHub Pages by adding a `CNAME` file to the `public/` folder.
|
||||
|
||||
Your CNAME file should look like this:
|
||||
|
||||
```
|
||||
mywebsite.com
|
||||
```
|
||||
|
||||
#### Notes on client-side routing
|
||||
|
||||
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:
|
||||
|
||||
- You could switch from using HTML5 history API to routing with hashes. If you use React Router, you can switch to `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](https://reacttraining.com/react-router/web/api/Router) about different history implementations in React Router.
|
||||
- Alternatively, you can use a trick to teach GitHub Pages to handle 404 by redirecting to your `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](https://github.com/rafrex/spa-github-pages).
|
||||
|
||||
#### Troubleshooting
|
||||
|
||||
##### "/dev/tty: No such a device or address"
|
||||
|
||||
If, when deploying, you get `/dev/tty: No such a device or address` or a similar error, try the following:
|
||||
|
||||
1. Create a new [Personal Access Token](https://github.com/settings/tokens)
|
||||
2. `git remote set-url origin https://<user>:<token>@github.com/<user>/<repo>` .
|
||||
3. Try `npm run deploy` again
|
||||
|
||||
##### "Cannot read property 'email' of null"
|
||||
|
||||
If, when deploying, you get `Cannot read property 'email' of null`, try the following:
|
||||
|
||||
1. `git config --global user.name '<your_name>'`
|
||||
2. `git config --global user.email '<your_email>'`
|
||||
3. Try `npm run deploy` again
|
||||
|
||||
### [Heroku](https://www.heroku.com/)
|
||||
|
||||
Use the [Heroku Buildpack for Create React App](https://github.com/mars/create-react-app-buildpack).<br>
|
||||
You can find instructions in [Deploying React with Zero Configuration](https://blog.heroku.com/deploying-react-with-zero-configuration).
|
||||
|
||||
#### Resolving Heroku Deployment Errors
|
||||
|
||||
Sometimes `npm run build` works locally but fails during deploy via Heroku. Following are the most common cases.
|
||||
|
||||
##### "Module not found: Error: Cannot resolve 'file' or 'directory'"
|
||||
|
||||
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.
|
||||
|
||||
##### "Could not find a required file."
|
||||
|
||||
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`.
|
||||
|
||||
### [Netlify](https://www.netlify.com/)
|
||||
|
||||
**To do a manual deploy to Netlify’s CDN:**
|
||||
|
||||
```sh
|
||||
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:
|
||||
|
||||
1. [Start a new netlify project](https://app.netlify.com/signup)
|
||||
2. Pick your Git hosting service and select your repository
|
||||
3. Click `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](https://zeit.co/now)
|
||||
|
||||
Now offers a zero-configuration single-command deployment. You can use `now` to deploy your app for free.
|
||||
|
||||
1. Install the `now` command-line tool either via the recommended [desktop tool](https://zeit.co/download) or via node with `npm install -g now`.
|
||||
|
||||
2. Build your app by running `npm run build`.
|
||||
|
||||
3. Move into the build directory by running `cd build`.
|
||||
|
||||
4. 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.](https://zeit.co/blog/unlimited-static)
|
||||
|
||||
### [S3](https://aws.amazon.com/s3) and [CloudFront](https://aws.amazon.com/cloudfront/)
|
||||
|
||||
See this [blog post](https://medium.com/@omgwtfmarc/deploying-create-react-app-to-s3-or-cloudfront-48dae4ce0af) on how to deploy your React app to Amazon Web Services S3 and CloudFront.
|
||||
|
||||
### [Surge](https://surge.sh/)
|
||||
|
||||
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:
|
||||
|
||||
```sh
|
||||
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](https://surge.sh/help/adding-a-200-page-for-client-side-routing).
|
||||
|
||||
@@ -65,20 +65,6 @@ You can find the most recent version of this guide [here](https://github.com/fac
|
||||
- [Offline-First Considerations](#offline-first-considerations)
|
||||
- [Progressive Web App Metadata](#progressive-web-app-metadata)
|
||||
- [Analyzing the Bundle Size](#analyzing-the-bundle-size)
|
||||
- [Deployment](#deployment)
|
||||
- [Static Server](#static-server)
|
||||
- [Other Solutions](#other-solutions)
|
||||
- [Serving Apps with Client-Side Routing](#serving-apps-with-client-side-routing)
|
||||
- [Building for Relative Paths](#building-for-relative-paths)
|
||||
- [Customizing Environment Variables for Arbitrary Build Environments](#customizing-environment-variables-for-arbitrary-build-environments)
|
||||
- [Azure](#azure)
|
||||
- [Firebase](#firebase)
|
||||
- [GitHub Pages](#github-pages)
|
||||
- [Heroku](#heroku)
|
||||
- [Netlify](#netlify)
|
||||
- [Now](#now)
|
||||
- [S3 and CloudFront](#s3-and-cloudfront)
|
||||
- [Surge](#surge)
|
||||
- [Advanced Configuration](#advanced-configuration)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [`npm start` doesn’t detect changes](#npm-start-doesnt-detect-changes)
|
||||
@@ -1500,460 +1486,6 @@ npm run build
|
||||
npm run analyze
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
`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.
|
||||
|
||||
### Static Server
|
||||
|
||||
For environments using [Node](https://nodejs.org/), the easiest way to handle this would be to install [serve](https://github.com/zeit/serve) and let it handle the rest:
|
||||
|
||||
```sh
|
||||
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](https://github.com/zeit/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:
|
||||
|
||||
```sh
|
||||
serve -h
|
||||
```
|
||||
|
||||
### Other Solutions
|
||||
|
||||
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](https://nodejs.org/) and [Express](http://expressjs.com/):
|
||||
|
||||
```javascript
|
||||
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.
|
||||
|
||||
### Serving Apps with Client-Side Routing
|
||||
|
||||
If you use routers that use the HTML5 [`pushState` history API](https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries) under the hood (for example, [React Router](https://github.com/ReactTraining/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:
|
||||
|
||||
```diff
|
||||
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](https://httpd.apache.org/), 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](http://tomcat.apache.org/), you need to follow [this Stack Overflow answer](https://stackoverflow.com/a/41249464/4878474).
|
||||
|
||||
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](#why-opt-in),
|
||||
a [service worker](https://developers.google.com/web/fundamentals/primers/service-workers/) 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](#npm-run-eject) and then modifying the
|
||||
[`navigateFallback`](https://github.com/GoogleChrome/sw-precache#navigatefallback-string)
|
||||
and [`navigateFallbackWhitelist`](https://github.com/GoogleChrome/sw-precache#navigatefallbackwhitelist-arrayregexp)
|
||||
options of the `SWPreachePlugin` [configuration](../config/webpack.config.prod.js).
|
||||
|
||||
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`](public/manifest.json) and change `start_url` to match the required URL scheme, for example:
|
||||
|
||||
```js
|
||||
"start_url": ".",
|
||||
```
|
||||
|
||||
### Building for Relative Paths
|
||||
|
||||
By default, Create React App produces a build assuming your app is hosted at the server root.<br>
|
||||
To override this, specify the `homepage` in your `package.json`, for example:
|
||||
|
||||
```js
|
||||
"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>`.<br>
|
||||
More information [here](https://reacttraining.com/react-router/web/api/BrowserRouter/basename-string).<br>
|
||||
<br>
|
||||
For example:
|
||||
|
||||
```js
|
||||
<BrowserRouter basename="/calendar"/>
|
||||
<Link to="/today"/> // renders <a href="/calendar/today">
|
||||
```
|
||||
|
||||
#### Serving the Same Build from Different Paths
|
||||
|
||||
> Note: this feature is available with `react-scripts@0.9.0` 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`:
|
||||
|
||||
```js
|
||||
"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.
|
||||
|
||||
### Customizing Environment Variables for Arbitrary Build Environments
|
||||
|
||||
You can create an arbitrary build environment by creating a custom `.env` file and loading it using [env-cmd](https://www.npmjs.com/package/env-cmd).
|
||||
|
||||
For example, to create a build environment for a staging environment:
|
||||
|
||||
1. Create a file called `.env.staging`
|
||||
1. Set environment variables as you would any other `.env` file (e.g. `REACT_APP_API_URL=http://api-staging.example.com`)
|
||||
1. Install [env-cmd](https://www.npmjs.com/package/env-cmd)
|
||||
```sh
|
||||
$ npm install env-cmd --save
|
||||
$ # or
|
||||
$ yarn add env-cmd
|
||||
```
|
||||
1. Add a new script to your `package.json`, building with your new environment:
|
||||
```json
|
||||
{
|
||||
"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.
|
||||
|
||||
### [Azure](https://azure.microsoft.com/)
|
||||
|
||||
See [this](https://medium.com/@to_pe/deploying-create-react-app-on-microsoft-azure-c0f6686a4321) blog post on how to deploy your React app to Microsoft Azure.
|
||||
|
||||
See [this](https://medium.com/@strid/host-create-react-app-on-azure-986bc40d5bf2#.pycfnafbg) blog post or [this](https://github.com/ulrikaugustsson/azure-appservice-static) repo for a way to use automatic deployment to Azure App Service.
|
||||
|
||||
### [Firebase](https://firebase.google.com/)
|
||||
|
||||
Install the Firebase CLI if you haven’t already by running `npm install -g firebase-tools`. Sign up for a [Firebase account](https://console.firebase.google.com/) 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`.
|
||||
|
||||
```sh
|
||||
=== 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](https://github.com/facebook/create-react-app/issues/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`.
|
||||
|
||||
```sh
|
||||
=== 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](https://firebase.google.com/docs/web/setup).
|
||||
|
||||
### [GitHub Pages](https://pages.github.com/)
|
||||
|
||||
> Note: this feature is available with `react-scripts@0.2.0` and higher.
|
||||
|
||||
#### Step 1: Add `homepage` to `package.json`
|
||||
|
||||
**The step below is important!**<br>
|
||||
**If you skip it, your app will not deploy correctly.**
|
||||
|
||||
Open your `package.json` and add a `homepage` field for your project:
|
||||
|
||||
```json
|
||||
"homepage": "https://myusername.github.io/my-app",
|
||||
```
|
||||
|
||||
or for a GitHub user page:
|
||||
|
||||
```json
|
||||
"homepage": "https://myusername.github.io",
|
||||
```
|
||||
|
||||
or for a custom domain page:
|
||||
|
||||
```json
|
||||
"homepage": "https://mywebsite.com",
|
||||
```
|
||||
|
||||
Create React App uses the `homepage` field to determine the root URL in the built HTML file.
|
||||
|
||||
#### Step 2: Install `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](https://myusername.github.io/my-app), run:
|
||||
|
||||
```sh
|
||||
npm install --save gh-pages
|
||||
```
|
||||
|
||||
Alternatively you may use `yarn`:
|
||||
|
||||
```sh
|
||||
yarn add gh-pages
|
||||
```
|
||||
|
||||
Add the following scripts in your `package.json`:
|
||||
|
||||
```diff
|
||||
"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:
|
||||
|
||||
1. First, change your repository's source branch to be any branch other than **master**.
|
||||
1. Additionally, tweak your `package.json` scripts to push deployments to **master**:
|
||||
|
||||
```diff
|
||||
"scripts": {
|
||||
"predeploy": "npm run build",
|
||||
- "deploy": "gh-pages -d build",
|
||||
+ "deploy": "gh-pages -b master -d build",
|
||||
```
|
||||
|
||||
#### Step 3: Deploy the site by running `npm run deploy`
|
||||
|
||||
Then run:
|
||||
|
||||
```sh
|
||||
npm run deploy
|
||||
```
|
||||
|
||||
#### Step 4: Ensure your project’s settings use `gh-pages`
|
||||
|
||||
Finally, make sure **GitHub Pages** option in your GitHub project settings is set to use the `gh-pages` branch:
|
||||
|
||||
<img src="http://i.imgur.com/HUjEr9l.png" width="500" alt="gh-pages branch setting">
|
||||
|
||||
#### Step 5: Optionally, configure the domain
|
||||
|
||||
You can configure a custom domain with GitHub Pages by adding a `CNAME` file to the `public/` folder.
|
||||
|
||||
Your CNAME file should look like this:
|
||||
|
||||
```
|
||||
mywebsite.com
|
||||
```
|
||||
|
||||
#### Notes on client-side routing
|
||||
|
||||
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:
|
||||
|
||||
- You could switch from using HTML5 history API to routing with hashes. If you use React Router, you can switch to `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](https://reacttraining.com/react-router/web/api/Router) about different history implementations in React Router.
|
||||
- Alternatively, you can use a trick to teach GitHub Pages to handle 404 by redirecting to your `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](https://github.com/rafrex/spa-github-pages).
|
||||
|
||||
#### Troubleshooting
|
||||
|
||||
##### "/dev/tty: No such a device or address"
|
||||
|
||||
If, when deploying, you get `/dev/tty: No such a device or address` or a similar error, try the following:
|
||||
|
||||
1. Create a new [Personal Access Token](https://github.com/settings/tokens)
|
||||
2. `git remote set-url origin https://<user>:<token>@github.com/<user>/<repo>` .
|
||||
3. Try `npm run deploy` again
|
||||
|
||||
##### "Cannot read property 'email' of null"
|
||||
|
||||
If, when deploying, you get `Cannot read property 'email' of null`, try the following:
|
||||
|
||||
1. `git config --global user.name '<your_name>'`
|
||||
2. `git config --global user.email '<your_email>'`
|
||||
3. Try `npm run deploy` again
|
||||
|
||||
### [Heroku](https://www.heroku.com/)
|
||||
|
||||
Use the [Heroku Buildpack for Create React App](https://github.com/mars/create-react-app-buildpack).<br>
|
||||
You can find instructions in [Deploying React with Zero Configuration](https://blog.heroku.com/deploying-react-with-zero-configuration).
|
||||
|
||||
#### Resolving Heroku Deployment Errors
|
||||
|
||||
Sometimes `npm run build` works locally but fails during deploy via Heroku. Following are the most common cases.
|
||||
|
||||
##### "Module not found: Error: Cannot resolve 'file' or 'directory'"
|
||||
|
||||
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.
|
||||
|
||||
##### "Could not find a required file."
|
||||
|
||||
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`.
|
||||
|
||||
### [Netlify](https://www.netlify.com/)
|
||||
|
||||
**To do a manual deploy to Netlify’s CDN:**
|
||||
|
||||
```sh
|
||||
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:
|
||||
|
||||
1. [Start a new netlify project](https://app.netlify.com/signup)
|
||||
2. Pick your Git hosting service and select your repository
|
||||
3. Click `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](https://zeit.co/now)
|
||||
|
||||
Now offers a zero-configuration single-command deployment. You can use `now` to deploy your app for free.
|
||||
|
||||
1. Install the `now` command-line tool either via the recommended [desktop tool](https://zeit.co/download) or via node with `npm install -g now`.
|
||||
|
||||
2. Build your app by running `npm run build`.
|
||||
|
||||
3. Move into the build directory by running `cd build`.
|
||||
|
||||
4. 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.](https://zeit.co/blog/unlimited-static)
|
||||
|
||||
### [S3](https://aws.amazon.com/s3) and [CloudFront](https://aws.amazon.com/cloudfront/)
|
||||
|
||||
See this [blog post](https://medium.com/@omgwtfmarc/deploying-create-react-app-to-s3-or-cloudfront-48dae4ce0af) on how to deploy your React app to Amazon Web Services S3 and CloudFront.
|
||||
|
||||
### [Surge](https://surge.sh/)
|
||||
|
||||
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:
|
||||
|
||||
```sh
|
||||
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](https://surge.sh/help/adding-a-200-page-for-client-side-routing).
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
You can adjust various development and production settings by setting environment variables in your shell or with [.env](#adding-development-environment-variables-in-env).
|
||||
|
||||
Reference in New Issue
Block a user