0

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
Sonjoy Datta
  • 1,188
  • 2
  • 13
  • 21

2 Answers2

1

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:

  1. Node.js API working locally but not on Heroku

  2. Mongodb atlas + node.js working locally but stop when pushed to Heroku

  3. 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 !!

tomerpacific
  • 4,704
  • 13
  • 34
  • 52
jsN00b
  • 3,584
  • 2
  • 8
  • 21
0

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'));
});
mousto090
  • 1,939
  • 1
  • 13
  • 12