How to deploy chat server on heroku - reactjs

So I've just created simple chat app with React, NodeJS, Express.JS and SocketIO. I'm going to deploy it on Heroku.
The problem is I'm not sure could I run both frontend and backend on the same URL. When I first created this chat locally, I've run front-end on localhost:3000 (default by Create-React-App) and backend on localhost:8000.
For the front-end side, I did it like this in external API.js file:
import io from 'socket.io-client';
let socket;
export const api = {
open: () => {
socket = io('http://localhost:8000');
}
}
For the backend side, I did it like this:
let express = require('express');
let io = require('socket.io')(8000);
So, you see, they're both on different ports. On my computer, it works perfectly. I'm not sure they could work locally on the same port (if I'm trying to switch 8000 port on back-end side to port 3000 it unfortunately doesn't work correctly - front and backend can't work on the same port, HTTP 404 error occurs).
My question is: is there any reason/is it even possible to put it on the same port? Because here's the problem number 2:
I've tried to deploy it on heroku, for the front-end side I've used Heroku Buildpack for create-react-app and it works fine, but totally don't know how to use it to deploy server-side. Should I create separate heroku address for the backend? And, at the code above, change paths like:
let socket;
export const api = {
open: () => {
socket = io('http://myherokuaddress');
}
}
and
let express = require('express');
let io = require('socket.io')(http://myherokuaddress);
?

In heroku you can't define port manually. use this code instead of port 8000.
process.env.PORT

You can do what Zenith said, however, the best practice is to use different servers for frontend and backend code, that way you can build mode frontend apps that uses the same backend code. And, if for some reason, your frontend server is down, you will only need to host the frontend code anywhere else and still using the same backend.

Related

How to change localhost API URL when deployed to Heroku?

I've deployed an server-side rendering React app (bundled without CRA):
it has an express server for server-side rendering (listens to port 3000 or process.env.PORT)
it has an express server for the API that serves the frontend (listens to port 8080 or process.env.PORT)
On localhost, the frontend makes a request to http://localhost:8080/api to get the data, which works perfectly.
From my understanding, when the app is in production, the base API URL should be the app's URL (eg. https://myapp.herokuapp.com) instead of http://localhost:8080, so I added this change in my code:
if the app is in dev, the frontend calls http://localhost:8080/api
if the app is in prod, the frontend calls https://myapp.herokuapp.com/api(I added https://myapp.herokuapp.com/as a config var in Heroku)
However, it doesn't work. My app is deployed successfully to Heroku and the SSR renders correctly, but the API call fails. (I also tried https://myapp.herokuapp.com/api:3000 which fails)
What should be the API URL to call a local server when the app is in production?
thanks a lot!
Well, as far as I know Heroku doesn't allow multiple ports and you will not be able to open 3000 for web and 8080 for api.
You can serve both on the same port and route /api to the api.
I have worked on a project that uses similar approach and below is the code:
app.use('/api', router); // every api route is in the router
app.use(express.static(staticDir));
It is also deployed to heroku.
full repo if you wish to take a look - https://github.com/berkeli/breteau-dashboard/blob/main/server/utils/createServer.js

React app + heroku server not working on production, but working fine in dev

I am working on React application which is querying from a server. I have deployed the server on heroku. When I am testing in dev, the application is behaving as expected. But when I am using it on vercel deployment, it is failing as heroku server is not responding properly.
Following is the server code of the query:
app.get(`/allPlans`, async (req, res) => {
console.log("allPlans() query");
ret = await Plans.find({});
f = [];
for (i = 0; i < ret.length; i++) {
f.push(ret[i].name);
}
console.log(f);
return res.status(200).send(f);
});
Folowing is the code I am using to query from the client using axios:
const endPoint = "/allPlans";
let ret = await axios.get(endPoint);
console.log(ret.data);
In the dev environment, when I am deploying the application on localhost:3000, this is returning me a nice array.
["test","myPlan190","myPlan987"]
But in the actual production on vercel it is returning the following object(You can check this message in the console by going on the vercel deployment):
All suggestions are welcome.
Github repo
Vercel deployment
Server status
Heroku server query which is failing from axios, but working elsewise
Well, I checked you repository and also checked the XHR requests on your Vercel deployment and as far as I can see it making only one, which is:
Request URL: https://planner-pcrsehfg3-akcgjc007.vercel.app/allPlans
It is not making an actual call to the server. I see that in Dashboard.js you are requiring axios from the package. I did not find any created instance of axios. So essentualy there is nothing to append in front of "/allPlans". Either create an axios instance with the right url "https://cryptic-bayou-91116.herokuapp.com" of just test it by putting the whole url "https://cryptic-bayou-91116.herokuapp.com/allPlans" inside the axios call in Dashboard.js.
Following is the updated code for an axios query:
const baseURL = "https://cryptic-bayou-91116.herokuapp.com"
...
const endPoint = baseURL + "/allPlans";
let ret = await axios.get(endPoint);
console.log(ret.data);
fHeroku randomly changed application binding port.
You may set port by:
const port = process.env.PORT || 3000
for this use in you app dotenv
Or edit file .env on heroku. Install Heroku CLI:
heroku login
heroku run bash -a app_name
touch .env
echo "PORT=3000" >> .env
check variable by
cat .env

ReactJS backend requests and proxy

I have a couple of questions regarding how ReactJS should work in development and production. My ReactJS application was built starting from creare-react-app boilerplate. I have a SpringBoot backend listening on port 8080. The first thing I noticed is that if I set a code like this to make requests the code hang:
async componentDidMount() {
...
const response = await fetch('http://localhost:8080/api/compliance');
I need to convert it into:
async componentDidMount() {
...
const response = await fetch('/api/compliance');
and then add the line:
"proxy": "http://localhost:8080",
and this works fine. The problem is that when I put this in a pre-production environment (or integration environment) where I have a URL like http://www.mywebsite.com I got:
Invalid Host Header
Looking on the web I noticed that probably this could be to:
1. proxy that checks. the HTTP Header host and verify it to avoid security attacks
2. webpack package
I would like to understand:
1. Is proxy really necessary to let ReactJS app talk with its backend?
2. If no, how I can solve the issue (currently solution on the web didn't solve my problem)?
Generally proxy is not meant for production. Your app should provide both app and api on same port, on one server. https://stackoverflow.com/a/46771744/8522881

Configuring a React-Express App on Heroku to Pull Data in an Ajax Request

I have a React-Express app that pulls data from a MongoDB database on mLab.
On my server.js file, I have the api port set as such:
var port = process.env.PORT || 3001;
And it listens as such:
app.listen(port, function() {
console.log(`api running on port ${port}`);
});
Currently, in my React app, one of the components makes an AJAX call to the database on mLab using the url of "http://localhost:3001/api/data", which works fine and pulls the data I requested.
However, when I deploy the app to Heroku, I'm not sure how to configure the server.js and the url in the React app, so the React app is able to pull the data from the database.
I've conferred with mLab, and there are no issues, and I've conferred with Heroku, and this is beyond the scope of their support.
UPDATE: Is it that the process.env.PORT variable needs to be set or redirected?
Any ideas what I need to do?
Thanks!
If your express app is serving both your bundled react app and your api, you need to make sure that express knows that the /api endpoint needs to be NOT served to the react app.
Not sure what your server code looks like, but this has worked for me:
if (process.env.NODE_ENV === 'production') {
app.get(/^\/(?!api).*/, (req, res) => { // don't serve react app to api routes
res.sendFile(PATHTOREACTBUNDLE));
});
};
Basically, you want to tell express that, if in production mode (deploy on heroku), serve all endpoints, except the api endpoint (/^/(?!api) to your react bundle.

How do I connect a react frontend and express backend?

So here is my issue in a pickle: btw I had some trouble finding out how to do this through google and I did try using StackOverflow but couldn't find the exact answer
So I have a ReactJS website where I use
yarn start
to run and it launches on localhost:3000
I want it to launch on localhost:3000 while an express server also launches on that server, aka start the react server up in express.js.
It seems like every tutorial I've found, most are outdated, and the remaining ones are guides to turn react into a static website and THEN use express. I would like to keep react on the server-side for advantage of react-router
Edit1: So basically when I have an expressjs server
THE DATABASE DETAILS HAVE BEEN REMOVED, THAT LINE ISNT AN ERROR
const express = require('express'); var app = express();
var mysql = require('mysql'); var connection =
mysql.createConnection({ host :
database : 'main' });
connection.connect()
app.post('/users', function(req, res) { var user = req.body;
res.end('Success'); })
app.listen(3000, function(){ console.log('Express sever is listening
on port 3000') })
//connection.end()
I also start the create-react-app server with yarn start and it launches on localhost:3000 but this expressjs server overrides that.
So I want to connect the two to be able to send post requests
I just recently worked on a sample repo that implements this strategy. There are a few ways this can be done, but the simplest way to do this will be to start the express server as a second server that will run on a different port, ie. 3001. You can then use concurrently to launch both the react server (I am assuming webpack) and the express API server in a single command.
Here is a tutorial that shows how this can be set up. You should pay attention to the section in this tutorial about proxying requests from the client (browser) through the webpack server. There are some considerations to think about with regards to CORS configuration if you do not proxy requests through the webpack server.
Here is my proof of concept repo where I implemented just what you are looking for: react client, and express server. It can be run via concurrently or with docker (compose).
You can change the port on which express is listening:
var server = app.listen(3001, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
Change 3001 to any valid port number

Resources