Lucas Cafieiro
Lucas Cafieiro

Reputation: 55

Nginx conflicts static files when serving multiple React apps

I'm currently trying to set up multiple projects of React Apps using Nginx. So far, whenever I had static files conflicting, I'd just copy everything from a folder into the other (yes, it's an awful solution, but it was working so far). The problem is that now I have multiple projects on the same server, and although the previous solution would still work, it wouldn't be long before it's a complete mess. I've looked up Stack Overflow and many websites, and I've come to a configuration that looks like what I want to do, but it's not working properly.

This is my nginx.conf file:

#user  nginx;
worker_processes  1;

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


events {
    worker_connections  1024;
}

http {
    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;
    #tcp_nopush     on;

    keepalive_timeout  65;

    server_names_hash_bucket_size 64;

    #gzip  on;

    index  index.html index.htm;

    map $http_referer $webroot {
        "/project1/main"            "/home/username/project1main/build";
        "/project1/admin"           "/home/username/project1admin/build";
        "/project2/main"            "/home/username/project2main/build";
        "/project2/admin"           "/home/username/project2admin/build";
    }

    include /etc/nginx/conf.d/*.conf;
}

This is my server.conf file:

server {
    listen    80;
    server_name gcloud-server;

    location /project1/main {
        alias      /home/username/project1main/build;
        try_files  $uri $uri/ /index.html =404;
    }
    location /project1/admin {
        alias      /home/username/project1admin/build;
        try_files  $uri $uri/ /index.html =404;
    }

    location /project2/main {
        alias      /home/username/project2main/build;
        try_files  $uri $uri/ /index.html =404;
    }
    location /project2/admin {
        alias      /home/username/project2admin/build;
        try_files  $uri $uri/ /index.html =404;
    }

    location /static {
        root       $webroot;
    }
}

Is there a way to solve this problem like this? Or am I stuck into setting one /static location in which I'll have to copy every single projects' static files?

Thanks in advance.

Upvotes: 0

Views: 1025

Answers (1)

Ivan Shatsky
Ivan Shatsky

Reputation: 15602

As far a I can remember how an alias directive worked, you came into the following problem. Lets assume you've got a /project1/main/some/path/file request:

    location /project1/main {
        alias      /home/username/project1main/build;
        # here our internal variables are:
        # $document_root = "/home/username/project1main/build"
        # $uri = "/project1/main/some/path/file"
        try_files  $uri $uri/ /index.html =404;
        # 1) try_files checks the existence of $document_root$uri physical file
        # this is "/home/username/project1main/build/project1/main/some/path/file"
        # which is absent
        # 2) try_files checks the existence of $document_root$uri/ directory
        # this is "/home/username/project1main/build/project1/main/some/path/file/"
        # which is absent
        # 3) you've got a 404 HTTP error
    }

This problem didn't happen when you are using a root directive, but alias works this way. What you can do is

    # use regex location match and capture URI suffix in a $1 variable
    location ~ /project1/main(.*) {
        alias      /home/username/project1main/build;
        # here our internal variables are:
        # $document_root = "/home/username/project1main/build"
        # $uri = "/project1/main/some/path/file"
        # $1 = "/some/path/file"
        try_files  $1 $1/index.html =404;
        # checked file is $document_root$1
        # this is "/home/username/project1main/build/some/path/file"
        # request would be served if this file exists
    }

Upvotes: 1

Related Questions