Reputation: 131
I have a React frontend (made with create-react-app) and an Express backend, with a remote MySQL database. Everything works fine when I run both locally, serving the frontend on localhost:3000
and proxying http requests to localhost:3306
, which is also the port that the Express app listens on. Requests are made to localhost:3000/api/endpoint
, and again this works.
I'm now trying to move this setup over to production on my server. I'm using a shared server and Node is configured through Cpanel (although I do have SSH access). I'm not "running" the React side on the server the way I would in development, but rather have created build files and placed them in the directory corresponding to my domain homepage.
Let's say my domain is foo.com. I've been advised by my hosting company to run Node on port 50000 (as when I had tried 3306 it said it was already in use). Currently, every request to my API seems to result in a 404: it is attempting to query foo.com/api/endpoint
and failing. My question is: how do I properly direct these requests to my backend? I know that the proxy
option in React package.json isn't really meant to be used in production, so what should I use instead, and what should it be set to? Is there anything else I should expect to have to configure on the server?
Update
Ok, I'm now trying to bypass Cpanel's Node manager and run things manually. My document structure on the server is like this:
/home/user
|--- /project
| |--- /backend
| |--- (Node server.js, etc.)
| |--- /client
| |--- (React src, components, etc.)
|--- /public_html
|--- (React build files)
|--- .htaccess
I believe the React build files need to be in public_html
for the server to render them on my homepage. Hence, I am currently NOT serving the build files from my backend (although @MattCarlotta has suggested that I do this below; I am open to doing this if it seems necessary. The React app itself seems to run ok live at 3ecologies-seedbank.com; but perhaps I also need to tell the Node server about the public_html
location?).
Other resources have led me to think that part of the answer lies with the .htaccess
file. Mine currently looks like this (including some Cpanel-generated code):
# php -- BEGIN cPanel-generated handler, do not edit
# Set the “ea-php56” package as the default “PHP” programming language.
<IfModule mime_module>
AddHandler application/x-httpd-ea-php56 .php .php5 .phtml
</IfModule>
# php -- END cPanel-generated handler, do not edit
RewriteEngine On
RewriteRule ^/public_html$ http://127.0.0.1:50000/ [P,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/public_html/(.*)$ http://127.0.0.1:50000/$1 [P,L]
My rough understanding of what this should do is redirect requests from the pages at public_html
to my Node app, which is listening on port 50000
. This makes sense to me because when I run both the back and front locally, I need to proxy requests from localhost:3000
(front) to localhost:3306
(back).
I have started the Node app over SSH, with a simple node server.js
. It is able to confirm that it is listening on port 50000
and connects to the database. However, every request made to the API from the front-end still results in a 404
. It seems to still not be reaching the back-end.
If it helps, I'm on a shared server with Apache 2.4.41 and Cpanel 82.0 (build 17).
TL;DR
What is the production equivalent of setting a proxy
in React to send requests to a Node backend?
Upvotes: 0
Views: 4905
Reputation: 19772
Alrighty, you have several problems that were holding you back:
You're using a package.json
proxy that will only work in development. Instead use an axios
configuration on the client-side and cors configuration on the API side to allow both to communicate in development/production.
Your server.js
isn't serving your client build
production assets, so I included an example of how to do so. In addition, I added a production
script in anarchive's package.json to create a working local production example. Simply type npm run production
or yarn production
to run the example. In this simple example, go to localhost:5000, and the client will immediately attempt to verify a fake JWT token by invoking an IFFE found here. The API will receive the token, authenticate it, then respond back with an "Invalid token" alert.
I couldn't get your API route configuration to work, so I'd recommend a more standard approach.
For example:
const authRoutes = require("./routes/api/auth");
app.use("/api/auth", authRoutes);
or
app.use("/api/auth", require("./routes/api/auth"));
Doing the above should get you up and running.
Here's a working repo: https://github.com/mattcarlotta/seedbank-example
Some other notes...
You can simplify a lot of your API controller code by using async/await
and try/catch
blocks. For example, this -- which currently crashes your app if a header doesn't contain an authorization) -- can be simplified to this (unfortunately JWT uses callbacks instead of promises, so I wrapped it in a promise for cleanliness -- but the main point being that the verify
controller is much easier to read and catches any errors and sends them back to the client, instead of crashing your app).
Upvotes: 1