Skip to content

Instantly share code, notes, and snippets.

@huangzhuolin
Last active October 9, 2024 19:52
Show Gist options
  • Save huangzhuolin/24f73163e3670b1cd327f2b357fd456a to your computer and use it in GitHub Desktop.
Save huangzhuolin/24f73163e3670b1cd327f2b357fd456a to your computer and use it in GitHub Desktop.
[Deploy create-react-app(react-router) with nginx] #react #nginx

Create-react-app

Create React apps with no build configuration.

Thanks to create-react-app. It's saves a lot of my time. I remember several months ago I had to setup a lot just for a react app, webpack, babel, test environment and so on... Fortunately, everything becomes easy now. Though you have many choices of start boiler plate, you worth trying this.

React router

If you are build a SPA with react, you probably use react-router. You should be clear that when we click on an internal link in our page, there's a little different from the traditional static web page:

  • In traditional static page, browser will send a request to nginx server for a new html page match that url.
  • In react-router, history will listen to the url of the browser, and when it changes, it will find for the proper component to render, and maybe send async request to ask for data.

For example, when we change to location /users, there is no file /users.html serve on nginx. The browser just changes the url and render some new component, bringing effect like "jump". For this reason, when a user start the page with the url /users, nginx should first tries to find /users.html. Of course it fails, and it will try to return index.html, and let the browser handle the rest.

Nginx config

Before deploy to nginx, we should run npm run build. If you deploy your app in the root of server, eg, example.com, everything just works well. Check the index.html file in the public folder, it will require the js/css file as /app.js. Here's the nginx config.

server {
    server_name example.com;
    ...
    
    location ~ / {
        root /var/www/example.com/static;
        try_files $uri /index.html;
    }
}

First nginx will try to find if exists an actual file in the static folder. If not, it is considered as front end url and return index.html, and let the browser handle the rest.

Deploy in subdirectory of nginx

I came with the special case that I have to deploy the application at the subdirectory of the server, eg, example.com/my_app. This time we have to do a little more work.

  1. because we change the url of our app(add /my_app as predix), we have to change our react-router's root from '/' to '/my_app'.

  2. Suppose that our static files's location is /var/www/example.com/static/my_app in server. You may notice that we add a folder my_app here, it's a little trick to match the static files in folder with url. We want to match all the request with prefix /my_app. Nginx config:

server {
    server_name example.com;
    ...
    
    location ~ /my_app {
        root /var/www/example.com/static;
        try_files $uri /my_app/index.html;
    }
}

For example, if nginx get a request for /my_app/app.js. Location /my_app is matched, this time the $uri in try_files is /my_app. So nginx will find /my_app/app.js in root var/www/example.com/static

After this you will figure that the index.html is loaded properly. But the js/css files required in index.html don't show up. Remember in index.html the other static files are written as href=/app.css, but now static files are not in root but the subdirectory /my_app. To fix this problem, we can add one line in package.json:

"homepage": "/my_app", 
# "homepage": '.' may work, just try

Run npm run build again. This time it's written as href=/my_app/app.css, and nginx know how to serve the proper static files.

Useful Links

@huangzhuolin
Copy link
Author

Hi,

Thanks for writing this up. I was just wondering about step 1 of Deploy to subdirectory. Is that covered by the homepage: in package.json or do you have to add something in App.js?

It's been a long time so I've forgot the details. Sorry for that. It's configured in package.json if I'm right. Please refer to this link: https://create-react-app.dev/docs/deployment/#serving-the-same-build-from-different-paths

@choutianxius
Copy link

I know this seems silly, but don't put the static files in the /root directory or the nginx program would have no access to the files (lol I did this and kept getting 500 internal server error)

@anazite
Copy link

anazite commented Oct 16, 2022

I know this seems silly, but don't put the static files in the /root directory or the nginx program would have no access to the files (lol I did this and kept getting 500 internal server error)

Man, You just saved my life, I was using /root/ and it keeps giving me the 500 response.
Thanks for that <3

@ch3rn1k
Copy link

ch3rn1k commented May 4, 2023

For someone who stucked with subdirectory 304 errors - working config:

location ^~ /my_app {
  alias /home/user/example.com/html/my_app/build;
  try_files $uri $uri/ /my_app/index.html;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment