Deploy React with Heroku - node.js

Hi i'm trying to deploy my project with heroku but it's impossible i don't understand
I already did like that on other project but this time it doesn't works in my server.js i have this code :
const express = require("express");
const graphqlHTTP = require("express-graphql");
const cors = require("cors");
const schema = require("./schema");
const path = require("path");
const app = express();
//allow Cross origin
app.use(cors());
app.use(
"/graphql",
graphqlHTTP({
schema,
graphiql: true
})
);
app.use(express.static('public'));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, 'public', 'index.html'));
});
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
In my app.js who is in my Client folder i modify uri for AplolloClient :
import React from 'react';
import './App.css';
import Logo from "./logo.png";
import Matchs from './components/Matchs'
import MatchDetail from './components/MatchDetail'
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "#apollo/react-hooks";
import { BrowserRouter as Router, Route } from "react-router-dom";
const client = new ApolloClient({
uri: "/graphql"
});
function App() {
return (
<ApolloProvider client={client}>
<Router>
<div className="container">
<img
src={Logo}
alt="Nba App"
style={{ width: 300, display: "block", margin: "auto" }}
/>
<Route exact path="/" component={Matchs} />
<Route exact path="/match/:gameId" component={MatchDetail} />
</div>
</Router>
</ApolloProvider>
);
}
export default App;
in my package.json from my client folder i add a proxy :
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"#apollo/react-hooks": "^3.1.3",
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.3.2",
"#testing-library/user-event": "^7.1.2",
"apexcharts": "^3.15.5",
"apollo-boost": "^0.4.7",
"classnames": "^2.2.6",
"graphql": "^14.6.0",
"lodash.flowright": "^3.5.0",
"react": "^16.12.0",
"react-apexcharts": "^1.3.6",
"react-apollo": "^3.1.3",
"react-dom": "^16.12.0",
"react-icons": "^3.9.0",
"react-router-dom": "^5.1.2",
"react-scripts": "3.3.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build && mv build ../public",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"proxy": "http://localhost:5000"
}
And i made a script to build and move in public/build
But when i deploy in heroku i have always
VM165:1 POST http://localhost:4000/graphql net::ERR_CONNECTION_REFUSED
But i don't know where he take this Url because i think i change all places where it could be problematic
Thanks a lot

Related

My react frontend not establishing connection with my node backend

