2

Foreword

I am building an application that will use React for a static frontend paired with a graphql backend all behind nginx. I am trying to use nginx as a static file server for the React app and as a reverse proxy for my graphql api. One docker container holds the nginx server and React files, the other docker container runs the graphql api.

Problem

I am having a problem getting React to work correctly on the browser when served behind nginx.

All of the files are accessible and I am getting 200 OKs for all of the requests, but for some reason it seems that react can't find/load static assets. For example none of the css is loading, the javascript seems to run because I am not getting the default message when the bundle can't be located. I have even tried cURLing all of the static assets that react could be fetching (successfully). Still, however, none of the css, svgs, or images want to load.

I am running a completely untouched create-react-app. I have run the exact same app via the development server and it works as expected, I even downloaded zeit/serve and ran that static file server successfully.

I have been looking up SO posts, read CRA - deployment, tried modifying "start_url" and "homepage" CRA variables, but can not seem to find the issue. I can probably run zeit/serve in another docker container and just reverse proxy to it via nginx but would prefer not to since nginx should be more than capable of serving these react files.

Here are a couple screenshots/configurations that may be useful. If there are any pointers/guesses I would be more than happy to try them out. If you would like any other screenshots or files uploaded that would be useful to give me a pointer just let me know.

Request/Response to nginx server enter image description here

nginx.conf

events {

}

http {
  server {
    listen 80;
    index index.html;
    root /app;

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

    location /api {
      rewrite ^/api(.*)$ / break;
      proxy_pass http://lab1_api:4000;
    }
  }
}

index.html

<!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"/>
        <meta name="description" content="Web site created using create-react-app"/>
        <link rel="apple-touch-icon" href="logo192.png"/>
        <link rel="manifest" href="./manifest.json"/>
        <title>React App</title>
        <link href="./static/css/main.dfca195d.chunk.css" rel="stylesheet">
    </head>
    <body>
        <noscript>You need to enable JavaScript to run this app.</noscript>
        <div id="root"></div>
        <script>
            !function(i) {
                function e(e) {
                    for (var r, t, n = e[0], o = e[1], u = e[2], f = 0, l = []; f < n.length; f++)
                        t = n[f],
                        Object.prototype.hasOwnProperty.call(p, t) && p[t] && l.push(p[t][0]),
                        p[t] = 0;
                    for (r in o)
                        Object.prototype.hasOwnProperty.call(o, r) && (i[r] = o[r]);
                    for (s && s(e); l.length; )
                        l.shift()();
                    return c.push.apply(c, u || []),
                    a()
                }
                function a() {
                    for (var e, r = 0; r < c.length; r++) {
                        for (var t = c[r], n = !0, o = 1; o < t.length; o++) {
                            var u = t[o];
                            0 !== p[u] && (n = !1)
                        }
                        n && (c.splice(r--, 1),
                        e = f(f.s = t[0]))
                    }
                    return e
                }
                var t = {}
                  , p = {
                    1: 0
                }
                  , c = [];
                function f(e) {
                    if (t[e])
                        return t[e].exports;
                    var r = t[e] = {
                        i: e,
                        l: !1,
                        exports: {}
                    };
                    return i[e].call(r.exports, r, r.exports, f),
                    r.l = !0,
                    r.exports
                }
                f.m = i,
                f.c = t,
                f.d = function(e, r, t) {
                    f.o(e, r) || Object.defineProperty(e, r, {
                        enumerable: !0,
                        get: t
                    })
                }
                ,
                f.r = function(e) {
                    "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {
                        value: "Module"
                    }),
                    Object.defineProperty(e, "__esModule", {
                        value: !0
                    })
                }
                ,
                f.t = function(r, e) {
                    if (1 & e && (r = f(r)),
                    8 & e)
                        return r;
                    if (4 & e && "object" == typeof r && r && r.__esModule)
                        return r;
                    var t = Object.create(null);
                    if (f.r(t),
                    Object.defineProperty(t, "default", {
                        enumerable: !0,
                        value: r
                    }),
                    2 & e && "string" != typeof r)
                        for (var n in r)
                            f.d(t, n, function(e) {
                                return r[e]
                            }
                            .bind(null, n));
                    return t
                }
                ,
                f.n = function(e) {
                    var r = e && e.__esModule ? function() {
                        return e.default
                    }
                    : function() {
                        return e
                    }
                    ;
                    return f.d(r, "a", r),
                    r
                }
                ,
                f.o = function(e, r) {
                    return Object.prototype.hasOwnProperty.call(e, r)
                }
                ,
                f.p = "./";
                var r = window.webpackJsonpfrontend = window.webpackJsonpfrontend || []
                  , n = r.push.bind(r);
                r.push = e,
                r = r.slice();
                for (var o = 0; o < r.length; o++)
                    e(r[o]);
                var s = n;
                a()
            }([])
        </script>
        <script src="./static/js/2.14750350.chunk.js"></script>
        <script src="./static/js/main.7811a2b9.chunk.js"></script>
    </body>
</html>

What it looks like (should be stock create-react-app)

  • This is the entire index.html landing page.
  • Notice the message being output to the screen, this indicates that the javascript is at least running or else would get default message.

enter image description here

project structure (host)

enter image description here

nginx docker container structure

enter image description here

7
  • Can you please post your project structure? Commented Sep 27, 2019 at 3:35
  • Added project structure of both my local os & the nginx docker container. Commented Sep 27, 2019 at 3:42
  • What do you see for file contents in browser console for the CSS file. Could it be possible that the file contents are corrupted, or corrupted contents are cached in browser. Commented Sep 27, 2019 at 4:01
  • Just diffed the css bundle from my browser with the one on my OS and they are identical. I have also cleared the cache and requested the app again a few times to no avail. From the first image I posted it also shows all 200 OK responses and no 304s indicating that it's not using the browser cache. @SujanAdiga Commented Sep 27, 2019 at 4:10
  • Which means there are no issues in your nginx setup which is serving the static files correctly. Commented Sep 27, 2019 at 4:14

1 Answer 1

2

I had a similar issue with nginx inside docker, I had to use include /etc/nginx/mime.types; which solved my issue.


events {
        worker_connections 768;
        # multi_accept on;
}

http {
    include /etc/nginx/mime.types;
    server {
        listen      80 default_server;

        root /usr/share/nginx/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        location / {
            try_files $uri /index.html;
        }
        
        location /api {
            proxy_pass http://localhost:5000;
        }

    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Great, worked for me! Wonder why this is not mentioned in the docs. That's hardly an exotic use case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.