How to solve page not found error in heroku after deployment - node.js

I'm trying to upload an express/node.js app to heroku. The app is deployed succesfully but when I try to access the url I get error: Not Found.
When I run heroku logs --tail I get:
Error: ENOENT: no such file or directory, stat '/client/build/index.html'
so I think I'm doing something wrong with the directories and the statics folder
this is my server.js file:
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const cors = require("cors");
const path = require("path");
const users = require("./routes/api/users");
const profile = require("./routes/api/profile");
const matches = require("./routes/api/matches");
const app = express();
//body-parser middleware
app.use(bodyParser.urlencoded({ extended: false, limit: "50mb" }));
app.use(bodyParser.json({ limit: "50mb" }));
//db config
const db = require("./config/keys").mongoURI;
//cors
app.use(cors());
//connect to mongoose
mongoose
.connect(db, { useNewUrlParser: true })
.then(() => console.log("MongoDB connected"))
.catch(err => console.log(err));
//Passport middleware
app.use(passport.initialize());
app.use("/images", express.static(path.join(__dirname + "/images")));
//Passport config
require("./config/passport")(passport);
//Use route
app.use("/api/users", users);
app.use("/api/profile", profile);
app.use("/api/matches", matches);
//Serve static assets if in production
if (process.env.NODE_ENV === "production") {
app.enable("trust proxy");
//Set static folder
app.use(express.static(path.join(__dirname, "/../client/build")));
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname + "/../client/build/index.html"));
});
}
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`server running on port ${port}`));
I also include an image of the folders "positions"

I solved this issue by defining build and install command in my package.json. Heroku would look for a build command for production in there.
"scripts": {
"build": "cd client && npm run build",
"install": "cd client && npm install",
"start": "node server",
"server": "nodemon server",
"client": "npm start --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\""
},

I think it should be like this
app.use("/images", express.static(path.join(__dirname, "images")));
Edit: Actually your app is expecting to find a file at /../client/build/index.html but that file does not exist (which is what ENOENT error means). So you either need to create the expected directory structure or else configure your application such that it looks in the correct directory for index.html. That whats i understand now, i hope this would help you.

I also got similar error. For me the problem is I have wrong script for build in package.json file, So build is not creating at all.
Verify you have "heroku-postbuild" script as below in package.json file.
"scripts": {
"start": "node server.js",
"server": "nodemon server.js",
"client": "npm start --prefix client",
"clientinstall": "npm install --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"
},

Related

Node.js not responding to API calls with my app? Working perfectly during development environment, however not when hosted

Trying to make my first Vue application, simple game with MEVN stack. Working perfect interacting with backend on development environment, however when hosting it doesn't fetch the data from the server.
Anyone able to point out what I have incorrect with the below?
More info below:
File structure:
/root
 |- config.js
 |- server.js
 |- package.json + package-lock.json
 |- client/
  |- vue.config.json
  |- ... (rest of dist, src, node_modules, public etc.)
 |- models/
  |- Elf.js + HighScore.js
 |- routes/
  |- api/
   |- elf.js + highScore.js
