Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React & nginx routing to subdirectory

Tags:

nginx

reactjs

Just started with using React. I have an app created with create-react-app which should be running on a sub-directory while making API calls to a different path.

React App:

location on server: /var/www/myapp/build

endpoint: https://foo.example.com/analytics

Data API endpoint: https://foo.example.com/api/data

Nginx setup

    location /analytics {
           root /var/www/myapp/build;
           try_files $uri /index.html;
    }

When setting "homepage":"https://foo.example.com/analytics" in the client's package.json, all the resource paths seem to be correct (i.e. https://foo.example.com/analytics/static/...), but when checking networking no request to .../api/data shows up in my browser's networking inspector and the app doesn't properly spawn.

Using absolute paths in the App's API call (fetch('https://foo.example.com/api/data') instead of fetch('/api/data')) doesn't seem to help, either.

When instead I set "homepage":"." in package.json and also change the Nginx config to serve the react build directory on server root, the app works.

server {
        root /var/www/myapp/build;
}

However, in this case, the app is also available under https://foo.example.com, which is something I don't want.

I strongly suspect this has to do with routing, but couldn't figure out how to fix it. So any help would be much appreciated!

--- Edit / Solution ---

I doubt it's the most straight forward solution, but the following setup works for me:

React App

In package.json, set "homepage":"./analytics" before running npm run build

Nginx config:

    location =  /analytics {

            root /var/www/myapp/build;
            try_files /index.html =404;
    }

    location ~ ^/analytics(.*) {

            root /var/www/myapp/build;
            try_files $1 $1/ /index.html =404;
    }

My understanding is that the initial setup using try_files $uri was looking for files in the root directory /var/www/myapp/build for the full uri rather than only the path that follows /analytics. E.g. when requesting ../analytics/css/styles.css it would check if a file (or directory) is available under /var/www/mayapp/build/analytics/css/styles.css which doesn't exist, so it kept serving the index.html as fallback. Hence the regex workaround.

Feedback to improve this solution still very welcome, though.

like image 423
citivin Avatar asked Nov 08 '18 11:11

citivin


People also ask

Is React for frontend?

React JS, commonly referred to as React is one frontend development framework, or to be more specific a library that has found a favorite with developers around the world.

Is React for HTML or JS?

To get an overview of what React is, you can write React code directly in HTML. But in order to use React in production, you need npm and Node.js installed.

What is React is used for?

The React. js framework is an open-source JavaScript framework and library developed by Facebook. It's used for building interactive user interfaces and web applications quickly and efficiently with significantly less code than you would with vanilla JavaScript.

Is React Java or JavaScript?

React is a JavaScript-based UI development library. Facebook and an open-source developer community run it. Although React is a library rather than a language, it is widely used in web development. The library first appeared in May 2013 and is now one of the most commonly used frontend libraries for web development.


1 Answers

I was struggling with the same problem. Finally I was able to solve it using official documentation and a combination of answers:

Assumptions:

  • Your React App is based on create-react-app package (you are using react-router-dom).
  • You are using Nginx and the root path is being used by another service (or even another React/Gatsby App which is my case).
  • You want to deploy the React App on a subdirectory and be able to serve all statics of your React App from that subdirectory.

React App Changes:

Based on official documentation.

  1. Update your BrowserRouter by adding a basename. Example: <BrowserRouter history={history} basename="/webapp">.
  2. Specify a homepage on your package.json. Example: "homepage": "/webapp".
  3. If you are referencing a static file by its relative path, you should add the subdirectory to that reference. Example: src="/static/logo/logo.png" becomes src="/webapp/static/logo/logo.png".

Nginx Changes:

location ^~ /webapp {
   alias /var/www/myapp/build;
   try_files $uri $uri/ /webapp/index.html;
}
like image 61
Juan García Avatar answered Sep 22 '22 06:09

Juan García