Deploy Create-React-App on Nginx

Kwhitejr picture Kwhitejr · Oct 23, 2017 · Viewed 43.6k times · Source

I'm attempting to deploy my create-react-app SPA on a Digital Ocean droplet with Ubuntu 14.04 and Nginx. Per the static server deployment instructions, I can get it working when I run serve -s build -p 4000, but the app comes down as soon as I close the terminal. It is not clear to me from the create-react-app repo readme how to keep it running forever, similar to something like forever.

Without running serve, I get Nginx's 502 Bad Gateway error.

Nginx Conf

server {
  listen 80;
  server_name app.mydomain.com;
  root /srv/app-name;
  index index.html index.htm index.js;
  access_log /var/log/nginx/node-app.access.log;
  error_log /var/log/nginx/node-app.error.log;
  location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm|svg)$ {
    root   /srv/app-name/build;
  }
  location / {
    proxy_pass http://127.0.0.1:4000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Access-Control-Allow-Origin *;
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }
}

Answer

davidjb picture davidjb · Nov 27, 2017

One of the major benefits of React (and Create React App) is that you don't need the overhead of running a Node server (or proxying to it with Nginx); you can serve the static files directly.

From the Deployment documentation you've linked to, Create React App describes what to do:

npm run build creates a build directory with a production build of your app. Set up your favorite HTTP server so that a visitor to your site is served index.html, and requests to static paths like /static/js/main.<hash>.js are served with the contents of the /static/js/main.<hash>.js file.

In your case, run npm run build to create the build/ directory and then make the files available in a location Nginx can access them. Your build is probably best done on your local machine and then you can securely copy the files across to your server (via SCP, SFTP etc). You could run npm run build on your server, but if you do, resist the temptation to directly serve the build/ directory as the next time you run a build, clients could receive an inconsistent set of resources whilst you're building.

Whichever build method you choose, once your build/ directory is on your server, then check its permissions to ensure Nginx can read the files and configure your nginx.conf like so:

server {
  listen 80;
  server_name app.mydomain.com;
  root /srv/app-name;
  index index.html;
  # Other config you desire (TLS, logging, etc)...
  location / {
    try_files $uri /index.html;
  }
}

This configuration is based upon your files being in /srv/app-name. In short, the try_files directive attempts to load CSS/JS/images etc first and for all other URIs, loads the index.html file in your build, displaying your app.

For note, you should be deploying using HTTPS/SSL to serve it rather than with insecure HTTP on port 80. Certbot provides automatic HTTPS for Nginx with free Let's Encrypt certificates, if the cost or process of obtaining a certificate would otherwise hold you back.