Deploying create-react-app to S3 and CloudFront
The new React CLI tool,
create-react-app, is helping front end developers finally focus on building applications, rather than configuring them. Gone are the days of searching through the dozens of boilerplate and starter apps to get off the ground. For the modest price of accepting Facebook’s opinionated (but sensible) configuration settings, you’re off to the races.
Once you’ve kicked off a new application,
npm run build will optimize, compile, and dump the static files required to serve your application in a
build directory. At this point, you’re free to host the contents of that directory wherever you like — and voila, your app is on the web. Please note: if your application depends on a client-side server, such as Express, this article is sadly not for you.
Within the README of an app created with
create-react-app, there are a number of helpful tips for how to deploy your application with a variety of tools: Github Pages, Heroku, Surge, and so on. We’ll walk through how to deploy to S3 and CloudFront on AWS.
Quickly — why deploy statically? I see two obvious wins:
- Ease. Deploying static files requires far fewer moving parts than an app with a server. There’s less to set up and less to maintain.
- Cost. Because there’s less to set up and maintain, the cost of deploying a static application can be dramatically cheaper.
Alrighty, lets hop to it.
Deploy to S3
- Create an account or sign in to the AWS Console: https://aws.amazon.com/
- Navigate to the S3 service and click
Create Bucket. Make up a clever name for your new bucket, then click
- Click on the newly-created bucket. Within the
Properties, open the
Static Website Hostingtab, and select
Enable website hosting. Fill in
index.htmlfor both the Index and Error Documents. By setting
index.htmlas the Error Document, we can allow something like
react-routerto handle routes outside of the root.
- Open the
Permissionstab, then select
Edit bucket policy. You may choose to do something more nuanced here, but a good starting point is to provide read-only permissions for anonymous users — a policy provided in the AWS examples. Make sure its your bucket name under the
- Add the contents of your
builddirectory to this bucket. This can be done by clicking on the bucket and clicking
Upload. That’s it! You can find the URL to your application back under the
Static Website Hostingtab, labeled
Bonus: Deploying with AWS CLI
You can streamline the deployment process with the AWS Command Line Interface. For example, you might write an npm script to run tests, build the application and push to your S3 bucket. Briefly:
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: us-west-2
Default output format [None]: json
- Create a bucket and deploy the app:
// create a bucket
$ aws s3 mb s3://bucket-name
// list buckets
$ aws s3 ls
// build and deploy the app
$ npm run build && aws s3 sync build/ s3://bucket-name
The deploy script above is as simple as it gets. It takes the contents of the build directory (produced by
npm run build) and replaces whatever is currently in your bucket with those contents. For a slightly more robust deployment pipeline, you may prefer to store the previous state of the application in another directory. You can then write a script to revert to a previous state, should you need to.
Other helpful CLI commands can be found here.
Note: at the time of writing, a bug exists that prevents Internet Explorer versions from utilizing the Error Document configuration with apps created with
create-react-app. One way around this issue is to use CloudFront.
Deploy to CloudFront
If it works on S3, why bother with CloudFront?
CloudFront is the Content Delivery Network (CDN) service offered by AWS. CDNs optimize for speed by pushing your content out to edge locations around the world, making it highly available around the globe. If your users are only local, the performance offered by S3 may be just fine.
- Select the
CloudFrontservice in the AWS console, click
Create Distribution, then under the
webdelivery method, click
- Select your Origin Settings. The
Origin Domain Namechoices pre-populate with S3 buckets. Selecting yours will also populate the
- Within the
Distribution Settings, set the
Default Root Objectto
- You may choose to further configure the distribution, but that’s enough to get the job done. Select
- Click the ID of your newly created distribution to reach its settings page, then click on the
Error Pagestab. Select
Create Custom Error Response.
Yesfor a custom error response, set
/index.htmlfor the response page path and
200: OKfor the response code. This custom error page in the CloudFront distribution is analogous to the Error Document on the S3 bucket (and will work on IE, too). When done, click
- That’s it! Give the deployment a handful of minutes, then check out your web app. You can find the URL on the distribution listings page, under the
Easy enough, right? As mentioned, you can tweak countless other settings, configure CNAMEs in CloudFront or use Route 53 for DNS service. At any rate, the choices made within
create-react-app suggest that static deployments are a preferred practice for React apps and here to stay. Do you prefer to configure anything differently? Let me know what and why in the comments.
Interested in a simple npm deploy script? This redux starter application (built with
create-react-app) utilizes one here.