Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: February 10, 2025
Deploying a React app on an Nginx server provides a fast and efficient way to serve applications. Additionally, it also improves the performance and security of the application.
In this tutorial, we’ll explore how to deploy a React application created using create-react-app on an Nginx server. First, we’ll begin by preparing a production-ready build of the react application. Next, we’ll install and configure Nginx to serve the static files. Finally, we’ll implement optimization and security measures to ensure the deployment is fast and secure.
To begin, we create a new React application using create-react-app. Once the application is scaffolded, we compile it into optimized static files for production.
First, let’s generate the new React project:
$ npx create-react-app react-deploy
This creates a folder named react-deploy containing the project structure. Next, we navigate into the project directory:
$ cd react-deploy
At this stage, we have a functional React application ready for development.
Before deploying, let’s compile the application into static files optimized for production:
$ npm run build
> [email protected] build
> react-scripts build
...
Compiled successfully.
File sizes after gzip:
58.99 kB build/static/js/main.fb9dabe6.js
2.7 kB build/static/js/488.8960d093.chunk.js
515 B build/static/css/main.f855e6bc.css
The project was built assuming it is hosted at /.
You can control this with the homepage field in your package.json.
The build folder is ready to be deployed.
You may serve it with a static server:
npm install -g serve
serve -s build
Find out more about deployment here:
https://cra.link/deployment
This generates a build folder containing minified JavaScript, CSS, HTML, and static assets. Furthermore, the build process also replaces development-specific configurations with performance-oriented settings, reducing file sizes and improving load times.
Finally, let’s move the production build to Nginx’s default web directory:
$ sudo cp -r build /var/www/html
This ensures that Nginx serves the React app from /var/www/html/build.
With the React application’s build files on the server, we now install and configure Nginx to serve the content. Nginx’s efficiency in handling static files makes it an ideal choice for hosting SPAs.
Firstly, let’s begin by updating the server’s package list to ensure access to the latest software versions:
$ sudo apt update
Next, let’s install Nginx using the package manager:
$ sudo apt install nginx
Once installed, let’s start the Nginx service and enable it to launch automatically on system boot:
$ sudo systemctl start nginx
$ sudo systemctl enable nginx
Synchronizing state of nginx.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install enable nginx
Created symlink '/etc/systemd/system/multi-user.target.wants/nginx.service' → '/usr/lib/systemd/system/nginx.service'.
To verify Nginx is running, we can access the server’s IP address in a web browser.
If the server uses a firewall, we must allow traffic on HTTP (port 80) and HTTPS (port 443):
$ sudo ufw allow 'Nginx Full'
Rules updated
Rules updated (v6)
These rules ensure external requests to the React application are not blocked.
Nginx uses server blocks (similar to virtual hosts) to manage configurations for different applications. We create a dedicated configuration file to serve the React app.
Let’s open a new configuration file in the /etc/nginx/sites-available/ directory:
$ sudo nano /etc/nginx/sites-available/react-app
Further, we add the following configuration to the created file:
server {
listen 80;
server_name risingsegun.xyz www.risingsegun.xyz;
root /var/www/html/build;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
access_log /var/log/nginx/react-app.access.log;
error_log /var/log/nginx/react-app.error.log;
}
In the configuration, risingsegun.xyz is the domain. Additionally, the root ensures the path matches the directory where the React build files were copied. Finally, try_files directs Nginx to serve index.html for all routes, enabling client-side routing in SPAs.
Furthermore, let’s create a symbolic link from the sites-available directory to sites-enabled to activate the configuration:
$ sudo ln -s /etc/nginx/sites-available/react-app /etc/nginx/sites-enabled/
We then test the configuration for syntax errors:
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
As seen, the Nginx configuration is successful. Additionally, let’s reload Nginx to apply changes:
$ sudo systemctl reload nginx
The React application is now accessible via the server’s IP or domain (risingsegun.xyz).
With the React application now live, let’s optimize its performance and fortify security. These steps ensure faster load times, encrypted traffic, and protection against common vulnerabilities.
Gzip reduces file sizes during transfer, speeding up content delivery. Let’s open the Nginx configuration file for the React app:
$ sudo nano /etc/nginx/nginx.conf
Next, inside the http block, we uncomment the following under the gzip on; tag:
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
We save the file, test the configuration, and restart Nginx:
$ sudo nginx -t && sudo systemctl reload nginx
[sudo] password for kali:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
As seen, the Nginx configuration is successful.
Additionally, we encrypt traffic using free SSL/TLS certificates from Let’s Encrypt. Furthermore, let’s install Certbot and its Nginx plugin:
$ sudo apt install certbot python3-certbot-nginx -y
Additionally, let’s proceed to obtain and install the certificate:
$ sudo certbot --nginx -d risingsegun.xyz -d www.risingsegun.xyz
...
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for risingsegun.xyz
http-01 challenge for www.risingsegun.xyz
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost root for HTTPS
Deploying Certificate to VirtualHost risingsegun.xyz for HTTPS
Congratulations! You have successfully obtained and installed your certificates for:
risingsegun.xyz
www.risingsegun.xyz
Your certificates are saved at:
/etc/letsencrypt/live/risingsegun.xyz/fullchain.pem
/etc/letsencrypt/live/risingsegun.xyz/privkey.pem
Your certificate will expire on 2025-01-31. To obtain a new or updated certificate, run "certbot renew" either manually or with a cron job.
Let’s verify that Certbot auto-renews the SSL certificate before it expires:
$ sudo certbot renew --dry-run
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing these Certificates:
risingsegun.xyz
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Simulating renewal of an existing certificate for risingsegun.xyz
Performing the following challenges:
http-01 challenge for risingsegun.xyz
Waiting for verification...
Cleaning up challenges
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Your certificates are due for renewal, but this is a dry run.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Finally, let’s restart Nginx to apply the SSL configuration changes:
$ sudo systemctl restart nginx
Now, we can visit the React application on a browser.
In this article, we’ve successfully deployed a React application on an Nginx server, optimizing it for performance and security. We covered building the React app, installing and configuring Nginx, enabling gzip compression, and securing traffic with HTTPS.
With these steps, the application is now efficiently served with improved speed and security.
As always, the code is available over on GitHub.