I am trying to get my react frontend to establish connection with my node backend. The node backend works when I am using PostMan. I have gone through most of the options suggested on this plateform but none is helping.
This is the Fetch request in react
import axios from 'axios'
// Sending Request to register User
let URL = "/user/"
const register = async (userData) => {
let response = await axios.post(URL + 'register', userData)
if (response.data) {
localStorage.setItem('user', JSON.stringify(response.data))
}
return register.data
}
This is my package.json file for the react:
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"options": {
"allowedHosts": [
"localhost",
".localhost"
],
"proxy":"http://localhost:8000"
},
"dependencies": {
"#reduxjs/toolkit": "^1.8.6",
"#testing-library/jest-dom": "^5.16.5",
"#testing-library/react": "^13.4.0",
"#testing-library/user-event": "^14.4.3",
"axios": "^1.1.2",
"bootstrap": "^5.2.2",
"react": "^18.2.0",
"react-bootstrap": "^2.5.0",
"react-dom": "^18.2.0",
"react-icons": "^4.4.0",
"react-redux": "^8.0.4",
"react-router-dom": "^6.4.2",
"react-scripts": "5.0.1",
"react-toastify": "^9.0.8",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
This is my Node index.js file to handle the post request
require('dotenv').config()
const express = require('express')
const bodyParser = require('body-parser')
const { connectToDb } = require('./database/db');
const cors = require('cors')
const port = process.env.PORT || 5000
connectToDb();
const app = express()
app.use(express.json())
app.use(bodyParser.urlencoded({extended:true}))
app.use(cors())
app.use('/user', require('./routes/userRoutes'))
app.listen(port, () => {
console.log(`Server is running on ${port}`)
})
What should am I not doing right?

My react node app not reading data from backend after deploying on heroku

I am able to run my project locally without any errors but on heroku it's stuck on initial login/signup page. I assume that's because it's not interacting with the backend and only displaying frontend.
This is what my project structure looks like,
Project Structure
Content of package.json of my root folder which is react frontend
frontend/package.json
{
"name": "cook-it",
"version": "0.1.0",
"private": true,
"dependencies": {
"#apollo/react-hooks": "4.0.0",
"#material-ui/core": "4.11.3",
"#material-ui/lab": "4.0.0-alpha.57",
"#testing-library/jest-dom": "5.11.9",
"#testing-library/react": "11.2.5",
"#testing-library/user-event": "12.8.0",
"add": "2.0.6",
"antd": "4.15.0",
"apollo-cache-inmemory": "1.6.6",
"apollo-client": "2.6.10",
"apollo-link-context": "1.0.20",
"apollo-link-http": "1.5.17",
"firebase": "8.3.1",
"graphql": "15.5.0",
"graphql-tag": "2.11.0",
"jwt-decode": "3.1.2",
"react": "17.0.1",
"react-bootstrap": "1.5.1",
"react-dom": "17.0.1",
"react-router-dom": "5.2.0",
"react-scripts": "4.0.3",
"semantic-ui-css": "2.4.1",
"semantic-ui-react": "2.0.3",
"web-vitals": "1.1.0",
"yarn": "^1.22.10"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
frontend/src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App';
import 'antd/dist/antd.css';
import { ApolloProvider } from '#apollo/react-hooks';
import ApolloClient from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { createHttpLink } from 'apollo-link-http';
import { setContext } from 'apollo-link-context';
import { AuthProvider } from './context/auth';
import 'semantic-ui-css/semantic.min.css'
const httpLink = createHttpLink({
uri: 'http://localhost:5000/'
});
const authLink = setContext(() => {
const token = localStorage.getItem('jwtToken');
return {
headers: {
Authorization: token ? `Bearer ${token}` : ''
}
};
});
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
});
ReactDOM.render(
<ApolloProvider client={client}>
<AuthProvider>
<App />
</AuthProvider>
</ApolloProvider>,
document.getElementById('root')
);
frontend/backend/package.json
{
"name": "merng",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"serve": "nodemon index",
"start": "node index"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"apollo-server": "^2.24.0",
"bcryptjs": "^2.4.3",
"csvtojson": "^2.0.10",
"graphql": "^14.3.1",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.12.7",
"react-router-dom": "^5.0.1",
"semantic-ui-css": "^2.4.1",
"semantic-ui-react": "^0.87.2"
},
"devDependencies": {
"nodemon": "^1.19.1"
}
}
frontend/backend/index.js
const { ApolloServer } = require('apollo-server');
const mongoose = require('mongoose');
const typeDefs = require('./graphql/typeDefs');
const resolvers = require('./graphql/resolvers');
const { MONGODB } = require('./config.js');
const ports = process.env.PORT || 5000
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => ({ req })
});
mongoose
.connect(MONGODB, { useNewUrlParser: true,useUnifiedTopology: true })
.then(() => {
console.log('MongoDB Connected');
return server.listen({ port: ports });
})
.then((res) => {
console.log(`Server running at ${res.url}`);
});
You deployed your backend to heroku
But did not update backend url in your frontend app
const httpLink = createHttpLink({
uri: 'http://localhost:5000/' // <-- here
});

Amazon AWS EC2 React App gets blocked (Content Security Policy)