config.js
module.exports = {
hostUrl: process.env.HOST_URL,
mongoURI: process.env.MONGO_URI,
PORT: process.env.PORT || 3000,
};
server.js
const express = require("express");
const app = express();
const port = 3000;
const mongoose = require("mongoose");
const { PORT, mongoURI } = require("./config.js");
// routes
const Player = require("./routes/api/player");
const Elf = require("./routes/api/elf");
const HighScore = require("./routes/api/highScore");
// cors is a middleware that allows us to make requests from our frontend to our backend
const cors = require("cors");
// morgan is a middleware that logs all requests to the console
const morgan = require("morgan");
// body-parser is a middleware that allows us to access the body of a request
const bodyParser = require("body-parser");
const path = require("path");
app.use(cors());
// use tiny to log only the request method and the status code
app.use(morgan("tiny"));
app.use(bodyParser.json());
// chek if we are in production
if (process.env.NODE_ENV === "production") {
// check if we are in production mode
app.use(express.static("client/dist"));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "dist", "index.html"));
});
}
// test if server is running and connected to mongoDB
app.get("/", (req, res) => {
res.send("Hello World!");
});
// app.get("/", (req, res) => {
// res.send("Hello World!");
// });
// use routes
app.use("/api/", Player);
app.use("/api/", Elf);
app.use("/api/", HighScore);
mongoose
.connect(mongoURI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useUnifiedTopology: true,
})
.then(() => console.log("MongoDB connected..."))
.then(() => {
// log uri to console
console.log(`MongoDB connected to ${mongoURI}`);
})
.catch((err) => console.log(err));
app.listen(PORT, () => {
console.log(`Example app listening at ${PORT}`);
});
package.json
{
"name": "week1",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"server": "nodemon server.js --ignore 'client/'",
"client": "npm run serve --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\"",
"start": "node server.js",
"build": "npm install --prefix client && npm run build --prefix client"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.20.1",
"bootstrap": "^5.2.3",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"mongoose": "^6.7.5",
"morgan": "^1.10.0",
"portal-vue": "^2.1.7"
},
"devDependencies": {
"concurrently": "^7.6.0",
"nodemon": "^2.0.20"
}
}
Running within my dev environment at root dir using 'npm run dev', the app works flawlessly send/ receive data from mongoDB during this time. This starts up http://localhost:8080/. Also tried install of 'npm install -g serve' and running 'serve -s dist', this starts up serving at localhost:36797 and working flawlessly too.
I have tried to setup on Vercel & Render, both giving me the same issue where I'm not getting much feedback and the data isn't being fetched. Anyone else has this issue before?

Routing won't work once app is deployed to Heroku

I have a fullstack app I deployed on Heroku with React in the frontend and Node.js for my backend. Initially, my frontend would display but the server wasn't running. Now that I've added more dependencies in my package.json, it seems the server is running but the frontend won't render. My page looks like this:
When I look at the Heroku logs, this is what the output is:
It seems that the server is starting on a port (in this instance Port: 17789 and 46894) but then something else tries to run on the same port which causes an error. The port for my server is set to process.env.PORT in the index.js file on my backend. I'm not sure if this is what I need to change or not. Here is the index.js:
import express from 'express';
import bodyParser from 'body-parser';
import mongoose from 'mongoose';
import cors from 'cors';
import postRoutes from './routes/posts.js';
const app = express();
//Middleware
app.use(bodyParser.json({ limit: '30mb', extended: true }));
app.use(bodyParser.urlencoded({ limit: '30mb', extended: true }));
app.use(cors());
app.use('/posts', postRoutes);
const CONNECTION_URL =
'mongodb+srv://caseyclinga:123abc#passport.czhpd.mongodb.net/recollections?retryWrites=true&w=majority';
const PORT = process.env.PORT || 5000;
mongoose
.connect(CONNECTION_URL, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() =>
app.listen(PORT, () => console.log(`Server running on Port: ${PORT} `))
)
.catch((err) => console.log(err));
And lastly, here is my package.json:
{
"scripts": {
"build": "cd client && npm run build",
"install-client": "cd client && npm install",
"heroku-postbuild": "npm run install-client && npm run build",
"server": "cd server && nodemon server.js",
"develop": "concurrently --kill-others-on-fail \"npm run server\" \"npm run start --prefix client\"",
"start": "concurrently --kill-others-on-fail \"npm run server\" \"npm run start --prefix client\""
},
"dependencies": {
"body-parser": "^1.20.0",
"concurrently": "^7.2.1",
"cors": "^2.8.5",
"express": "^4.18.1",
"mongoose": "^6.3.4",
"nodemon": "^2.0.16"
}
}
Does anyone know where the issue may be in this?
In your code you have app.use('/posts', postRoutes);, but you are trying to get /post instead of /posts.

How to Setup Proxy Target in React Native with Nodejs?

