How to Deploy React App on Aws S3
How to Deploy React App on AWS S3 Deploying a React application on Amazon S3 is one of the most efficient, cost-effective, and scalable methods for hosting static web applications in the cloud. As React continues to dominate the frontend development landscape, developers increasingly seek reliable, high-performance hosting solutions that require minimal maintenance. AWS S3 (Simple Storage Service)
How to Deploy React App on AWS S3
Deploying a React application on Amazon S3 is one of the most efficient, cost-effective, and scalable methods for hosting static web applications in the cloud. As React continues to dominate the frontend development landscape, developers increasingly seek reliable, high-performance hosting solutions that require minimal maintenance. AWS S3 (Simple Storage Service) provides exactly that: a secure, durable, and highly available object storage service that can serve static content like HTML, CSS, JavaScript, and media files with low latency and high throughput.
Unlike traditional server-based hosting, S3 eliminates the need to manage servers, apply patches, or scale infrastructure manually. Combined with AWS CloudFront for content delivery and Route 53 for custom domain routing, S3 becomes a powerful platform for modern web applications. This guide walks you through every step of deploying a React app to AWS S3from building the production bundle to configuring bucket policies, enabling static website hosting, and optimizing performance.
By the end of this tutorial, youll not only know how to deploy your React app successfully but also understand the underlying architecture, best practices, and troubleshooting techniques that ensure your application runs smoothly at scale.
Step-by-Step Guide
Prerequisites
Before you begin deploying your React app to AWS S3, ensure you have the following:
- A working React application built with Create React App (CRA), Vite, or any other React framework.
- An AWS account with access to S3, CloudFront, and Route 53 services (free tier eligible).
- A local development environment with Node.js and npm or yarn installed.
- A terminal or command-line interface (CLI) to run build and AWS CLI commands.
- Optional: AWS CLI installed and configured with appropriate credentials (recommended for advanced users).
If you dont have a React app ready, create a simple one using Create React App:
npx create-react-app my-react-app
cd my-react-app
npm start
Once your app runs locally, youre ready to proceed.
Step 1: Build Your React Application for Production
React applications are built as static files optimized for production. The build process bundles JavaScript, minifies assets, and generates an optimized folder structure ready for deployment.
In your project directory, run the following command:
npm run build
This command creates a new folder named build in your project root. Inside this folder, youll find:
index.htmlThe main HTML file that serves as the entry point.static/Contains bundled JavaScript, CSS, and media files with hashed filenames for cache busting.asset-manifest.jsonandmanifest.jsonMetadata files used by the browser and service workers.
Do not modify files in the build folder manually. This folder is auto-generated and should be treated as immutable. Always rebuild after making changes to your source code.
Step 2: Create an S3 Bucket
Log in to the AWS Management Console and navigate to the S3 service.
Click on Create bucket. Enter a globally unique bucket name. AWS S3 bucket names must:
- Be between 3 and 63 characters long.
- Contain only lowercase letters, numbers, dots (.), and hyphens (-).
- Not begin or end with a dot.
- Not contain consecutive dots.
For example: my-react-app-2024 or mycompany-frontend-prod.
Choose a region close to your primary audience to reduce latency. For global audiences, consider pairing S3 with CloudFront later.
Under Block Public Access, leave all settings enabled for now. Well adjust permissions in a later step.
Click Create bucket.
Step 3: Enable Static Website Hosting
After creating the bucket, select it from the bucket list. Go to the Properties tab and scroll down to Static website hosting.
Click Edit, then select Enable.
In the Index document field, enter: index.html
Leave the Error document field as index.html as well. This is critical for React Router applications, which rely on client-side routing. Without this, refreshing pages or navigating directly to deep links (e.g., /about) will return a 404 error.
Click Save changes.
A message will appear at the top of the page with your static website endpoint. It will look like:
http://my-react-app-2024.s3-website-us-east-1.amazonaws.com
Do not close this page. Youll need this URL to test your deployment.
Step 4: Configure Bucket Permissions
By default, S3 buckets block public access. Since were hosting a public website, we must allow public read access to the objects in the bucket.
Go to the Permissions tab and scroll down to Block Public Access. Click Edit.
Uncheck the box labeled Block all public access.
A warning will appear. Confirm by typing confirm and clicking Save changes.
Next, you need to attach a bucket policy that explicitly grants public read access. Go to the Permissions tab and click on Bucket Policy.
Paste the following JSON policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-react-app-2024/*"
}
]
}
Replace my-react-app-2024 with your actual bucket name.
Click Save.
This policy allows any user on the internet to read objects (files) in your bucket, which is required for your website to load properly.
Step 5: Upload Your Build Files to S3
Now, upload the contents of your build folder to the S3 bucket.
You can do this via the AWS Console, AWS CLI, or third-party tools like Cyberduck or S3 Browser.
Option A: Using AWS Console
In your S3 bucket, click Upload.
Select all files and folders inside your local build directory. You can drag and drop the entire folder.
Click Upload.
After upload completes, verify that index.html is at the root level of the bucket.
Option B: Using AWS CLI (Recommended for Automation)
If you have the AWS CLI installed and configured, navigate to your projects build folder and run:
aws s3 sync . s3://my-react-app-2024 --delete
This command synchronizes your local build folder with the S3 bucket, uploading new or modified files and deleting files in S3 that no longer exist locally. The --delete flag ensures your bucket stays in sync with your local build, preventing stale files from lingering.
For faster uploads and better reliability, especially with large apps, you can also add:
--acl public-read --cache-control "max-age=31536000"
These flags set the access control and caching headers automatically during upload.
Step 6: Test Your Deployment
Open your browser and navigate to the static website endpoint you noted earlier:
http://my-react-app-2024.s3-website-us-east-1.amazonaws.com
If everything is configured correctly, your React app should load without errors.
Test deep links: Append a route like /about or /dashboard to the URL. If the page loads correctly, your error document setup is working.
If you see a blank page or 403/404 errors, double-check:
- That
index.htmlis uploaded to the root. - That static website hosting is enabled.
- That the bucket policy allows public read access.
- That Block Public Access is disabled.
Step 7: (Optional) Connect a Custom Domain
To use your own domain (e.g., www.myreactapp.com), youll need to use Amazon Route 53 or another DNS provider.
Using Route 53
In the AWS Console, go to Route 53 and create a hosted zone for your domain (if not already created).
Create an A record that points to your S3 website endpoint:
- Name:
www(or @ for root domain) - Type: A
- Value: The S3 website endpoint (e.g.,
my-react-app-2024.s3-website-us-east-1.amazonaws.com)
Save the record. DNS propagation may take a few minutes to several hours.
Important Note
If youre using a root domain (e.g., myreactapp.com), S3 does not support naked domain static hosting directly. In this case, create two buckets:
myreactapp.comRedirects towww.myreactapp.comwww.myreactapp.comHosts your actual React app
Configure the first bucket for redirection:
- Enable static website hosting.
- Set Redirect all requests to to
www.myreactapp.com. - Set the protocol to HTTP or HTTPS based on your preference.
Then, set up the second bucket (www) as your main app bucket with static website hosting and custom domain as described above.
Step 8: Enable HTTPS with CloudFront (Highly Recommended)
While S3 supports HTTP, modern browsers require HTTPS for features like service workers, geolocation, and secure cookies. S3 static website endpoints do not support custom SSL certificates directly.
To enable HTTPS with your custom domain, use AWS CloudFront Amazons content delivery network (CDN).
In the AWS Console, go to CloudFront and click Create Distribution.
Under Origin Domain, select your S3 buckets website endpoint (not the REST endpoint). It should look like:
my-react-app-2024.s3-website-us-east-1.amazonaws.com
Set Origin ID to something descriptive, like MyReactAppS3.
Under Default Cache Behavior Settings:
- Set Viewer Protocol Policy to Redirect HTTP to HTTPS.
- Set Cache Policy to CachingOptimized.
- Set Origin Request Policy to OriginRequestAll.
Under Alternate Domain Names (CNAMEs), add your custom domain (e.g., www.myreactapp.com).
Under SSL Certificate, choose Request a certificate with ACM if you havent already. ACM (AWS Certificate Manager) will issue a free SSL certificate for your domain.
Wait for the certificate to be issued (may take 1030 minutes).
Once issued, select it in the CloudFront distribution settings.
Click Create Distribution.
CloudFront will take 515 minutes to deploy. Once active, your site will be accessible via HTTPS at your custom domain.
Update your DNS A record in Route 53 to point to your CloudFront distribution domain name (e.g., d12345.cloudfront.net) instead of the S3 endpoint.
After propagation, your React app will be served securely over HTTPS with global CDN caching.
Best Practices
Use Versioned Builds and CI/CD
Manually uploading files via the console is fine for testing, but for production, use automated deployment pipelines. Tools like GitHub Actions, AWS CodePipeline, or Bitbucket Pipelines can automatically build and deploy your app on every git push to the main branch.
Example GitHub Actions workflow:
name: Deploy React to S3
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm run build
- uses: jakejarvis/s3-sync-action@master
with:
args: --acl public-read --delete
env:
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: us-east-1
SOURCE_DIR: build/
This ensures consistent, repeatable deployments and eliminates human error.
Enable Compression
Enable Gzip or Brotli compression on your S3 files to reduce bandwidth and improve load times. React build outputs (JS and CSS files) compress well.
When using AWS CLI, add --content-encoding gzip to upload compressed files. Alternatively, configure CloudFront to automatically compress objects on delivery by enabling Compress Objects Automatically in the cache behavior settings.
Set Proper Cache Headers
React apps use hashed filenames (e.g., main.abc123.js) for cache busting. Set long cache expiration headers (1 year) on static assets and short or no caching on index.html.
In CloudFront, create two cache behaviors:
- Static Assets: Match
static/*? Cache policy:CachingOptimized? TTL: 1 year - Root Document: Match
index.html? Cache policy:CacheDisabled? TTL: 0 seconds
This ensures users always get the latest index.html while benefiting from long-term caching of static assets.
Use Environment Variables Wisely
Never hardcode API keys or secrets in your React app. Use environment variables prefixed with REACT_APP_ during build time. These are embedded into the bundle at compile time and cannot be changed at runtime.
For sensitive data, use a backend API with authentication (e.g., AWS API Gateway + Lambda) and avoid exposing secrets in client-side code.
Monitor Performance and Errors
Integrate monitoring tools like AWS CloudWatch Logs, Sentry, or Google Analytics to track user behavior, JavaScript errors, and page load performance.
Use Lighthouse in Chrome DevTools to audit your deployed app for accessibility, performance, and SEO best practices.
Secure Your Bucket and Avoid Over-Permissive Policies
While public read access is necessary for static hosting, avoid granting write access to anonymous users. Always use the minimal required permissions.
Regularly audit your bucket policies and IAM roles. Use AWS Config or AWS Trusted Advisor to detect misconfigurations.
Enable Versioning and Lifecycle Policies
Enable versioning on your S3 bucket to preserve previous builds. This allows you to roll back if a deployment fails.
Set up a lifecycle policy to automatically delete old versions after 3090 days to control storage costs.
Tools and Resources
Essential Tools
- AWS CLI Command-line interface for managing AWS services. Install via:
pip install awscli - aws-s3-sync Node.js tool for syncing local folders with S3. Install:
npm install -g aws-s3-sync - GitHub Actions Free CI/CD automation for deploying on git pushes.
- CloudFront CDN for global delivery, HTTPS, and caching.
- Route 53 AWS DNS service for custom domain mapping.
- ACM (AWS Certificate Manager) Free SSL/TLS certificates for HTTPS.
- Netlify or Vercel Alternative static hosts with built-in CI/CD and HTTPS (useful for comparison).
Useful Libraries and Scripts
For advanced deployments, consider these utilities:
- aws-sdk JavaScript SDK for programmatic S3 uploads in Node.js scripts.
- serverless Framework to deploy React apps with serverless backends (e.g., API Gateway + Lambda).
- react-snap Pre-renders React pages to static HTML for improved SEO (useful for marketing sites).
- dotenv Load environment variables from
.envfiles during build.
Documentation and References
- AWS S3 Static Website Hosting
- AWS CloudFront Documentation
- Create React App Deployment Guide
- AWS Free Tier Get started without cost for 12 months.
- GitHub Action for S3 Sync
Real Examples
Example 1: Personal Portfolio Site
A developer builds a React portfolio using Create React App with React Router for pages like /projects, /contact, and /about. They build the app locally, upload the build folder to an S3 bucket named john-doe-portfolio, enable static hosting, and set the index and error documents to index.html. They then configure CloudFront with a custom domain www.johndoe.dev and an ACM certificate. The site loads securely over HTTPS with global CDN caching. Page load time drops from 2.8s to 850ms after CloudFront implementation.
Example 2: Internal Dashboard for a Startup
A startup deploys a React-based analytics dashboard using Vite. The app uses environment variables for API endpoints. They set up a CI/CD pipeline on GitHub Actions that triggers on every merge to the main branch. The pipeline runs npm run build, then uses the s3-sync action to deploy to an S3 bucket named analytics-dashboard-prod. CloudFront is configured with a custom domain dashboard.company.com and strict caching policies: 1 year for assets, 0 for index.html. They enable S3 versioning and lifecycle rules to retain only the last 10 builds. Deployment time is reduced from 15 minutes (manual) to 90 seconds.
Example 3: E-commerce Landing Page
A marketing team creates a React landing page for a product launch. The page includes animations, a form, and embedded videos. They use a third-party tool to compress images and optimize assets before building. After deployment to S3, they notice slow load times on mobile. They enable CloudFront compression, set up a custom cache policy for images (6 months), and move static assets to an S3 bucket with reduced redundancy (S3 Standard-IA). Page speed score improves from 62 to 94 in Lighthouse.
FAQs
Why does my React app show a blank page after deploying to S3?
This usually happens when the index.html file is missing from the bucket root or static website hosting is not enabled. Double-check that the file is uploaded and that youre accessing the S3 website endpoint (not the REST endpoint). Also ensure your bucket policy allows public read access.
Why do I get 404 errors when refreshing on a React Router page?
React Router handles routing on the client side. When you refresh a page like /about, the browser requests /about from the server, but S3 doesnt have a file named about. To fix this, set the error document in S3 static website hosting to index.html. This tells S3 to serve index.html for any 404 request, allowing React Router to take over.
Do I need to use CloudFront?
You dont need CloudFront to deploy a React app on S3, but its highly recommended. CloudFront provides HTTPS support with custom domains, global caching, reduced latency, DDoS protection, and better performance. Without it, your site will only be accessible via HTTP on the S3 endpoint, which is not suitable for production.
Can I host multiple React apps on the same S3 bucket?
Technically yes, but its not recommended. Each S3 bucket should host one application to avoid confusion and simplify management. Instead, create separate buckets for each app (e.g., app1-prod, app2-prod) and use CloudFront distributions with different domain names or paths.
How much does it cost to host a React app on S3?
Hosting a small to medium React app on S3 typically costs less than $1 per month. S3 charges based on storage (GB/month), requests (GET/PUT), and data transfer. For example:
- Storage: 50 MB ? ~$0.0023/month
- Requests: 10,000 GETs ? ~$0.0004
- Data Transfer: 1 GB out ? ~$0.09
CloudFront adds minimal cost (~$0.085 per GB) but improves performance significantly. The AWS Free Tier covers 5 GB S3 storage and 15 GB data transfer per month for 12 months.
Can I use S3 to host a React app with authentication?
S3 is static hosting only. You cannot run server-side logic like user authentication directly on S3. However, you can integrate authentication using third-party services like AWS Cognito, Firebase Auth, or Auth0. Your React app can make API calls to authenticate users and store tokens in local storage or cookies. Use API Gateway + Lambda for protected backend endpoints.
How do I update my React app after deployment?
Rebuild your app locally with npm run build, then re-upload the contents of the build folder to S3. If using CI/CD, push your changes to the main branch and the pipeline will handle the deployment automatically. Always test the new build locally before deploying.
Is S3 secure for hosting React apps?
Yes, S3 is highly secure. AWS provides encryption at rest and in transit, access logging, and fine-grained permissions. As long as you follow best practices using HTTPS via CloudFront, avoiding public write permissions, and rotating credentials your app is as secure as any modern static site.
Conclusion
Deploying a React application on AWS S3 is a straightforward, scalable, and cost-efficient method for hosting static web apps. By combining S3s durability and availability with CloudFronts global CDN, Route 53s DNS management, and ACMs free SSL certificates, you can deliver high-performance applications to users worldwide with minimal operational overhead.
This tutorial has walked you through the complete process from building your React app to configuring bucket policies, enabling HTTPS, and automating deployments. Youve also learned critical best practices for caching, security, and performance optimization that ensure your app runs smoothly under real-world conditions.
Whether youre a solo developer launching a personal project or part of a team managing enterprise applications, mastering S3 deployment empowers you to ship faster, scale effortlessly, and reduce infrastructure complexity.
As you continue to build and deploy React applications, remember that the goal is not just to get your app online its to deliver a fast, secure, and reliable experience to every user. With AWS S3 and the tools outlined here, youre equipped to do exactly that.