Score:0

Nginx React server will only look for static assets at root

cn flag

My react app works if nginx reverse-proxy is set as follows:

server {
    listen       80;
    server_name  my_public_vps_addr; 

    location / {
        proxy_pass      http://127.0.0.1:3000/;
    }
}

I can load the page correctly at http://my_public_vps_addr/.

But I want to access the site via http://my_public_vps_addr/ecapp/.

So I configured nginx:

server {
    listen       80;
    server_name  my_public_vps_addr; 

    location /ecapp/ {
        proxy_pass      http://127.0.0.1:3000/;
    }
}

Now if I load the page at http://my_public_vps_addr/ecapp/ and inspect the console I get:

GET http://my_public_vps_addr/static/js/bundle.js
[HTTP/1.1 404 Not Found 147ms]
GET http://my_public_vps_addr/static/js/0.chunk.js
[HTTP/1.1 404 Not Found 433ms]
GET http://my_public_vps_addr/static/js/main.chunk.js
[HTTP/1.1 404 Not Found 424ms]

I've identified a possible cause. The assets should be fetched from http://my_public_vps_addr/ecapp/static/js/bundle.js etc instead of http://my_public_vps_addr/static/js/bundle.js.

To fix this error, I will list relevant source code:

server.js

const express = require('express');
const compression = require('compression');
const path = require('path');
const app = express();

app.use(compression());
app.use(express.static(path.join(__dirname, 'build')));

app.get('*', function(req, res) {
    res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
    console.log(`App is running on port ${PORT}`);
});

I've tried app.use('/ecapp/static', express.static(path.join(__dirname, 'build'))); but no luck.

Routes.js

const Routes = () => {
    return (
        <BrowserRouter>
            <Switch>
                <Route path="/" exact component={Home} />
                ...
            </Switch>
        </BrowserRouter>
    );
};

I've tried <BrowserRouter basename='/ecapp'></BrowserRouter> but no luck.

I think the app will load correctly at http://my_public_vps_addr/ecapp/ if I can configure the page to look for assets at http://my_public_vps_addr/ecapp/static/*. I need help in doing this.

Ivan Shatsky avatar
gr flag
This is more SO than SF question. I'm not a React expert, but can suggest to check [How to deploy a React app to a subdirectory](https://medium.com/@svinkle/how-to-deploy-a-react-app-to-a-subdirectory-f694d46427c1) article, it helps some people with similar questions on SO to do what you are asking for.
rafawhs avatar
cn flag
If your nginx have complex configuration for location/cache rules, enable debug log docs.nginx.com/nginx/admin-guide/monitoring/logging and see which rule are being applied. I had the same problem and it was some conflict between js and html expiration settings.
Score:1
cn flag

I figured it out so I'm posting my solution here.

OBJECTIVE

To host create-react-app site at http://my_public_vps_addr:port/sub_path.

PROCEDURE

  1. in .env file: a) set NODE_ENV=production b) set PUBLIC_URL to http://my_public_vps_addr:port/sub_path
  2. set basename: <Router basename=’/sub_path’></Router>
  3. npm run build a) this generates static files inside build/ directory.
  4. Copy contents build/* to /var/www/sub_path/html/sub_path/
  5. cd to /var/www/sub_path/html/ a) sudo find . -type d -exec chmod 755 {} \; b) sudo find . -type f -exec chmod 644 {} \;
  6. touch /etc/nginx/sites-available/sub_path a) ln -s /etc/nginx/sites-available/sub_path /etc/nginx/sites-enabled/sub_path
  7. Content of /etc/nginx/sites-available/sub_path
    server {
      listen port;
      listen [::]:port;
      root /var/www/sub_path/html;
      index index.html index.htm index.nginx-debian.html;
      server_name my_public_vps_addr:port;
      location /sub_path {
        try_files $uri $uri/ /index.html =404
      }
    }
  1. Restart nginx service: a) sudo systemctl restart nginx.service
  2. Your site should be available from http://my_public_vps_addr:port/sub_path
  3. That’s it!
Ivan Shatsky avatar
gr flag
While in general this is the right approach, especially comparing to that one using `sub_filter`, your `try_files` directive isn't correct. The correct one is `try_files $uri $uri/ /sub_path/index.html` (or maybe even `try_files $uri /sub_path/index.html`).
Score:0
cn flag

I changed to:

location /ecapp/ {
        sub_filter '<script src="/static' '<script src="/ecapp/static';
        sub_filter_once off;
        proxy_set_header Accept-Encoding "";
        proxy_pass      http://127.0.0.1:3000;
}

And now view-source:http://my_public_vps_ip_addr/ecapp/ is:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <link rel="manifest" href="/manifest.json" />
    <link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
      integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
      crossorigin="anonymous"
    />
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  <script src="/ecapp/static/js/bundle.js"></script><script src="/ecapp/static/js/0.chunk.js"></script><script src="/ecapp/static/js/main.chunk.js"></script></body>
</html>

But then now loading http://my_public_vps_ip_addr/ecapp/ gives:

The script from “http://my_public_vps_addr/ecapp/static/js/bundle.js” was loaded even though its MIME type (“text/html”) is not a valid JavaScript MIME type.
...
Uncaught SyntaxError: expected expression, got '<'

http://my_public_vps_addr/ecapp/static/js/bundle.js etc return no content.

us flag
This is an approach that only gives headaches in the future. You need to configure your React application properly as indicated in the comments above.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.