Trying to configure proxy in react native with node to run axios calls.
Tried the following code in server/package.json
"proxy": {
"/*": {
"target": "http://localhost:5000/"
}
},
"scripts": {
"start": "node index.js",
"server": "nodemon index.js",
"client": "cd ../client && yarn ios",
"dev": "concurrently \"yarn server\" \"yarn client\""
}
server/authRouter.js
const authRouter = require('express').Router();
authRouter.get('/test', (req, res) => {
res.send('proxy success');
});
module.exports = authRouter;
server/index.js
const express = require('express');
const authRouter = require('./authRouter');
const app = express();
app.use('/auth', authRouter);
const PORT = process.env.PORT || 5000;
app.listen(PORT);
client/app.js
await axios.get('/auth/test');
When I run yarn dev and test an axios call, it logs the following error
LOG [Error: Network Error]
any help would be much appreciated.
Try calling the proxy directly in axios
http://localhost:5000/auth/test
I'm not sure why it doesn't work that way, even i had a problem in the past.

Deploy React App to heroku cannot connect backend

I am trying to deploy my app which using node.js, react and MongoDB to Heroku; The deploy was succeeded; However, the website cannot fetch data from MongoDB.
The error is GET http://localhost:5000/comment net::ERR_CONNECTION_REFUSED and Uncaught (in promise) Error: Network Error, I think it is because I don't have node server.js running in the backend. can anyone help me with how to deploy this correctly?
my pakage.json in the backend is
"client-install": "npm install --prefix myprofile",
"start":"node server.js",
"server":"nodemon server.js",
"client":"npm start --prefix myprofile",
"dev":"concurrently \"npm run server\" \"npm run client\"",
"heroku-postbuild":"NPM_CONFIG_PRODUCTION=false npm install --prefix myprofile && npm run build --prefix myprofile"
}
And my server.js is
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const path = require("path");
require("dotenv").config();
const app = express();
const port = process.env.PORT || 5000;
app.use(express.json());
app.use(cors());
//app.use(express.static(path.join(__dirname,'./myprofile/build')));
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true
});
const connection = mongoose.connection;
connection.once("open", () => {
console.log("MongoDB data connected");
});
const CommentRouter = require("./CommentRouter");
app.use("/comment", CommentRouter);
if (process.env.NODE_ENV === "production") {
app.use(express.static("myprofile/build"));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "myprofile", "build", "index.html"));
});
}
app.listen(port, () => console.log(`Server is running on ${port}`));
Thank you very much in advance!
If you are deploying this project to heroku, your start command and your server.js looks similar to this example so that's a good start.
Are you setting your environment variables with heroku, specifically process.env.ATLAS_URI? I would imagine heroku doesn't know where your MongoDB database is located.

React content not found heroku deployment

Im trying to deploy a nodejs and react app to Heroku. It works completely fine local and it does serve my backend, but i get Not Found on anything else than my api endpoints. It seems like its not running the build script in the client folder. Can anyone help me spot where it goes wrong?
server.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const path = require('path');
const projects = require('./routes/api/projects');
const app = express();
// Body parser middlewaree
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// DB Config
const db = require('./config/keys').mongoURI;
// Connect to DB
mongoose
.connect(
db,
{ useNewUrlParser: true }
)
.then(() => console.log('mongoDB connected.'))
.catch(err => console.log(err));
// Setting up routes
app.use('/api/projects', projects);
// Serve static assets if in production
app.use(express.static(path.join(__dirname, '/client/build')));
app.get('*', (req, res) => {
res.sendfile(path.join((__dirname, '/client/build/index.html')));
});
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server up and running on ${port}`));
package.json
"scripts": {
"client-install": "npm install --prefix client",
"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"
},
I've deployed successfully to Heroku using the following code (I've just answered an alike question here):
app.use(express.static(path.join(__dirname, './client/build')))
app.get('*', function(_, res) {
res.sendFile(path.join(__dirname, './client/build/index.html'), function(err) {
if (err) {
res.status(500).send(err)
}
})
})
Also, if you're trying to deploy a create-react-app application, you can use this buildpack. Buildpacks are scripts that are run when your app is deployed. They are used to install dependencies for your app and configure your environment.
You can see the full code here of how I usually deploy Heroku applications.

Resources