How can I enable React client-side routing with NGINX and CloudPanel?

If you’re facing issues with getting the NGINX server settings right for client-side routing, this is the right place for you. Whether you’re working with a React app or an Angular application, these settings will resolve your routing issues.

First, let’s understand why client-side routing does not work with the default settings of an NGINX server.

Applications like React use JavaScript to load pages, so when JavaScript loads a page, it does so without needing the entire page to refresh. However, this behavior is not understood by the NGINX server. For example, if we want to open a page like “freeinvoice.live/about“, the browser will throw a 404 Page Not Found error. The reason for this error is that whenever the server receives a URL request, it tries to find the corresponding page file in the public folder. If the page, in this case “about,” is not found, it throws a 404 error. The server has no idea about client-side routing, and we cannot blame the server either, as it’s just following the standards it was built with.

What’s the solution then?

The simple solution is to tell the server that, no matter which URL is requested, it will serve only the index.html file. This resolves the problem because the index.html page contains all the code necessary to serve pages on the client side. Let’s have a look at the settings.

server {
    listen 80;
    listen [::]:80;
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    {{ssl_certificate_key}}
    {{ssl_certificate}}
    server_name example.com;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 80;
    listen [::]:80;
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    {{ssl_certificate_key}}
    {{ssl_certificate}}
    server_name www.example.com www1.example.com;
    {{root}}

    {{nginx_access_log}}
    {{nginx_error_log}}

    if ($scheme != "https") {
        rewrite ^ https://$host$uri permanent;
    }

    location ~ /.well-known {
        auth_basic off;
        allow all;
    }

    {{settings}}

    index index.html;

    location / {
        try_files $uri /index.html;
    }

    location ~* ^.+\.(css|js|jpg|jpeg|gif|png|ico|gz|svg|svgz|ttf|otf|woff|woff2|eot|mp4|ogg|ogv|webm|webp|zip|swf)$ {
        add_header Access-Control-Allow-Origin "*";
        expires max;
        access_log off;
    }

    location ~* ^.+\.(html|json|xml|txt)$ {
        try_files $uri =404;
    }

    location ~ /\. {
        deny all;
    }

    if (-f $request_filename) {
        break;
    }
}

Explaining everything in the settings file would be a waste of time for the current issue, as most of the settings are just defaults. However, the notable setting to focus on is:

location / {
        try_files $uri /index.html;
    }

This line of code tells the server to serve the index.html file for every requested URL.

How can I implement this?

The easiest way is to not overthink it. Simply take the entire setting I have provided, replace your domain details, and you’re good to go. Make sure you don’t miss anything while copying and pasting, as this could lead to errors. If you want to understand the server settings better, you can check out the official NGINX documentation page.

I hope this article has resolved your problem with client-side routing. If you have any doubts about the current solution, please leave a comment.

Leave a Comment

Your email address will not be published. Required fields are marked *