I need to deploy a React App on AWS S3 using SSL and managing caching. What are the required steps, and what are some of the problems I might encounter?
Amazon Web Services has many innovative ways of hosting static websites and one of those is AWS S3. Today, we will learn how to deploy ReactJS app on AWS S3.
Why do this?
It can be incredibly fast, "serverless" and very inexpensive. Through the CloudFront global endpoints (edge locations), an application can run very quickly with high reliability. By setting another source origin, CloudFront can act as a reverse proxy to an API, eliminating cross-region (CORS) issues and accelerating API calls in distant locations. Multiple deployments can be uploaded to a single S3 bucket.
Basic Concepts
There are a number of concepts to keep in mind when deploying a Create React App to S3/CloudFront:
index.html
should be set for no-caching. These caching attributes can set through S3.Cross-domain API issues (CORS) - how to avoid
Each CloudFront distribution can have multiple origins. One origin should be set to S3, while the other can be set to an API server or load balancer. If the API server is within the AWS system, CloudFront can safely use non-SSL (port 80) to communicate as a proxy server.
To use port 80, the API server must be configured to respond to the non-secure traffic (if traffic is only port 80, no SSL certificate is required). The Apache VirtualHost will use the hostname of CloudFront instance not the API server hostname (e.g. my.react-app.com
not my.api.com
) because the HTTP request Host value is not modified.
To enable the API with CloudFront:
/api/*
path pattern, HTTPS only viewer policy, all HTTP methods (unless you have GET only), ALL
for Cache Based on Selected Request Headers, Compress Objects enabled, and Forward All for the query stringsCopying to S3
A simple way to copy your build system to S3 would be:
aws s3 sync . s3://MY-S3-BUCKET/ --quiet
This is quite limited. It will not manage browser caching easily. Old files can be removed (--delete
option) or maintained (default); of course this tool is agnostic to which CRA files should be maintained for older versions, so garbage collection will be complicated.
Python Tool for Deploying CRA to S3 / CloudFront
I built a python tool which will:
precache-manifest
files)Even if you don't use this, it may help you out with your deployment system.
Enabling React Router in CloudFront
To enable different paths in React Router, set the the CloudFront error page to be /index.html
(so that all failed requests will go there):
403: Forbidden
and 404: Not Found
pointing
/index.html
with HTTP response of 200
Testing HTTP headers
You can view this HTTP header if your S3 bucket is set for static website hosting (note S3 website hosting is not required for CloudFront to work):
curl -I http://MY-S3-ENDPOINT/index.html
Likewise you can test the header from CloudFront:
curl -I https://CLOUDFRONT-URL/index.html
To test compression, add encoding acceptance to the request HTTP header, e.g.
curl -H "Accept-Encoding: gzip" -I https://CLOUDFRONT-URL/index.html
Great question and answer @charlie-hileman, thanks for sharing! In regards to "some of the problems I might encounter", I was exploring the associated costs of this approach, and I thought it might help someone else coming to this question.
CloudFront docs:
No additional charge for the first 1,000 paths requested for invalidation each month. Thereafter, $0.005 per path requested for invalidation.
Easy formula, but tricky to factor without a real-world project.
Formula:
0.005 * ((files * deployments) - 1000)
My fairly modest create-react-app generates 202 files (a lot of which are webpack chunks due to the default chunking strategy). I'll round it down to 200 for easy maths. That means I get roughly five invalidations per month for free:
0.005 * ((200 * 5) - 1000) // $0.00
Beyond that, each deployment costs $1.
Let's scale that. Say I work roughly twenty days a month (five days a week, avg four weeks per month). At that rate, here's the cost if I deploy on average 1x day, 2x day, 3x...
0.005 * ((200 * 20 * 1) - 1000) // $15/mo
* 2 // $35/mo
* 3 // $55/mo
* 4 // $75/mo
* 5 // $95/mo
That's actually still relatively economical considering the benefits, now that I'm going into it understanding the costs. Plus, it might be an amortized cost if the project will stabilize and have fewer deployments over time. I would factor this against comparison operating costs of (for example) keeping a Node server up to host this project.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With