Search code examples
nginxreactjsreact-routercherrypy

How can I configure react-router to with nginx/cherrypy and my current reactjs app


I have a working web app served by nginx with cherrypy in the backend and ReactJS for the front-end.

The app grew so I want to use react-router to provide quick access to pages with URLs. For example I want that my.domain.name/user will get the part in my app that manages user.

My single index.html includes the js bundle like this: <script src="/js/bundle.js"></script>

Until now my app started by rendering AppMain. Now, I created a NoMatch class and I've put both into a react-router, like this:

ReactDOM.render((
    <Router history={browserHistory}>
        <Route path="/" component={AppMain}>
            <Route path="*" component={NoMatch}/>
        </Route>
    </Router>
), document.getElementById('main-central'));

When trying this it worked nicely. Using http://my.domain.name gave me the app as before. But thoeritcally now trying http://my.domain.name/whatever should have renderred whatever NoMatch is rendering. But instead I get the nginx 404 page.

So I believe an nginx-side configuration is needed but maybe not only (which is why I brought the entire story above).

Nginx configuration (http part) looks like this:

upstream app_servers {
    server 127.0.0.1:9988;
}

# Configuration for Nginx
server {

    location / {
        root /var/www;
        index index.html;
    }

    # Proxy connections to the application servers
    # app_servers
    location /api {
        proxy_pass         http://app_servers/api;
        proxy_redirect     off;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
    }
}

As you can see cherrypy is getting all /api/* paths.

I have static content under /css, /img etc that I want to be served properly.

So I need everything not static and not /api to go to js/bundle.js

How do I configure that in nginx? Do I need to do something in cherrypy or javascript differently?

Thanks in advance.


Solution

  • Found my own answer... Here is is:

    Basically nginx configuration needed redirect urls to /index.html (not to my bundle.js, of course)

    The addition of try_files in nginx conf takes care of that:

    location / {
        root /var/www;
        index index.html;
    
        try_files $uri $uri/ /index.html;
    }
    

    Additionally I modified the router's main rednering:

    ReactDOM.render(
        (<Router history={browserHistory}>
            <Route path="/" component={AppMainNewNav}>
                <Route path="users" component={UsersPage}/>
                <Route path="about" component={About}/>
            </Route>
            <Route path="*" component={NoMatch}/>
        </Router>)
        , document.getElementById('navbar'));
    

    And in AppMainNewNav render() I modified the navigation to something like this:

    <nav>
        <ul role="nav">
            <li><Link to="/videos">Videos</Link></li>
            <li><Link to="/about">About</Link></li>
        </ul>
    </nav>