Home > Enterprise >  NGINX: replacing React router hash routes
NGINX: replacing React router hash routes

Time:08-09

I have following nginx config:

server {
    server_name dev.example.com;
    root /home/example/develop/frontend/build;

    location / {
        rewrite ^/#(.*)$ $1 last;  # for some reason this is not working
        try_files $uri $uri/ /index.html;
    }

    location ~ .(static)/(js|css|media)/(. )$ {
        try_files $uri $uri/ /$1/$2/$3;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/dev.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/dev.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

I've changed from React HashRouter to BrowserRouter, so I had to add those 2 location entries. Some of the links outside application are already generated, so I would like to redirect all hash urls to standard browser urls to make my app backward compatible, e.g.:

https://dev.example.com/#/somepage/123123

should be changed (or should redirect) to:

https://dev.example.com/somepage/123123

For some reason, none of the rewrite rules I have written seems to work.

CodePudding user response:

As @RichardSmith mention in comment, everything after # is processed by a browser, so it is never sent to the NGINX.

I've managed to solve this issue on the app client side.

My app routing looks like this:

<BrowserRouter>
    <UserContextProvider>
        <React.Suspense fallback={ loading }>
            <Switch>
                {/* routes */ }
            </Switch>
        </React.Suspense>
    </UserContextProvider>
</BrowserRouter>

Solution:

In UserContextProvider I've placed following code:

useEffect(() => {
    if (location.hash.startsWith('#/')) { // checking if it's HashRoute
        history.replace({
            pathname: location.hash.replace(/#\/(.*)/, '$1'), // skipping `#/`
        })
    }
}, [])

After this change all the # routes are "translated" into BrowserRoutes and it works as expected, what means that my app is backward compatible with previously used HashRouter.

  • Related