So I did the deployment exactly like here: https://medium.com/#rksmith369/how-to-deploy-mern-stack-app-on-aws-ec2-with-ssl-nginx-the-right-way-e76c1a8cd6c6
But my React App wont load, instead it gets blocked(Content Security Policy).
Maybe something with nginx? Or is my React app broken? I was searching the whole day so I thought I give it a try and ask for help.
Edit:
New Problem my homepage gets loaded, but on all of the other sites I get a 404 if I reload...
New Server.js
const express = require('express')
const mongoose = require('mongoose')
const http = require('http')
const socketio = require('socket.io')
const path = require('path')
const bodyParser = require('body-parser')
require('dotenv').config()
const app = express()
// Body Parser Middleware:
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(express.static(path.join(__dirname, 'client/build')))
mongoose
.connect(process.env.DATABASE, {
useNewUrlParser: true,
useFindAndModify: false,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() => console.log('DB connected'))
.catch(() => console.log('DB Connection Error:', err))
const server = http.createServer(app)
const io = socketio(server, {
cors: {
origin: process.env.CLIENT_URL,
methods: ['GET', 'POST'],
},
})
// Assign socket object to every request
app.use(function (req, res, next) {
req.io = io
next()
})
// Routes
const orderRoutes = require('./routes/order')
// Middleware
app.use('/api', orderRoutes)
const PORT = process.env.PORT || 5000
server.listen(PORT, console.log(`Server läuft auf Port: ${PORT}`))
React App package.json
{
"name": "client",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:5000",
"dependencies": {
"#testing-library/jest-dom": "^5.11.10",
"#testing-library/react": "^11.2.6",
"#testing-library/user-event": "^12.8.3",
"antd": "^4.15.6",
"axios": "^0.21.1",
"lodash": "^4.17.21",
"react": "^17.0.2",
"react-bootstrap": "^1.5.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.3",
"react-router-bootstrap": "^0.25.0",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"react-slick": "^0.28.1",
"react-toastify": "^7.0.3",
"redux": "^4.0.5",
"redux-devtools-extension": "^2.13.9",
"redux-thunk": "^2.3.0",
"socket.io-client": "^4.1.2",
"web-vitals": "^1.1.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
the problem is not with your React App or the your server, but its with your helmet configuration.
Update your CORS configuration to provide a valid content security policy. For example
app.use(helmet({
contentSecurityPolicy: {
directives: {
...helmet.contentSecurityPolicy.getDefaultDirectives(),
'script-src': ["'self'", 'https://apis.google.com'],
'style-src': ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com'],
'connect-src': ["'self'", 'https://accounts.google.com' ],
'img-src': ['https:', 'data:'],
},
},
}));
To read more about CSP checkout this
MDN doc
helmet

Routing doesn't work after doing react build

So I created a routing as shown below,
import React from "react";
import ReactDOM from "react-dom";
import MainComponent from "./components/mainComponent";
import LoaderComponent from "./components/loaderComponent";
import * as serviceWorker from "./serviceWorker";
import { Route, BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(
<Router>
<div>
<Route exact path="/home" component={MainComponent} />
<Route exact path="/loader" component={LoaderComponent} />
<Route exact path="/" component={MainComponent} />
</div>
</Router>,
document.getElementById("root")
);
serviceWorker.unregister();
The routing works absolutely fine when the app is started through
npm run start
When I hit localhost:3000/home it renders the MainComponent.
But after the build, it says Cannot GET /home
npm run build
When checking the app(after build) through nodeJs, only the default routing () works. Remaining routes throw Cannot GET error in the browser.
Attached below the nodejs server.js file
const express = require("express");
const bodyParser = require("body-parser");
const path = require("path");
const dotenv = require("dotenv");
dotenv.config();
require("./db/db_connection");
require("./scheduler");
const app = express();
//This is to make sure request body is accessible in express
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
//Router for the api end points
const leaderboardRoutes = require("./routes");
app.use("/api/v1", leaderboardRoutes);
//Views are present inside build folder
app.use(express.static(path.join(__dirname, "build")));
//Application hosted port
const port = process.env.PORT || 3000;
app.listen(port, function () {
console.log(`Application running on port ${port}`);
});
I'm also attaching the package.json file for reference,
{
"name": "test-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/user-event": "^7.2.1",
"axios": "^0.19.2",
"body-parser": "^1.19.0",
"bootstrap": "^4.4.1",
"connect-timeout": "^1.9.0",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"http": "0.0.1-security",
"material-ui": "^0.20.2",
"mongoose": "^5.9.9",
"node-schedule": "^1.3.2",
"path": "^0.12.7",
"pure-react-carousel": "^1.25.2",
"react": "^16.13.0",
"react-bootstrap": "^1.0.0-beta.17",
"react-circular-progressbar": "^2.0.3",
"react-dom": "^16.13.0",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.0",
"request": "^2.88.2"
},
"scripts": {
"start": "react-scripts start",
"start-server": "npm run build && nodemon server.js",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Please help me in understanding what' going wrong or what I've missed.
Thanks in advance.
I have not used react-scripts but after build, if its showing Cannot GET /*, then it seems to me that the files are going into some directory under the build directory, meaning the path you're trying to access is not complete. You might want to check that and use in your build configuration.
For example, in my case, I used a mount path for my application, so it looked like:
http://localhost:3000/myapp where myapp was the mount path.
Then I had used public name for a directory in webpack config path for I wanted to put my files in there, and then I had used publicPath with value myapp, which means files were going into build/public/myapp, so when I hit the URL above, the server looked for index file in this path and loaded the file.

React/Express App when deployed to Heroku only responds with index.html

I'm attempting to deploy my first react + express app. It works locally and runs both the front end and backed on port 8080. However when I deploy to heroku, the backend only responds with index.html. I've tried changing the scripts in package.json and the paths in server.js but I'm pretty stuck in terms of getting more information out of this error and what to try next. When I first deployed to heroku I received an H10 error, but then following an article recommendation I installed serve. That package resolved the H10 error, but the app doesn't respond with the json from the database. What am I missing here?
https://runtopia.herokuapp.com/
Package.json
{
"name": "runtopia",
"version": "0.1.0",
"private": true,
"dependencies": {
"#amcharts/amcharts4": "^4.9.26",
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/user-event": "^7.2.1",
"express": "^4.17.1",
"lodash": "^4.17.15",
"moment": "^2.26.0",
"nedb": "^1.8.0",
"nodemon": "^2.0.4",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.1",
"serve": "^11.3.2"
},
"scripts": {
"dev": "react-scripts start",
"start": "serve -s build",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"heroku-postbuild": "npm run build"
},
"proxy": "http://localhost:8080/",
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
server.js
const express = require('express');
const path = require('path')
const app = express();
const port = process.env.PORT || 8080;
const Datastore = require('nedb');
// console.log that your server is up and running
app.listen(port, () => console.log(`Listening on port ${port}`));
app.use(express.json());
// ADDED TO WORK FOR HEROKU
app.use(express.static(path.join(__dirname,'build')));
//retrieve data from database
app.get('/chartData', (request,response) => {
db.find({},(err,data) => {
if (err){
response.end();
return
}
response.json(data)
})
})
const db = new Datastore({filename:'./database.db', autoload: true});
app.post('/fitData', (request, response) => {
const fitData = request.body
fitData.map(week =>
{
console.log("logging week",week.weekYear)
db.update({'weekYear' : week.weekYear}, week, {upsert: true, multi: true}, function (){});
})
response.json({status: "this is the backend saying, got the lastest fitbit Data!"})
})
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.js
import React from 'react';
import Chart2 from './Chart';
import './App.css';
import moment from 'moment';
import _ from 'lodash';
class App extends React.Component{
constructor(props){
super(props)
this.state = {
fitData:[],
chartData: [],
}
this.grab = this.grab.bind(this);
this.queryDb = this.queryDb.bind(this)
}
//populates chart with data currently in db
componentDidMount(){
this.queryDb()
}
async post(){
const options = {
method: 'POST',
headers: {
'Content-Type' : 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(this.state.fitData)
}
const response = await fetch('/fitData', options);
const data = await response.json()
console.log(data)
await this.queryDb()
}
async queryDb(){
const response = await fetch('/chartData');
const dbData = await response.json()
let sorted = dbData.sort((a, b) => (a.date > b.date) ? 1 : -1)
this.setState({chartData:sorted})
}
render(){
return (
<div className="grid-container">
<div className="Top"></div>
<div className="Title">
<p className="runtopia">RUNTOPIA.</p>
<div>
<button className="big-button" onClick= {this.grab}>Get Data</button>
</div>
</div>
<div className="Weekly">
<Chart2 key={this.state.chartData} data={this.state.chartData} />
</div>
<div className="Bottom"></div>
</div>
);
}
}
export default App;

Resources