React Router Configuration - Apache Http Server, Nginx, Tomcat

React Router Configuration - Apache Http Server, Nginx, Tomcat

learninjava
Apr 18, 2020 - ReactJS
 

Concept 

So, you are here after browsing through half of the internet searching about configuring react router or SPA in general for your production and could not get the actual idea on why its not working or what's the concept ?
Well! You are in the right place, sit tight, this is not just another react router configuration tutorial. We will explain what you dont find over the internet: The actual concepts of routing along with production ready configuration on three most famous servers: Apache HTTP Server, Nginx and Tomcat.
 

Client Side Vs Server Side Routing 

Why two routings required ? Why is this confusion ? Why cant we have only one ? Since SPA is client side application, why not only Client side routing works ? So many questions asked. Enough!!, Here are the answers,
See the below image, it shows how the routing works in Server side and Client side. As you can see, in a multi page application, a java web application for instance, the server refers to a configuration file. This configuration file could be a simple web.xml or if you are using a framework like Spring, it could be a applicationContext.xml file. No matter what framework you use or what configuration file you use, all it has is the routing information.
https://github.com/learninjavagithub/assets/raw/master/articles/react-router.jpg
When a user clicks on a link to navigate to another page, the routing information is looked up in the configuration file. Then server returns the target page and the user sees the new html page. Since server is taking care of the routing its called Server side routing.
Now compare this to the single page application. In this case, there is only a single page, index.html. The webserver always returns index.html for any routing. This is because all the code is in a single page. This is why all the SPA frameworks has their own routing frameworks. In react, its the react-router framework.
Such a client side routing works fine in development environment. But how can you make sure it works on a production server ? Since the production servers are created before SPA frameworks came in to usage, we need special instructions for them to work with newer frameworks. That means we need a combination of Server Side and Client Side Routings.
This is why when you directly push your code to production, you will see 404 Not Found error when you refresh. This is because when you refresh on a page with URL "/user", the server tries to find that route which will not be there in server configuration The basic gist of all this conversation is this very concept of combination of Server Side Routing and Client Side Routing. When you try to route to a page say "/user", the server tries to find that page. We need to fool the server by always directing it to index.html. Once we are inside index.html, our client side routing in SPA will take care of the rest.
See below for the production ready configurations that does exactly what is explained above.
 Remember!
  • You will need both Server Side and Client Side Routing for an SPA
  • You will see 404 Not Found errors if Server Side Routing is missing or misconfigured
  • Server should be configured to always serve index.html irrespective of route
  • We have configured react router on Create React App (CRA) scaffolding application. Let us see how to make it run on all three servers. Dont worry we have included the working application at the end. Check "Download Source" section.
    We are configuring server side configuration here, If you want to setup client side routing painlessly, head over to this easy to understand step by step tutorial - Create React App - React Router Setup
     

    HashRouter Vs BrowserRouter 

    There is enough information on what are the differences between HashRouter and BrowserRouter so we are not going to see the differences. However, we want you to understand which is used when and how they work. Think of HashRouter as a development environment routing. Although it can work on production, it appends a # in the URL which would not feel like production URLs.
    HashRouter uses history library and anchor blocks, also called as html bookmarks. This is the reason you dont need any server side configuration to make it working. But hold on, are you ok to have your URLs appended with an ugly #. Imagine you also have html bookmarks or anchor blocks in your pages. Then the URLs looks more uglier.
    This is where the BrowserRouter comes in. Although it requires server side routing to be setup for them to work properly. This is why we used BrowserRouter, to make your routing production ready.
    For your reference this is how our URLs would look like if HashRouter is used:
    http://localhost:8080/react-routing-config/#/dashboard
    http://localhost:8080/react-routing-config/#/user
    Not so pretty right !! Read on..
     Remember!
  • HashRouter requires no Server Side Routing but appends # characters to the URLs which does not look pretty on a production environment.
  • BrowserRouter requires Server Side Routing which is where everyone struggles to setup. But not any more, after you read through this tutorial
  •  

    Apache HTTP Server - 2.4.43 

    1. httpd.conf - default context location (/htdocs) :

     Remember!
  • First we need to enable LoadModule rewrite_module modules/mod_rewrite.so module for the configurations to work
  • loading...

    2. httpd.conf - custom context location (say, /react-routing-config) :

    This one is a bit tricky one, we need to tell your build tool to build with the context name and use that build instead. Also, we need to create a Virtual Host and add configuration using <Directory> tag. Here are the steps:
    a. Add basename as your context name in BrowserRouter tag
    loading...
    b. Add homepage in package.json
    loading...
    c. Finally, the httpd.conf configuration
    loading...

    3. .htaccess file

    loading...
    The -f, -d and -l flags represents file, directory and a symbolic link respectively. The configuration says that when you receive a request from index.html do nothing as its already in index.html, next follows the non index.html requests like "/user". In this case, we check if the request is not a file, directory or symbolic link, if so just direct them to index.html.
    Now, navigate to the dashboard screen and user screen and make sure you are not getting 404 errors when you refresh.
    https://github.com/learninjavagithub/assets/raw/master/articles/react-router-dashboard.jpg
    https://github.com/learninjavagithub/assets/raw/master/articles/react-router-user.jpg
     

    Nginx - 1.16.1 

    1. nginx.conf - default context location (/html) :

    This configuration is pretty simple. All we have to do is add try_files
    loading...

    2. nginx.conf - custom context location (say, /react-routing-config) :

    Build the application with the context name and add the required configuration on server. Here are the steps:
    a. Add basename as your context name in BrowserRouter tag
    loading...
    b. Add homepage in package.json
    loading...
    c. Finally, the nginx.conf configuration
    loading...
     

    Tomcat - 10.0.0 

    Tomcat configuration is a bit different than other two servers. Since Tomcat only serves a web application, we need to modify our application structure to look like the structure of a Java Web Application.

    Using <error-page> in web.xml :

    Create WEB-INF folder and create a web.xml file as below and proceed with the configurations. The idea is to redirect always to index.html when 404 error occurs.
    loading...

    Using rewrite.config and Valve :

    If for some reason you dont want to use error-page, there is another approach using rewrite.config file. It uses a tomcat feature called Valve. First remove the error-page tag from web.xml and Simply create a file as below and name it as rewrite.config. Place this file in WEB-INF folder.
    loading...
    In the tomcat server.xml, add the below config and proceed with the configurations.
    loading...

    1. Default context location (/ROOT) :

    This configuration is pretty simple. All we have to do is copy the application to the ROOT folder.

    2. Custom context location (say, /react-routing-config) :

    Build the application with the context name and deploy the application to Tomcat. Here are the steps:
    a. Add basename as your context name in BrowserRouter tag
    loading...
    b. Add homepage in package.json
    loading...
    c. Finally, deploy the application to react-routing-config directory in webapps
    Thats all folks !! Happy coding. If you feel this helped you, keep supporting us by   or  or  below or on the articles on social media.
     
    Like us on: