How to connect frontend to json data on heroku - reactjs

I'm trying to deploy my first React app on Heroku. I used simple json files for the backend.
Locally, everything runs good: my server is on localhost:8080, and frontend axios calls gets data from it like so:
axios.get(localhost:8080/bench).then( (response) => {
// my logic here
})
My deployment flow is:
to run a npm build and put everything in the build folder into the server end's public folder. Here's the entry-point file:
const path = require("path");
const publicPath = path.join(__dirname, "public");
console.log(publicPath);
app.use(express.static(publicPath));
app.get("*", (req, res) => {
res.sendFile(path.join(publicPath, "index.html"));
});
push to build artifacts to Heroku
Doing so, everything from the frontend part runs good on Heroku.
My concern is that I can't figure out what axios calls I should use for the frontend to get the data from the server. Is there anything I am missing?

Localhost only works on your machine. In your frontend, you'll need to change the axios url to point to the URL of your deployed server like so:
axios.get(`${YOUR_HEROKU_URL}`/bench)

Related

live reload when running express with CRA

I have my create react app setup similar to this setup. https://www.newline.co/fullstack-react/articles/using-create-react-app-with-a-server/
All is working great so far.
when I'm running on localhost:3000 i'm seeing hot reloading as CRA dev server is taking care of that for me.
Now when I run my app using my express server localhost:8081 i'm loading my html file and assets from CRA build folder which obviously means I'm only going to get the built files.
What i'd like to do is when running in port localhost:8081 I can get a reload of development changed files and not just the static build files.
The reason for this is let's say I'm using an authentication setup where I need to check if user is logged in before I allow the * route to proceed otherwise redirect to another route in express. I want to be able to check for this when working in development.
If I run the dev server localhost:3000 then I no longer get the route change loading my html files from express. Only the api call would work from express.
Here is my setup in express:
const express = require("express");
const path = require("path");
const PORT = process.env.PORT || "8081";
const app = express();
const indexPath = path.join(__dirname, "../build/index.html");
app.use(express.static(path.resolve(__dirname, "../build"), { index: false }));
app.get("/test", (req, res) => {
res.json({ message: "welcome to backend" });
});
app.get("*", (req, res) => {
console.log("sending index.html");
res.sendFile(indexPath);
});
app.listen(PORT, () => console.log(`listing on port ${PORT}`));
This express route will only work when using in localhost:8081 which is getting the build files.
app.get("*", (req, res) => {
console.log("sending index.html");
res.sendFile(indexPath);
});
But this never runs when working in dev server localhost:3000 so I can not do any authentication on this route when working in development mode. This would mean to test this I would have to keep rebuilding the build folder which is crazy.
I'm running my client in one terminal and my server in another. I also restarted both multiple times. The proxy as I said works in my package file for the /test route when called using fetch .
This a similar unanswered question I found:
create-react-app + nodejs (express) server

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

locally host firebase backend with react frontend together, for debugging

I am building a react website with firebase functions backend.
I'm using firebase serve to locally host the node.js backend that I connect to my react code through express API endpoints, and I am using react-scripts start to test my react frontend app.
all my get requests in my react app use /some endpoint to communicate with my firebase localserver. But they are running on different ports. firebase serves it on localhost:5000 while react live server hosts it at localhost:3000.
I tried many things and couldn't get any useful way to make this work. I at last added my react project as a subfolder in my firebase project and made the hosting public path at firebase.json to my react build directory. It works now but I always have to run npm run build on my react app on every change, to make it compile my app into the build directory, which is painfully slow.
What is the proper way to do this? debug react app and firebase backend together.
I finally enabled cross-origin-requests on my server using cors module
Serverside code
const cors = require("cors");
app.get("/test", (req, res) => {
return cors()(req, res, async () => {
res.send("working...");
});
});
Serverside code
And then adding a simple config file in the react side, to switch between debugging and deployed testing really helped.
config.js
var domain = "";
// domain = "http://localhost:5000";
export {domain}
then whenever I use apis in react, I simply comment/uncomment the second line to switch between local and deployed testing.
Then whenever I use APIs, I append `domain` before every url in all references, eg fetch requests
import { domain } from "config.js";
fetch(domain + "/int-search", ...
Then it worked fine running both the firebase backend and the react application on localhost, using firebase serve and npm start for my react app.

Simple password-protection for React app on Heroku

I have a simple React app, created with create-react-app, that I'd like to deploy to Heroku (or somewhere easy) and password-protect. The protection can be really simple—just a single password is fine.
I started looking into HTTP basic auth but didn't find an easy answer. The closest I found was in this post, but (a) I don't love the idea of having to eject my app, and (b) I couldn't get it working. I was hoping I could find a Heroku plugin, but no luck there either.
It wouldn't be too hard to write a component that wraps my app and requests a password before showing it. The problem is that it executes client-side. I want to store the correct password server-side (or a hash thereof), and have the app send password attempts up to the server.
Since create-react-app operates on top of Node, I'm hoping there's an easy way to tell it to execute and store certain things on the server, but maybe I'm wrong. Any suggestions?
This create-react-app buildpack seems to support http basic auth:
https://github.com/substantial/create-react-app-buildpack
https://elements.heroku.com/buildpacks/substantial/heroku-buildpack-static
I am assuming your intentions are wanting to protect the config vars in heroku so other people cannot access you database with your credentials.
The way I password protected my deployment to heroku, is to make a keys_prod.js file containing the Heroku config vars of my mLab database in my backend using express and mongoDB:
keys_prod.js file:
module.exports = {
mongoURI: process.env.MONGO_URI,
secretOrKey: process.env.SECRET_OR_KEY
};
keys.js file:
if (process.env.NODE_ENV === 'production') {
module.exports = require('./keys_prod');
} else {
module.exports = require('./keys_dev');
}
in my server.js file I added:
// DB Config
const db = require('./config/keys').mongoURI;
// Server static assets if in production
if (process.env.NODE_ENV === 'production') {
// Set static folder
app.use(express.static('client/build'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
This allows you to request the config vars you filled in heroku without including it in your repo.
If you use Node in backend you can use Passport Basic Auth
app.get('*', passport.authenticate('basic', { session: false }), (req, res) => {
res.sendFile(path.join(`${__dirname}/../build/index.html`))
})
Every time you access the page in browser, a popup will appear, asking you username and password.

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.

Resources