Baeldung Pro – Ops – NPI EA (cat = Baeldung on Ops)
announcement - icon

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.

Partner – Orkes – NPI EA (cat=Kubernetes)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

1. Introduction

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.

2. Building the React Application

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.

2.1. Creating the React Application

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.

2.2. Generate a Production Build

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.

3. Install and Set Up Nginx

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.

3.1. Install Nginx

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.

3.2. Adjust Firewall Rules

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.

4. Configure Nginx to Serve the React App

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.

4.1. Create a Nginx Configuration File

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.

4.2. Enable the Configuration

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).

5. Enhancing Performance and Security

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.

5.1. Enable Gzip Compression

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.

5.2. Set Up HTTPS with Let’s Encrypt

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.

6. Conclusion

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.