Search code examples
reactjsangularnginxdocker-swarmnginx-reverse-proxy

Nginx fails to resolve Upstream React JS files and falls back to index.html


I have docker swarm setup for a website. The main website is in Angular and specific portion of the website is React application.

The swarm cluster has 3 services for 3 apps. Both Angular and React apps served through Nginx

  1. Angular App (https://mywebsite.com)
  2. React App (https://mywebsite.com/viewer)
  3. Spring Boot app with /api end points (https://mywebsite.com/api)

Primary Nginx config that serves the website and Spring boot and React apps served as upstreams. Below Nginx file shows 3 location blocks for 3 apps.

nginx.conf

user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events
{
  worker_connections 1024;
}

http
{
    upstream springboot
    {
        server springboot:8081;
    }

    upstream viewer
    {
      server viewer;
    }

   # Redirect all requests to HTTPS server
    server
    {
        listen 80;
        server_name mywebsite.com;

        # redirects http requests to https
        return 301 https://mywebsite.com$request_uri;
    }

  server
  {
    listen 443 ssl http2;
    server_name mywebsite.com;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_certificate /etc/nginx/certs/mywebsite_com.crt;
    ssl_certificate_key /etc/nginx/certs/mywebsite_com.key;
    ssl_trusted_certificate /etc/nginx/certs/mywebsite_com_truster_chain.crt;
    ssl_prefer_server_ciphers on;

    location /
    {
      #### Gzip Settings  ####
      gzip on;
      gzip_min_length   1100;
      gzip_vary         on;
      gzip_proxied      expired no-cache no-store private auth;
      gzip_types        text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
      gzip_comp_level   5;

      #### Serve Angular Application ####
      root /usr/share/nginx/html;
      try_files $uri $uri/ /index.html;
      add_header Cache-Control "no-store, no-cache, must-revalidate";
      proxy_http_version 1.1;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-Port $server_port;
    }

   location /viewer
    {
      proxy_pass http://viewer;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Host $host;
      proxy_set_header X-Forwarded-Server $host;
      proxy_set_header X-Forwarded-Port $server_port;
      proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /api
    {
      proxy_pass http://springboot;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Host $host;
      proxy_set_header X-Forwarded-Server $host;
      proxy_set_header X-Forwarded-Port $server_port;
      proxy_set_header X-Forwarded-Proto $scheme;
    }
  }

  include /etc/nginx/mime.types;
  default_type application/octet-stream;

  log_format main '$remote_addr - $remote_user [$time_local] "$request" '
  '$status $body_bytes_sent "$http_referer" '
  '"$http_user_agent" "$http_x_forwarded_for"';

  access_log /var/log/nginx/access.log main;
  sendfile on;
  keepalive_timeout 30m;
  include /etc/nginx/conf.d/*.conf;
}

nginx.conf (React)

server {
  listen 80;

  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
  }
  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
    root   /usr/share/nginx/html;
  }
}

The angular app and /api/ paths work fine. But when I try to go to https://mywebsite.com/viewer path, the JS files are being rendered. Only index.html file renders and rest of the JS files could not be found and falls back to index.html which of course fails

Error:

Uncaught SyntaxError: Unexpected token '<'.init-service-worker.js:1 
        
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec. vendors~app.bundle.9…07e3ba0a6ba969.js:1 
        
Uncaught SyntaxError: Unexpected token '<'

Solution

  • As it turns out the issue was with Nginx. Rewriting URL after /viewer/ fixed the issue

    rewrite ^/viewer(/.*)$ $1 break;
    

    here is the complete Nginx file

    server {
      listen 80;
    
      location / {
        rewrite ^/viewer(/.*)$ $1 break;
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
      }
      error_page   500 502 503 504  /50x.html;
      location = /50x.html {
        root   /usr/share/nginx/html;
      }
    }