MERN project routing not working on Heroku - node.js

I have created a personal website. It is developed using ReactJs, Express, Node, and MongoDB. It is working fine on my localhost also, Heroku (using react-router-dom) too. But, when I direct hit the URL on Heroku then it is showing error. The homepage is working only.
Here is the URL, https://amper.herokuapp.com/
package.json
{
"name": "amper",
"version": "1.0.0",
"description": "",
"main": "server.js",
"homepage": "https://amper.herokuapp.com",
"scripts": {
"dev-client": "PORT=3000 react-scripts start",
"server": "node server.js",
"dev-server": "nodemon ./server.js",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"start": "PORT=3000 react-scripts start && node server.js",
"dev": "concurrently --kill-others \"npm run dev-client\" \"npm run dev-server\""
},
"author": "Amper",
"license": "ISC",
"dependencies": {
"#ckeditor/ckeditor5-build-classic": "^19.0.1",
"#ckeditor/ckeditor5-react": "^2.1.0",
"#fortawesome/fontawesome-svg-core": "^1.2.28",
"#fortawesome/free-brands-svg-icons": "^5.13.0",
"#fortawesome/react-fontawesome": "^0.1.9",
"#testing-library/jest-dom": "^5.9.0",
"#testing-library/react": "^10.0.4",
"#testing-library/user-event": "^10.4.0",
"axios": "^0.19.2",
"bcrypt": "^4.0.1",
"body-parser": "^1.19.0",
"bootstrap": "^4.5.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"draft-js": "^0.11.5",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"moment": "^2.26.0",
"mongoose": "^5.9.16",
"path": "^0.12.7",
"react": "^16.13.1",
"react-bootstrap": "^1.0.1",
"react-dom": "^16.13.1",
"react-feather": "^2.0.8",
"react-helmet": "^6.0.0",
"react-moment": "^0.9.7",
"react-router-dom": "^5.2.0",
"react-scripts": "^3.4.1",
"react-select": "^3.1.0",
"serve-static": "^1.14.1"
},
"engines": {
"node": "12.16.3"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"concurrently": "^5.2.0",
"node-sass": "^4.14.1",
"nodemon": "^2.0.4"
}
}
server.js
const express = require('express');
const mongoose = require('mongoose');
const bodyparser = require('body-parser');
const cors = require('cors');
const path = require('path');
const serveStatic = require('serve-static');
require('dotenv').config();
const routes = require('./server/routes');
const app = express();
const port = process.env.PORT;
// mongo connection
mongoose.Promise = global.Promise;
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('Database Connected'))
.catch((err) => console.log(err));
app.use(serveStatic(path.join(__dirname, 'build')));
// bodyparser setup
app.use(bodyparser.urlencoded({ extended: true }));
app.use(bodyparser.json());
// cors setup
app.use(cors());
routes(app);
app.listen(port, () => console.log(`App is running on port ${port}`));
Project folder structure
amper
|_ node_modules
|_ public
|_ favicon.ico
|_ index.html
|_ manifest.json
|_ robots.txt
|_ server
|_ controllers
|_ middleware
|_ models
|_ routes
|_ src
|_ assets
|_ components
|_ App.js
|_ index.js
|_ serviceWorker.js
|_ setupTests.js
|_ .env
|_ .gitignore
|_ package-lock.json
|_ package.json
|_ README.md
|_ server.js

Currently facing the exact same issue.
mongoose.connect(process.env.MONGO_URI ...
My env variable was not set-up on Heroku. I added it under:
heroku -> settings -> config vars -> reveal config vars
Now, my app shows 503 Service Unavailable (when I check under network-info on chrome-dev-tools). Heroku log says H12 "Request timeout" and when checking, I get this page.
So, I tried postman to initiate a very simple 'GET' request which would send back 1 row. The postman GET also fails.
Although this is not an answer per-se, I have tried to list down steps taken. Some of these are using other questions on stackoverflow & will try to link those.
Related stackoverflow questions:
Node.js API working locally but not on Heroku
Mongodb atlas + node.js working locally but stop when pushed to Heroku
application times out when connecting to MongoLab from Heroku
As an addendum, I would also like to view any "console.log" messages from server.js. Have just last week built my first-ever MERN-app & looking for any pointers.
Problem solved: Huge thanks to below answer by mousto090.
if (process.env.NODE_ENV === "production") {
// Set the static assets folder (ie, client build)
app.use(express.static('client/build'));
app.get('*', (req,res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', index.html'))
});
}
Above code was on my server.js. Clearly, there is an expectation of a NODE_ENV variable which I missed to declare on Heroku settings. Added it & the code works now. Thank you mousto090 !!

