Error deploying Mern Stack application on Heroku - node.js

I am trying to deploy a full-stack app on heroku, i have tried couple of things but none of them worked... when i entered "heroku logs" to follow up with the errors it should me code: 'MODULE_NOT_FOUND even though the node_module's can be found in both the Root of the project and the Frontend file as well , how do i fix this error and where does it come from ?
Here's a picture of my projects structure:
server.js:
require('dotenv').config();
const path = require('path');
const express = require("express");
const productRoutes = require("./routes/productRoutes");
const connectDB = require("./config/db");
connectDB();
const app = express();
app.use(express.json());
//--------------- deployment -------
app.use("/api/products", productRoutes);
if(process.env.NODE_ENV === "production") {
app.use(express.static(path.join('../frontend/build')));
app.get('*',(req,res) => {
res.sendFile(path.resolve(__dirname,'../frontend/build','index.html'))
})
} else {
app.get("/", (req, res) => {
res.send("Api running");
})
}
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
.env:
PORT=8080
MONGO_URI=*****
NODE_ENV=production
Package.json:
{
"name": "mern-shopping-build",
"version": "1.0.0",
"description": "Shopping list built with MERN stack",
"main": "server.js",
"engines": {
"node": "16.4.1",
"npm": "7.18.1"
},
"scripts": {
"build": "cd frontend && npm run dev",
"install-client": "cd frontend && npm install",
"heroku-postbuild": "npm run install-client && npm run build",
"start": "node server.js",
"server": "nodemon backend/server.js",
"client": "npm start && cd frontend",
"dev": "concurrently --kill-others-on-fail \"npm run server\" \"npm start --prefix frontend\""
},
"keywords": [],
"author": "Karim ",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"mongoose": "^5.13.2"
},
"devDependencies": {
"concurrently": "^6.2.0",
"nodemon": "^2.0.9"
}
}
ProcFile:
web node server.js
I Would appreciate any kind of feedback or help, Thank you!

A Procfile is not technically required to deploy simple apps written in most Heroku-supported languages—the platform automatically detects the language and creates a default web process type to boot the application server.
Just make sure to point your root package.json main key to backend/server.js.
Most likely it would work otherwise share your Build Logs to check it further.
{
"main": "backend/server.js"
}

Related

How to make changes to mern app deployed on heroku and how to check the changes before I deploy it in production?

Let me explain further, what i mean is i have created a mern app which is already deployed on heroku now i want to make changes in the app but before i push it again on heroku i want to check my changes locally so how do i do that?
I tried the heroku local command but it starts the client side and cannot fetch the node server routes please help me out here !? here is my code:
node app.js
import express from "express";
import bodyParser from "body-parser";
import dotenv from 'dotenv'
import router from './Routes/auth.js'
import path from 'path';
dotenv.config({path:'./config.env'});
const host = '0.0.0.0';
const port = process.env.PORT || 5000;
const app= express()
app.use(router);
if(process.env.NODE_ENV === "production"){
const __dirname=path.resolve();
app.use(express.static(path.join(__dirname,"/client/build")));
app.get("*",(req,res)=>{
res.sendFile(path.resolve(__dirname,'client','build','index.html'));
})
}
app.listen(port,host,()=>{
console.log(`Server Started Succesfully on port number ${port}`);
})
package.jso(nodejs)
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "app.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "npx nodemon app.js",
"client":"npm start --prefix client",
"dev":"concurrently \"npm start\" \"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",
"body-parser": "^1.19.1",
"cookie-parser": "^1.4.6",
"dotenv": "^10.0.0",
"express": "^4.17.2",
"jsonwebtoken": "^8.5.1",
"moment": "^2.29.1",
"mongoose": "^6.1.8"
}
}
My file system
According to my testing You can do:
Check on Browser Tools: Like Responsiveness
Check your elements in DevTools
All Pages all Div tags elements, responsiveness of app, and design you can check of your app
for node server routes you can check by testing it in Postman API tool
That's it Ready to Deploy

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%.

Create-React-App + Heroku + Api Routes = 404 Errors

