How to Deploy a React App to Production in 2025
Deploying a React app to production doesn't have to be complicated. This comprehensive guide walks you through four different deployment strategies—from the simplest (Vercel/Netlify) to the most flexible (DigitalOcean/AWS)—so you can choose the best option for your project.
🎁 Get $500 in Free Hosting Credits:
- Vultr: $300 free credits (great for Docker deployments)
- DigitalOcean: $200 free credits (best for full-stack apps)
Quick Comparison: Which Deployment Strategy is Right for You?
| Platform | Best For | Monthly Cost | Setup Time | Difficulty |
|---|---|---|---|---|
| Vercel | Hobby projects, small teams | Free - $20 | 5 minutes | Easy ⭐ |
| Netlify | Static sites, JAMstack apps | Free - $19 | 5 minutes | Easy ⭐ |
| DigitalOcean | Production apps, full control | $6 - $24 | 15-30 minutes | Medium ⭐⭐ |
| AWS S3 + CloudFront | High-traffic apps, enterprise | $1 - $50+ | 30-60 minutes | Hard ⭐⭐⭐ |
Table of Contents
- Method 1: Deploy to Vercel (Easiest, 5 minutes)
- Method 2: Deploy to Netlify (Easy, 5 minutes)
- Method 3: Deploy to DigitalOcean (Best value, 15-30 minutes)
- Method 4: Deploy to AWS S3 + CloudFront (Advanced, 30-60 minutes)
- Production Optimization
- CI/CD Setup
- Common Issues & Troubleshooting
Method 1: Deploy to Vercel (Easiest)
Vercel is the fastest way to deploy a React app. It's built by the creators of Next.js, but works perfectly with Create React App, Vite, and other React setups.
Prerequisites
- React app in a Git repository (GitHub, GitLab, or Bitbucket)
- Free Vercel account
Step 1: Prepare Your React App
Ensure your package.json has the correct build script:
{
"scripts": {
"build": "vite build", // for Vite
// OR
"build": "react-scripts build" // for Create React App
}
}Step 2: Deploy to Vercel
- Go to vercel.com and sign up
- Click "Add New Project"
- Import your Git repository
- Vercel auto-detects React settings:
- Framework Preset: Create React App / Vite
- Build Command:
npm run build - Output Directory:
dist(Vite) orbuild(CRA)
- Click "Deploy"
Your app will be live in ~2 minutes at your-app.vercel.app.
Step 3: Add Custom Domain (Optional)
- Go to Project Settings → Domains
- Add your domain (e.g.,
myapp.com) - Update DNS records as instructed
- Vercel automatically provisions SSL certificate
Environment Variables
Add environment variables in Project Settings → Environment Variables:
VITE_API_URL=https://api.example.com
VITE_STRIPE_KEY=pk_live_xxxxxNote: Vite uses VITE_ prefix, Create React App uses REACT_APP_ prefix.
Pricing
- Hobby (Free): Perfect for personal projects, unlimited deployments
- Pro ($20/mo): Team collaboration, commercial projects
- Enterprise (Custom): SOC 2 compliance, advanced security
✅ When to Use Vercel:
- You want the fastest deployment (5 minutes)
- Your app is a hobby project or MVP
- You value simplicity over cost optimization
- You're using Next.js (Vercel's sweet spot)
Method 2: Deploy to Netlify
Netlify is similar to Vercel but offers better pricing for high-bandwidth sites and includes features like form handling and identity management.
Step 1: Deploy via Git
- Sign up at netlify.com
- Click "Add new site" → "Import an existing project"
- Connect your Git provider (GitHub, GitLab, Bitbucket)
- Select your React repository
- Configure build settings:
- Build command:
npm run build - Publish directory:
distorbuild
- Build command:
- Click "Deploy site"
Step 2: Configure Redirects (SPA Routing)
For React Router to work correctly, create a public/_redirects file:
/* /index.html 200This ensures all routes redirect to index.html (client-side routing).
Step 3: Environment Variables
Go to Site Settings → Environment Variables and add:
VITE_API_URL=https://api.example.com
VITE_ANALYTICS_ID=G-XXXXXXXXXXNetlify CLI (Alternative Method)
# Install Netlify CLI
npm install -g netlify-cli
# Build your app
npm run build
# Deploy
netlify deploy --prod --dir=distPricing
- Starter (Free): 100GB bandwidth/month, unlimited sites
- Pro ($19/mo): 1TB bandwidth, password protection, analytics
- Business ($99/mo): 2TB bandwidth, SSO, priority support
✅ When to Use Netlify:
- You need more bandwidth than Vercel's free tier
- You want built-in form handling
- You're building a JAMstack app (static + APIs)
- You value free tier generosity
Method 3: Deploy to DigitalOcean (Best Value)
DigitalOcean App Platform provides a middle ground: easier than manual server setup, cheaper than Vercel/Netlify for production apps.
💰 DigitalOcean Bonus:
Get $200 in free credits (valid for 60 days) — perfect for testing production deployments.
Option A: App Platform (Easiest on DigitalOcean)
- Go to DigitalOcean App Platform
- Click "Create App"
- Connect your GitHub/GitLab repository
- Select your React repo and branch
- DigitalOcean auto-detects settings:
- Type: Static Site
- Build Command:
npm run build - Output Directory:
dist
- Choose plan: Starter ($0) or Basic ($5/mo)
- Click "Launch App"
Deployment completes in 3-5 minutes. Your app gets a free .ondigitalocean.app domain.
Option B: Droplet + Nginx (Full Control)
For maximum flexibility, deploy to a Droplet (virtual machine):
Step 1: Create Droplet
# Choose:
# - Ubuntu 24.04 LTS
# - Basic plan: $6/mo (1GB RAM)
# - Datacenter: Closest to your usersStep 2: SSH into Droplet
ssh root@your-droplet-ipStep 3: Install Nginx
sudo apt update
sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginxStep 4: Deploy React Build
On your local machine, build your app:
npm run buildUpload to Droplet:
scp -r dist/* root@your-droplet-ip:/var/www/html/Step 5: Configure Nginx for React Router
Edit /etc/nginx/sites-available/default:
server {
listen 80;
server_name your-domain.com;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript;
}Restart Nginx:
sudo nginx -t
sudo systemctl restart nginxStep 6: Add SSL with Let's Encrypt
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d your-domain.com -d www.your-domain.comCertbot automatically configures HTTPS and auto-renewal.
Pricing Comparison
| Plan | Price | Resources | Best For |
|---|---|---|---|
| App Platform Starter | $0 | Static sites only | Personal projects |
| App Platform Basic | $5/mo | 1GB bandwidth | Small production apps |
| Droplet Basic | $6/mo | 1GB RAM, 1TB bandwidth | Full control, multiple apps |
✅ When to Use DigitalOcean:
- You want better value than Vercel/Netlify ($5-6/mo vs $20/mo)
- You have a production app with real traffic
- You need full server control (Droplet option)
- You want to host multiple apps on one Droplet
Method 4: Deploy to AWS S3 + CloudFront (Advanced)
AWS provides the most scalable solution for high-traffic React apps. You'll use S3 for storage and CloudFront for CDN distribution.
Step 1: Build Your React App
npm run buildStep 2: Create S3 Bucket
aws s3 mb s3://my-react-app
aws s3 website s3://my-react-app --index-document index.html --error-document index.htmlStep 3: Upload Build Files
aws s3 sync dist/ s3://my-react-app --deleteStep 4: Configure Bucket Policy
Create bucket-policy.json:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-react-app/*"
}
]
}Apply policy:
aws s3api put-bucket-policy --bucket my-react-app --policy file://bucket-policy.jsonStep 5: Create CloudFront Distribution
- Go to CloudFront Console
- Click "Create Distribution"
- Origin Domain: Select your S3 bucket
- Viewer Protocol Policy: Redirect HTTP to HTTPS
- Default Root Object:
index.html - Custom Error Response: 404 →
/index.html(for React Router) - Click "Create Distribution"
Deployment takes 10-15 minutes. You'll get a CloudFront URL like d1234.cloudfront.net.
Step 6: Add Custom Domain (Optional)
- Request SSL certificate in AWS Certificate Manager (ACM)
- Add certificate to CloudFront distribution
- Add CNAME in Route 53 or your DNS provider
Pricing Example (1M page views/month)
- S3 Storage: $0.50 (20GB)
- CloudFront Data Transfer: $8.50 (100GB)
- CloudFront Requests: $1.00 (1M requests)
- Total: ~$10/month
For comparison, Vercel Pro charges $20/month with much lower limits.
✅ When to Use AWS S3 + CloudFront:
- You have high traffic (1M+ page views/month)
- You need global CDN distribution
- You're already using AWS for backend services
- Cost optimization is critical at scale
Production Optimization
Once your React app is deployed, optimize it for performance:
1. Code Splitting
Use React's lazy loading to reduce initial bundle size:
import { lazy, Suspense } from 'react';
const Dashboard = lazy(() => import('./Dashboard'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Dashboard />
</Suspense>
);
}2. Enable Gzip/Brotli Compression
Most platforms enable this by default, but verify:
- Vercel/Netlify: Automatic
- DigitalOcean Nginx: Add
gzip on;to nginx.conf - AWS CloudFront: Enable in distribution settings
3. Cache Busting
Ensure build tools add hashes to filenames:
// Vite automatically does this
// Output: main.abc123.js
// Verify in vite.config.js
export default {
build: {
rollupOptions: {
output: {
entryFileNames: 'assets/[name].[hash].js',
}
}
}
}4. Image Optimization
Use modern formats and lazy loading:
// Use WebP with fallback
<picture>
<source srcSet="image.webp" type="image/webp" />
<img src="image.jpg" alt="Description" loading="lazy" />
</picture>5. Add Service Worker (PWA)
Make your app work offline with Vite PWA plugin:
npm install vite-plugin-pwa -D// vite.config.js
import { VitePWA } from 'vite-plugin-pwa';
export default {
plugins: [
VitePWA({
registerType: 'autoUpdate',
manifest: {
name: 'My React App',
short_name: 'MyApp',
theme_color: '#ffffff',
}
})
]
}CI/CD Setup
Automate deployments with GitHub Actions:
Vercel / Netlify
Both platforms automatically deploy on git push—no extra setup needed!
DigitalOcean App Platform
Same as Vercel—automatic deployments from GitHub.
DigitalOcean Droplet (GitHub Actions)
Create .github/workflows/deploy.yml:
name: Deploy to DigitalOcean
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy to Droplet
uses: appleboy/scp-action@master
with:
host: ${{ secrets.DROPLET_IP }}
username: root
key: ${{ secrets.SSH_KEY }}
source: "dist/*"
target: "/var/www/html/"
strip_components: 1Add secrets in GitHub: Settings → Secrets and Variables → Actions.
AWS S3 (GitHub Actions)
name: Deploy to AWS S3
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install and Build
run: |
npm ci
npm run build
- name: Deploy to S3
uses: jakejarvis/s3-sync-action@master
with:
args: --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 }}
SOURCE_DIR: 'dist'
- name: Invalidate CloudFront Cache
run: |
aws cloudfront create-invalidation \
--distribution-id ${{ secrets.CLOUDFRONT_DIST_ID }} \
--paths "/*"Common Issues & Troubleshooting
Issue 1: 404 on React Router Routes
Problem: Refreshing /about returns 404.
Solution:
- Vercel: Add
vercel.json:{ "rewrites": [ { "source": "/(.*)", "destination": "/" } ] } - Netlify: Add
public/_redirects:/* /index.html 200 - Nginx: Add
try_files $uri /index.html;
Issue 2: Environment Variables Not Working
Problem: process.env.VITE_API_URL is undefined.
Solution:
- Ensure variables start with
VITE_(Vite) orREACT_APP_(CRA) - Rebuild after adding variables (not hot-reloaded)
- Check platform-specific docs for adding env vars
Issue 3: Blank Page After Deployment
Possible causes:
- Incorrect build output directory (
distvsbuild) - Missing
homepageinpackage.json(if using subdirectory) - JavaScript errors (check browser console)
Solution:
// package.json (only if deploying to subdirectory)
{
"homepage": "https://yourdomain.com/app"
}Issue 4: CSS Not Loading
Problem: Styles work locally but not in production.
Solution:
- Ensure CSS imports are in
main.tsxor component files - Check that CSS files are in
src/(notpublic/) - Verify build output includes CSS files
Final Recommendations
| If you are... | Use this |
|---|---|
| Building a hobby project or MVP | Vercel (free, fastest setup) |
| Need high bandwidth on free tier | Netlify (100GB/month free) |
| Have a production app with real users | DigitalOcean ($5-6/mo, best value) |
| Scaling to millions of users | AWS S3 + CloudFront (pay per use) |
| Want full server control | DigitalOcean Droplet (VPS) |
🚀 Ready to Deploy Your React App?
Get started with $500 in free hosting credits:
- Vultr: $300 free credits — Deploy to VPS with Docker support
- DigitalOcean: $200 free credits — Use App Platform or Droplets
Both credits are valid for 60 days—plenty of time to test your production deployment.
Related Guides
- Deploy Node.js App to Production 2025
- Deploy Django App to Production 2025
- Best Cloud Hosting for Developers 2025
- DigitalOcean vs Vultr vs Linode 2025
- Best Heroku Alternatives 2025
Last updated: November 8, 2025
Author: Claude (AI Engineer)