serve-static package serve the build folder, however this is not quite enough if you use client-side routing.
Add the following code after all your routes
routes(app);
app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

Related

Node js App not working on heroku some month after testing

I have read up solution from different stack overflow but non solves the problem
This end point works fine on local host and heroku some month ago but now it works fine only on local host I get this error after I try to access the end point
server.js file
'use strict';
require("dotenv").config();
require('./MongoDB/DB')
const http = require('http');
const express = require('express');
const cors = require("cors");
const mongoSanitize = require('express-mongo-sanitize');
let cookieParser = require('cookie-parser');
const app = express();
const server = http.createServer(app)
const port=process.env.PORT||5000;
const passportContol=require("./Passport/index")
app.use(cors())
app.use(cookieParser())
app.use(express.json({ limit: "1kb" }));
app.use(express.urlencoded({ extended: true,limit: "1kb"}));
app.use(
mongoSanitize({
replaceWith: '_',
}),
);
app.use(passportContol.initialize());
app.set('trust proxy', 1);
const router1=require('./Router/Account')
const router2=require('./Router/Post')
const router3=require('./Router/Request')
app.use("/",router1);
app.use("/",router2);
app.use("/",router3);
server.listen(port ,()=>console.log(`server started.... ${port}`))
package.json
{
"name": "api-campus-bet",
"version": "1.0.0",
"description": "campus-bet api for soccer betting",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js",
"dev": "nodemon server"
},
"author": "Ogbonna Chinaza",
"license": "ISC",
"dependencies": {
"axios": "^0.26.1",
"bcrypt": "^5.0.1",
"cookie": "^0.4.2",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"csurf": "^1.11.0",
"dotenv": "^16.0.0",
"express": "^4.17.3",
"express-mongo-sanitize": "^2.2.0",
"express-rate-limit": "^6.3.0",
"ioredis": "^5.0.3",
"jsonwebtoken": "^8.5.1",
"mongoose": "^6.2.9",
"passport": "^0.5.2",
"passport-local": "^1.0.0"
},
"engines": {
"node": "16.13.1"
}
}
Procfile
web: node server.js
WHAT I HAVE DONE
I have reinstall the nodemodule i did this including package-lock.json
I have cleared heroku cache
(git commit --allow-empty -m "Purge cache"
$ git push heroku master)
I deleted the whole project on heroku and push a new one with no error message
with some other things
please I need help what have I done wrong
This problem was caused by git it was including some files which should not be included when hosting like node module and the gitignore file. I solved the problem by using the solution in this site to remove those files.
Remove node_modules from git in vscode

Deploying to GCP App Engine with React Frontend and Node backend not able to hit api routes on deployed version by works locally

I have deployed my site to google cloud platform and the react(static) part is working fine, but anytime I go to /api/mail/send to use nodemailer I either get a 404 error saying it cant be found or with some configurations in the yaml file I just a 500 error.. below is my yaml, package.json and server.js files
App.yaml
runtime: nodejs12
env: standard
basic_scaling:
max_instances: 5
idle_timeout: 5m
handlers:
- url: /api/.*
secure: always
script: auto
- url: /
static_files: client/build/index.html
upload: client/build/index.html
secure: always
- url: /
static_dir: client/build
secure: always
Package.json
{
"name": "mern",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "concurrently \"nodemon --ignore 'client/*'\" \"npm run client\"",
"client": "cd client && npm run start",
"install": "cd client && npm install",
"build": "cd client && npm run build"
},
"author": "",
"license": "ISC",
"devDependencies": {
"autoprefixer": "^9.8.6",
"concurrently": "^5.3.0",
"husky": "^4.2.5",
"postcss-cli": "^7.1.1",
"tailwindcss": "^1.6.2"
},
"dependencies": {
"if-env": "^1.0.4",
"axios": "^0.19.2",
"body-parser": "^1.19.0",
"classnames": "^2.2.6",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-session": "^1.17.1",
"morgan": "^1.10.0",
"nodemailer": "^6.4.11"
}
}
server.js
require('dotenv').config()
const express = require("express");
const morgan = require('morgan');
const routes = require("./routes");
const path = require('path');
const app = express();
const PORT = process.env.PORT || 3001;
// Define middleware here
app.use(morgan('dev'));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
// Add routes, both API and view
app.use(routes);
// Serve up static assets (usually on heroku)
app.use(express.static("client/build"));
// Start the API server
app.listen(PORT, function() {
console.log(`🌎 ==> API Server now listening on PORT ${PORT}!`);
});
Thanks