I've been able to use React for heroku applications before and I've had successful api calls without React on heroku, but I've never been able to mix the two. Not even once.
The api route works on localhost.
I have incredibly basic code that produces a 404 error whenever I attempt to access one of the api routes on deployment to Heroku. Below is my server.js file:
const express = require("express");
const mongoose = require("mongoose");
const PORT = process.env.PORT || 3001;
const path = require("path");
const routes = require("./routes");
const app = express();
let MONGODB_URI = process.env.MONGODB_URI || "mongodb://localhost/database";
app.use(express.urlencoded({extended:false}));
app.use(express.json());
app.use(express.static("public"));
if (process.env.NODE_ENV === "production") {
app.use(express.static("client/build"));
}
mongoose.connect(MONGODB_URI, {useNewUrlParser: true, useUnifiedTopology: true});
mongoose.connection.on("connected", function() {
console.log("~ Connected To Database ~");
});
app.use(routes);
app.get("*", function(req,res) {
res.sendFile(path.join(__dirname, "/client/build", "index.html"));
});
app.listen(PORT, function() {
console.log("App listening in on " + PORT);
});
My api route is set via the file structure:
routes (located in the same directory as server.js)
index.js
api.js
Here is the index.js:
const apiRoutes = require("./api.js");
const router = require("express").Router();
router.use("/api", apiRoutes);
module.exports = router;
And here is the api.js:
const router = require("express").Router();
router.get("/users/all", function(req, res) {
console.log("Running! The API Route is Being Called!");
res.send("Success");
});
module.exports = router;
Here is the Base react component where the axios call is initiated:
import React, {Component} from "react";
import "./style.css";
import axios from "axios";
class Base extends Component {
testAxios = async () => {
axios.get("/api/users/all");
}
render() {
return (
<div>
<p>Helloooo</p>
<button onClick = {this.testAxios}>Test Axios</button>
</div>
)
}
}
export default Base;
And, finally, here are the relevant package.json files:
For the Client Folder:
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-router-dom": "^5.1.2",
"react-scripts": "3.2.0"
},
"scripts": {
"start": "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"
]
}
}
For the Root Folder:
{
"name": "garbage",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "if-env NODE_ENV=production && npm run start:prod || npm run start:dev",
"start:prod": "node server.js",
"start:dev": "concurrently \"nodemon --ignore 'client'/*'\" \"npm run client\"",
"install": "cd client && npm install",
"client": "cd client && npm run start",
"build": "cd client && npm run build",
"heroku-postbuild": "cd client && npm install --only=dev && npm install && npm run build"
},
"devDependencies": {
"concurrently": "^5.0.0",
"nodemon": "^1.19.4",
"http-server": "^0.11.1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.19.0",
"concurrently": "^5.0.0",
"express": "^4.17.1",
"mongoose": "^5.7.10",
"node": "^12.11.1",
"nodemon": "^1.19.3",
"react": "^16.10.2",
"react-router-dom": "^5.1.2"
},
"repository": {
"type": "git",
"url": "git+https://github.com/garbage/garbage.git"
}
}
I've tried adding a static.json file, and it didn't work. If you have any ideas, please let me know.
I've discovered the source of my problem. In the package.json, it was one line:
"scripts": {
"start": "node server.js",
"start:original": "if-env NODE_ENV=production && npm run start:prod || npm run start:dev"
}
The "start:original" line was, as it implies, the original start function. Rather than rely on the "if-env NODE...", I simply replaced it with "node server.js". When I'm developing and I want to start the server with concurrently, I now just use node run start:dev.
Since then, all my React apps have successfully worked with api routes.

Babel 7 with Express

I am trying to use Babel 7 with Express and I have resolved all errors that have come my way, but I cannot get the Express server to start. I'm unsure if this is because there is no substitute (to my knowledge) for babel-node or if I am doing something wrong.
Here is my package.json
{
"name": "MEAN-Package",
"version": "0.1.0",
"description": "A package for the exercises",
"main": "index.js",
"author": "Chasen Bettinger",
"license": "MIT",
"scripts": {
"start": "nodemon server.js --exec babel"
},
"dependencies": {
"connect": "^3.6.6",
"express": "^4.16.3",
"mongodb": "^3.0.4"
},
"devDependencies": {
"#babel/cli": "^7.0.0-beta.42",
"#babel/core": "^7.0.0-beta.42",
"#babel/preset-env": "^7.0.0-beta.42",
"nodemon": "^1.17.2"
}
}
Here is server.js
import express from "express";
const app = express();
app.use("/", (req, res) => {
res.status(200).send("Hello World");
});
app.listen(3000);
console.log("Server running at http://localhost:3000/");
export { app as default };
My .babelrc file
{
"presets": ["#babel/preset-env"]
}
Console output:
Trying to learn express so any help is appreciated!
You should you babel-node instead of babel. Follow these steps to fix it:
Add babel-node:
yarn add #babel/node --dev
2- Change your start script on package.json to:
"scripts": {
"start": "nodemon server.js --exec babel-node",
}
You should not be using babel-node in production. It is unnecessarily heavy, with high memory usage due to the cache being stored in memory. You will also always experience a startup performance penalty as the entire app needs to be compiled on the fly.
the correct way is:
npm i -D #babel/node
and
"scripts": {
"start": "nodemon server.js --exec babel-node",
}
npm run start

How to add multiple NODE_PATH in package.json?

How do I add multiple NODE_PATH in package.json?
I want to have these multiple paths:
NODE_PATH=./ NODE_PATH=./modules/
or
NODE_PATH=./lib NODE_PATH=./modules/
package.json:
{
"name": "my-app",
"description": "env",
"repository": "https://github.com/xxx.git",
"scripts": {
"dev": "NODE_PATH=./lib NODE_PATH=./ node server.js",
"start": "cross-env NODE_ENV=production NODE_PATH=./ NODE_PATH=./modules/ nodemon --exec babel-node --presets es2015 server.js"
},
"dependencies": {
"cross-env": "^5.0.5",
"express": "^4.15.4"
},
"license": "MIT"
}
server.js:
'use strict'
import express from 'express'
import sample from 'lib/sample'
import config from 'lib'
const app = express()
const isProd = (process.env.NODE_ENV === 'production')
const port = process.env.PORT || 3000
console.log(isProd)
console.log(sample)
console.log(config)
app.get('/', function (req, res) {
const data = {message: 'Hello World!'}
console.log(data);
return res.status(200).json(data);
})
app.listen(port, function () {
console.log('listening on port 3000!')
})
Error:
Error: Cannot find module 'lib/sample'
Any ideas?
The way you are using NODE_PATH in your example, by setting it twice, you are overwriting the writing the value you assign first with the second time.
Instead, set NODE_PATH to multiple paths, delimited by colons (on MacOS or Linux) or semicolons (Windows), like this:
{
"name": "my-app",
"description": "env",
"repository": "https://github.com/xxx.git",
"scripts": {
"dev": "NODE_PATH=./lib:./ node server.js",
"start": "cross-env NODE_ENV=production NODE_PATH=./:./modules/ nodemon --exec babel-node --presets es2015 server.js"
},
"dependencies": {
"cross-env": "^5.0.5",
"express": "^4.15.4"
},
"license": "MIT"
}
See Node.js documentation:
https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders

Resources