Build & Deploy
Build
npm run build
creates a build
directory with a production build of your app. Inside the build/static
directory will be your JavaScript and CSS files. Each filename inside of build/static
will contain a unique hash of the file contents. This hash in the file name enables long term caching techniques.
When running a production build of freshly created Create React App application, there are a number of .js
files (called chunks) that are generated and placed in the build/static/js
directory:
main.[hash].chunk.js
- This is your application code.
App.js
, etc.
[number].[hash].chunk.js
- These files can either be vendor code, or code splitting chunks. Vendor code includes modules that you've imported from within
node_modules
. One of the potential advantages with splitting your vendor and application code is to enable long term caching techniques to improve application loading performance. Since vendor code tends to change less often than the actual application code, the browser will be able to cache them separately, and won't re-download them each time the app code changes.
runtime-main.[hash].js
- This is a small chunk of webpack runtime logic which is used to load and run your application. The contents of this will be embedded in your
build/index.html
file by default to save an additional network request. You can opt out of this by specifyingINLINE_RUNTIME_CHUNK=false
, which will load this chunk instead of embedding it in yourindex.html
.
If you're using code splitting to split up your application, this will create additional chunks in the build/static
folder as well.
Deploy
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 more information see the production build section of the Create React App documentation.
Static Server
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 -l
or --listen
flags:
serve -s build -l 4000
Run this command to get a full list of the options available:
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 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.
Serving Apps with Client-Side Routing
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.
Building for Relative Paths
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>
.
More information here.
For example:
<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
:
"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.
For example, to create a build environment for a staging environment:
- Create a file called
.env.staging
- Set environment variables as you would any other
.env
file (e.g.REACT_APP_API_URL=http://api-staging.example.com
) - Install env-cmd
$ npm install env-cmd --save
$ # or
$ yarn add env-cmd - Add a new script to your
package.json
, building with your new environment:{
"scripts": {
"build:staging": "env-cmd -f .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.
Static File Caching
Each file inside of the build/static
directory will have a unique hash appended to the filename that is generated based on the contents of the file, which allows you to use aggressive caching techniques to avoid the browser re-downloading your assets if the file contents haven't changed. If the contents of a file changes in a subsequent build, the filename hash that is generated will be different.
To deliver the best performance to your users, it's best practice to specify a Cache-Control
header for index.html
, as well as the files within build/static
. This header allows you to control the length of time that the browser as well as CDNs will cache your static assets. If you aren't familiar with what Cache-Control
does, see this article for a great introduction.
Using Cache-Control: max-age=31536000
for your build/static
assets, and Cache-Control: no-cache
for everything else is a safe and effective starting point that ensures your user's browser will always check for an updated index.html
file, and will cache all of the build/static
files for one year. Note that you can use the one year expiration on build/static
safely because the file contents hash is embedded into the filename.