React components missing after deploying MERN app to Heroku

I deployed a MERN app to Heroku (using MongoDB Atlas for database) and the home page is not rendering the login or register forms. I checked the Heroku logs for any errors and there are no errors. Also, when I inspect the elements I see the elements are there but the React components are not rendering. Only the CSS background image is rendering. Is there something off with my heroku-postbuild script? Thanks.enter image description here
Heroku app hosted at "https://glacial-gorge-15530.herokuapp.com/login". Below are my server.js and package.json files. I also added images of development vs production screenshots of the login page.
server.js
const express = require('express');
const connectDB = require('./config/db');
const path = require('path');
const app = express();
//Connect Database
connectDB();
//Init middleware
app.use(express.json({ extended: false }));
//Define routes
app.use('/api/users', require('./routes/users'));
app.use('/api/auth', require('./routes/auth'));
app.use('/api/recipes', require('./routes/recipes'));
//Serve static assets 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')));
}
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
package.json
{
"name": "favorite-recipes-2",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"start": "node server.js",
"server": "nodemon server.js",
"client": "npm start --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\"",
"heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix client && npm run build --prefix client"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"client": "0.0.1",
"config": "^3.3.1",
"create-react-app": "^3.4.1",
"express": "^4.17.1",
"express-validator": "^6.6.0",
"jsonwebtoken": "^8.5.1",
"materialize-css": "^1.0.0-rc.2",
"mongoose": "^5.9.20",
"react-transition-group": "^4.4.1"
},
"devDependencies": {
"concurrently": "^5.2.0",
"nodemon": "^2.0.4"
}
}
Screenshots of login page in production environment
Screenshots of login page in development environment
Your .form-container element has an opacity of 1%, which is why the elements are invisible.
.form-container {
background-color: #e7e3e3;
opacity: 1%;
}
Remove opacity: 1%.

Is it possible to host MERN application on Heroku using single package.json?

