I am currently deploying a django + react app on amazon aws using zappa.
Django is used as a restful api in combination with the DRF. React is hosted by django, i.e. django has a route that sends the index.html file of React as a response to all none-api URLs.
The page works as intended as long as I navigate on the page via clicking. However, when I refresh the page I do always get a 404 error. Why is this? The URL that I am located on when refreshing the page is like this:
myDomainName/currentPath
When I refresh the page, an immediate redirect is caused and the new request is made to:
myDomainName/stageName/currentPath
Therefore, the URL that I see in the browser search bar when everything is done loading is:
myDomainName/stageName/currentPath instead of myDomainName/currentPath.
As react does not know this URL with the prepended stageName, it raises a 404 error.
My question is: How can I make sure that the URL after loading is of form myDomainName/currentPath?
I think the redirect of CloudFront must happen, as its origin is simply located at path: /stageName/currentPath. Thus, I cannot change anything here.
Note: Once this problem happened once on a specific page, the next refresh works correctly as CloudFront uses cached data.
Another solution that I thought of is changing the behaviour of CloudFront. First, the request made by the user by refreshing the page is sent to CloudFront. CloudFront then prepends the stage name of the origin (the stage name identifies different origins). If CloudFront makes a request to the origin with this new pathname, everything works well at the origin. When CloudFront receives the response from the origin it could forward the data it received from the origin to the client, but to the URL requested by the user. CloudFront in turn only works as a proxy.
Any advice is warmly welcome, as it is very frustrating to have a fully functional page, which does not work correctly on page refresh.
Cheers
Without seeing your exact code and how your file structure is set up, it is difficult to give a comprehensive answer, especially because there are so many different ways to set up Django + React to work together.
However two of the most common ways are:
(A) Deploy a standalone React app on its own server, usually using Node + Express, but deploy a second standalone Django project with a
DjangoRestFrameworkAPI to model and interact with your database (usually usingfetchor some other ajax library to communicate between the two). This is the method of choice if you are most familiar with React and want to predominantly utilise React and Node features, but a downside is you lose a lot of Django functionality like its built-in Auth capabilities.(B) Deploy a Django project, but use
WebpackandBabelin combination with React to build a dynamic javascript file that 'takes over' the frontend functionality. This is the method of choice if you are most familiar with Django and want as many of its built-in features as possible (like Auth), but you want to use a Javascript framework (like React) to build your frontend. This method usually still usesDRFandfetchfor interactions, but Django is serving the site rather than a standalone Node server.It sounds like your project is closer to (B) than (A), so the below fixes which I have used before may help you with your URL issues, especially if you are using
react-routerwhich does not work nicely out of the box with Django urls:The key line by far is
path('<path:path>/', index, name='frontend_index_with_path')inside our urls.py file: it should stop your 404 error when you refresh. What happens is Django interprets the URL string sent exactly as is, and without that line it cannot map the URL to a view (because Django cannot natively interact withreact-router). So this path:path is essentially a dummy variable that always dispatches the index.html file regardless of the URL string, allowing react-router to take control from there.SaaSPegasus has much more information on both this trick and other common issues when integrating Django + React.
I also recommend the Tech with Tim tutorial series on this, but please note he uses an old version of React Router which may not be compatible with your build.
Hope this helps