Make cowpte.com works
move the code there (done)
create a new client (done)
HashRouter
uses a hash symbol in the URL, which has the effect of all subsequent URL path content being ignored in the server request (ie you send “www.mywebsite.com/#/person/john” the server gets “www.mywebsite.com”. As a result the server will return the pre #
URL response, and then the post #
path will be handled by parsed by your client side react application.
BrowserRouter
will not append the #
symbol to your URL, however will create issues when you try to link to a page or reload a page. If the explicit route exists in your client react app, but not on your server, reloading and linking(anything that hits the server directly) will return 404 not found errors.
webpage navigating
refreshing the page
directly input the url
HashRoute
Server-side vs Client-side
The first big thing to understand about this is that there are now 2 places where the URL is interpreted, whereas there used to be only 1 in ‘the old days’. In the past, when life was simple, some user sent a request for http://example.com/about
to the server, which inspected the path part of the URL, determined the user was requesting the about page, and then sent back that page.
With client-side routing, which is what React Router provides, things are less simple. At first, the client does not have any JavaScript code loaded yet. So the very first request will always be to the server. That will then return a page that contains the needed script tags to load React and React Router, etc. Only when those scripts have loaded does phase 2 start. In phase 2, when the user clicks on the ‘About us’ navigation link, for example, the URL is changed locally only to http://example.com/about
(made possible by the History API), but no request to the server is made. Instead, React Router does its thing on the client-side, determines which React view to render, and renders it. Assuming your about page does not need to make any REST calls, it’s done already. You have transitioned from Home to About Us without any server request having fired.
So basically when you click a link, some JavaScript runs that manipulates the URL in the address bar, without causing a page refresh, which in turn causes React Router to perform a page transition on the client-side.
But now consider what happens if you copy-paste the URL in the address bar and e-mail it to a friend. Your friend has not loaded your website yet. In other words, she is still in phase 1. No React Router is running on her machine yet. So her browser will make a server request to http://example.com/about
.
And this is where your trouble starts. Until now, you could get away with just placing a static HTML at the webroot of your server. But that would give 404 errors for all other URLs when requested from the server. Those same URLs work fine on the client-side, because there React Router is doing the routing for you, but they fail on the server-side unless you make your server understand them.
Combining server- and client-side routing
If you want the http://example.com/about
URL to work on both the server- and the client-side, you need to set up routes for it on both the server- and the client-side. It makes sense, right?
Bypassing the problem altogether: Hash History
With Hash History, instead of Browser History, your URL for the about page would look something like this: http://example.com/#/about
The part after the hash (#
) symbol is not sent to the server. So the server only sees http://example.com/
and sends the index page as expected. React Router will pick up the #/about
part and show the correct page.
Downsides:
- ‘ugly’ URLs
- Server-side rendering is not possible with this approach. As far as search engine optimization (SEO) is concerned, your website consists of a single page with hardly any content on it.
What if we use Node.js as our server so we can run the same JavaScript code on both ends? Now, we have all our routes defined in a single react-router configuration and we don’t need to duplicate our rendering code. This is ‘the holy grail’ so to speak. The server sends the exact same markup as we would end up with if the page transition had happened on the client. This solution is optimal in terms of SEO.
you must use a Node.js based server.