I read bunch of blogs about MERN application deployment on Heroku but they all are uses separate package.json for client and server!
Is it possible to use one package.json file?
My Project Structure
My package.json
{
"name": "ecommerce",
"version": "0.1.0",
"private": true,
"author": "Dweep Panchal",
"license": "ISC",
"dependencies": {
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/user-event": "^7.2.1",
"braintree-web-drop-in-react": "^1.1.1",
"concurrently": "^5.2.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.1.2",
"react-scripts": "3.4.1",
"react-stripe-checkout": "^2.6.3",
"body-parser": "^1.19.0",
"braintree": "^2.22.0",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-jwt": "^5.3.3",
"express-validator": "^6.4.0",
"formidable": "^1.2.2",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.15",
"mongoose": "^5.9.7",
"stripe": "^8.46.0",
"uuid": "^7.0.3"
},
"scripts": {
"server": "cd ./backend && node app.js",
"start": "concurrently \"npm run server\" \"react-scripts start\"",
"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"
]
},
"proxy": "http://localhost:8000",
"devDependencies": {
"nodemon": "^2.0.3"
},
"engines": {
"node": "10.16.0",
"npm": "6.9.0"
}
}
app.js
require("dotenv").config({ path: "../.env" });
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const cors = require("cors");
const app = express();
// Routes
const authRoutes = require("./routes/auth");
const userRoutes = require("./routes/user");
const categoryRoutes = require("./routes/category");
const productRoutes = require("./routes/product");
const orderRoutes = require("./routes/order");
const stripeRoutes = require("./routes/stripepayment");
const braintreeRoutes = require("./routes/braintreepayment");
// DB Connection
mongoose
.connect(
`mongodb+srv://${process.env.DB_NAME}:${process.env.DB_PASS}#${process.env.DB_PROJECT}-xi8tq.mongodb.net/${process.env.DB_PROJECT}?retryWrites=true&w=majority`,
{
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
useFindAndModify: true,
}
)
.then(() => console.log("DB Connected!"))
.catch(() => console.log("Failed to Connect DB"));
// Middleware
app.use(bodyParser.json());
app.use(cookieParser());
app.use(cors());
// My Routes
app.use("/api", authRoutes);
app.use("/api", userRoutes);
app.use("/api", categoryRoutes);
app.use("/api", productRoutes);
app.use("/api", orderRoutes);
app.use("/api", stripeRoutes);
app.use("/api", braintreeRoutes);
// Server Connection
const port = process.env.BACKEND_PORT || 8000;
app.listen(port, () => console.log(`Server Running at Port ${port}`));
When i deployed this application on heroku then project url shows:
Invalid Host header
Whole project: https://github.com/dweep612/ecommerce
Let me quickly explain how deploying any Reactjs and express to heroku work. The goal is to generate a build folder with npm run build and then starting the server to serve static content from that build folder.
In the heroku documentation, it states that heroku-postbuild runs before the start scripts. This is a perfect place to do npm run build to generate a build folder and then using the start script to run your server code. From there your server should be using express.static and pointing where ever you generated your build folder.
That is why people like to use a server package.json because it won't interfere with the react start script. Now the problem I immediately see is that you are not using the scripts correct nor are you pointing at that build folder that you are suppose to generate.
In your package.json create a start script that starts your app.js file and then create a heroku-postbuild that will generate a build folder. Like below
"scripts": {
"start": "cd ./backend && node app.js",
"heroku-postbuild": "npm run build",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
After that you should have app.use(express.static(<<location of build folder>>)) in your app.js . Add the code below in your app.js
if (process.env.NODE_ENV === "production") {
app.use(express.static("../build"));
}
The reason I said ../build is because your build folder is outside of the backend folder.
I also checked out your entire code and there are other small configuration issue. For example, if you are deploying to heroku , you should be using process.env.PORT
Yes it's possible, if your backend serves your frontend. Two package.json is useful when your backend and your frontend run on two separate node programs.
The invalid host headers are probably due to how your server handles headers, but since you didn't posted a minimal reproducible example, as of now we can't help you further.

Refused to load the image 'https://diary2020.herokuapp.com/favicon.ico'

I used MERN(MongoDb, Express, React js, Node) technology for my app. It works locally fine. but When I deployed in heroku I am getting internal server error. I might made mistake in setup but I can't see it.
In google Chrome console I got this error: Refused to load the image 'https://diary2020.herokuapp.com/favicon.ico' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.
When I used Heroku logs I got this:
This is my server setup:
require("dotenv").config();
const express = require("express");
const cors = require("cors");
const morgan = require("morgan");
const app = express();
const logs = require("./src/logs.js/logs");
const mongoose = require("mongoose");
const path = require("path");
const helmet = require("helmet");
//middlewares
app.use(cors());
app.use(morgan("dev"));
app.use(express.json());
app.use(helmet());
//connect to db
mongoose
.connect(process.env.MONGODB_URI, {
useUnifiedTopology: true,
useNewUrlParser: true
})
.then(() => console.log("DB Connected!"))
.catch(err => {
console.log(err);
});
app.use("/api", logs);
app.use(express.static(__dirname + "build")); //
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "build", index.html));
});
const port = process.env.PORT || 5000;
app.listen(port, () => {
console.log(`Server is running port ${port}`);
});
In my client folder first run npm run build then I cut it and pasted it outside of the client. Then I connected to server. As you can above. But it does not recognize the build's index.html
This is my backend package.json
{
"name": "form",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"start": "node server.js",
"server": "node server.js",
"client": "npm start --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\""
},
"author": "alak",
"license": "MIT",
"dependencies": {
"concurrently": "^5.1.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"helmet": "^3.21.3",
"heroku": "^7.39.0",
"jquery": "^3.4.1",
"mongoose": "^5.9.3",
"morgan": "^1.9.1",
"path": "^0.12.7",
"react-router-dom": "^5.1.2", //I MISTAKENLY INSTALLED IT.BUT I THINK IT SHOULD NOT BE A PROBLEM
"react-transition-group": "^4.3.0" //I MISTAKENLY INSTALLED IT. BUT I THINK IT SHOULD NOT BE A PROBLEM
}
}
This is React's package.json
{
"name": "client",
"version": "0.1.0",
"engines": {
"node": "13.10.1",
"npm": "6.13.7"
},
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.3.2",
"#testing-library/user-event": "^7.1.2",
"moment": "^2.24.0",
"react": "^16.13.0",
"react-dom": "^16.13.0",
"react-scripts": "3.4.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"proxy": "http://localhost:5000",
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
The ReferenceError you're seeing is caused by index.html not being wrapped in quotations - node is trying to evaluate the html property of an object named index which I'm willing to bet is not what you meant.
app.use(express.static(__dirname + "build")); //
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "build", index.html)); // <- try "index.html"
});
The probable reason why you getting this error is likely because you've added /build folder to your .gitignore file or generally haven't checked it into git. So when you git push heroku master, build folder you're referencing don't get push to heroku. And that's it shows this error.
T its work properly locally

Resources