How to deploy MERN app, i got 'cannot get /' - node.js

I'm trying to deploy a MERN app on Azure but when I check my url I got cannot the error cannot get /.
I have tried to start my node server on my local machine on production env and I just have a blank page.
I try to check if there is not a path problem in my code so in server.js I have console.log(path.resolve(__dirname, '../client/build')); on my local it show me the correct path but on azure it result of undefined so I guess on azure I can't use __dirname
My app tree is like this:
|--client
|--build
|--node_modules
|--server
|--server.js
|--package.json
My server.js
const dotenv = require('dotenv');
dotenv.config();
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const app = express();
const passport = require("passport");
const path = require('path');
const users = require("./routes/api/users");
// Bodyparser middleware
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json());
// DB Config
const db = require("./config/key.js").mongoURI;
console.log(db);
// Connect to MongoDB
mongoose.Promise = global.Promise;
mongoose.connect(db, { useNewUrlParser: true })
.then(() => console.log("MongoDB successfully connected"))
.catch(err => console.log(err));
// Passport middleware
app.use(passport.initialize());
// Passport config
require("./config/passport")(passport);
// Routes
app.use("/api/users", users);
// Serve static assets if in production
if (process.env.NODE_ENV === 'production') {
// Set static fold
console.log(path.resolve(__dirname, '../client/build'));
app.use(__dirname, 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 up and running on port
${port} !'));
To be honest I don't know what I expect to have.
When I develop on my local I have my node-js server started and my react server started too.
When I try to make some search about how to deploy I can only find tutorial which explain 'copy paste this and it will work' but I have no idea how it work ?
With all my search, I guess I have to run the node server and it will render my front-end from the index.html from my build repository then why on azure I got cannot get / ?
##EDIT##
Actually the problem was Azure doesn't start my server.js in production mode so my condition was never hit.
I don't have this cannot get / any more and I have the same problem in local, I have got a blank page. If I open the inspector I can see it's my index.html and I can in the console I have this error
Uncaught SyntaxError: Unexpected token < main.a3362a52.chunk.js:1
Uncaught SyntaxError: Unexpected token < index.bundle.js:1
Could it be the cause of the blank page ?

Related

find the error while deploying the node.js app to server

I found the error while deploying the node app on the server. the index.js file code
const connectToDb = require("./DBconfig");
const express = require('express')
const router = express.Router();
var cors = require('cors');
connectToDb();
const app = express();
const port = process.env.PORT | 5000;
app.use(cors());
app.use(express.json());
connectToDb();
app.use( '/api/user' ,require('./routes/user') );
app.use( '/api/post' ,require('./routes/post') );
app.get('/', (req, res) => {
res.send('The site is start now')
})
if(process.env.NODE_ENV === "production"){
app.use(express.static("client/build"));
const path = require("path");
app.get("*",(req,res)=>{
res.sendFile(path.resolve(__dirname,'client','build','index.html'))
})
}
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
when I deploy the app and install the node in the server like how I install the node in server I attached the picture in which I show the installation of the node. and above I add the index.js code. It works properly in the local machine but if I hit the URL of backend backendURL it show the service unavailable error message kindly give me the solution to solve this problem.

Heroku only displaying backend of MERN app. How can I fix this?

I've finished working on my first MERN app. It works locally and it was 'successfully built' on Heroku but all that is displayed is the backend-data retrieved for the '/' route from MongoDB.
I've looked at a couple of resources that discuss deploying MERN stack apps to Heroku here:
1. https://www.freecodecamp.org/forum/t/solved-deployment-problem-showing-backend/280178
2. https://www.freecodecamp.org/news/how-to-deploy-a-react-app-with-an-express-server-on-heroku-32244fe5a250/
I've tried integrating these posts with my code but to no avail. I'm not sure how to use the path middleware in tandem with my three existing routes ('/', '/authors', and '/books') and ultimately how that results in the build for index.html. I'm not sure if it makes any difference but I'm using parceljs to build the frontend.
Edit: Added screenshot of folder layout to show where dist folder is located within the project
Below is my server.js file:
if (process.env.NODE_ENV !== "production") {
require("dotenv").config();
}
const express = require("express");
const app = express();
const cors = require("cors");
const path = require("path");
// Middleware
app.use(express.urlencoded({ limit: "10mb", extended: true }));
app.use(express.json({ limit: "10mb" }));
app.use(cors());
// Connect to Mongoose
const mongoose = require("mongoose");
mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true
});
const db = mongoose.connection;
db.on("error", err => console.error(err));
db.once("open", () => console.log("Connected to Mongoose"));
// Define routes
const indexRouter = require("./routes/index");
const authorRouter = require("./routes/authors");
const bookRouter = require("./routes/books");
// Utilize routes
app.use("/", indexRouter);
app.use("/authors", authorRouter);
app.use("/books", bookRouter);
app.listen(process.env.PORT || 3000);
Can you try this code, if your app is in production express will serve static assets and it will redirect user to index.html if user comes to routes other than api routes(by providing app.get('*', ...))
server.js
...
app.use("/books", bookRouter);
if(process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, '/client/dist')))
app.get('*', (req,res) => {
res.sendFile(path.join(__dirname, '/client/dist', 'index.html'))
})
}

Node.js - Specifying URL in Heroku yields internal server error, running locally works fine

I'm having some issues with my application after it's been deployed to heroku. When I specify the URL, or refresh the browser on a page OTHER than the homepage I am getting an "Internal Server error" and the page doesn't load. However when I click the links which naviagte me to those pages from the home page it works fine. When I run the server locally it does not give me this error.
Based on my research this is probably an error on the server side. Here is my code:
Node.js backend
const express = require("express");
const bodyParser = require("body-parser");
const passport = require("passport");
const users = require("./routes/api/users");
const actions = require("./routes/api/dbActions");
const app = express();
// Bodyparser middleware
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json());
// Passport middleware
app.use(passport.initialize());
// Passport config
require("./config/passport")(passport);
// Routes
app.use("/api/users", users);
app.use("/api/dbActions", actions);
// Serve static assets if 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 running on port ${port} !`));
Any idea why this might be happening?
Thanks!!
In my server.js file I included the following:
const path = require('path');
Which seems to have worked for me.

Vue + Express app on heroku not using the SPA in server/public folder

My app is running on heroku and the routes send me JSON files, but what I need is to use the SPA that is in my ./server/public folder as index.html.
When I open the heroku app it send me the JSON file that is sent from the "/" route, but I need it to use the Vue SPA, because of what I did in my front-end client if for some reason you go to a route that doesn't exists it does redirect me to my "/forum" route with the front-end client, but any other route that exists will not work, it will keep sending the JSON of that route.
app/server.js
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const expressValidator = require("express-validator");
const flash = require('connect-flash');
const mongoose = require('mongoose');
const cors = require("cors");
const config = require("./config/database");
if(process.env.NODE_ENV !== "production") require('dotenv').config();
mongoose.connect(config.database, { useNewUrlParser: true, useFindAndModify: false });
let db = mongoose.connection;
db.once("open", () => {
console.log("Connected to MongoDB Atlas");
});
db.on("error", (err) => {
console.log(err);
});
const app = express();
//Body-parser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());
app.use(expressValidator());
app.use(flash());
app.use(cors());
require("./passport")
//Routes
const home = require("./routes/home.js");
const forum = require('./routes/forum.js');
const ranking = require('./routes/ranking.js');
const profile = require('./routes/profile.js');
// Routing
app.use("/", home);
app.use("/forum", forum);
app.use("/profile", profile);
app.use("/ranking", ranking);
// Handle production build
if (process.env.NODE_ENV === "production") {
app.use(express.static(__dirname + '/public/'));
app.get(/.*/, (req, res) => { res.sendFile(__dirname + '/public/index.html') });
}
// PORT
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Server listening on port ${port}`)
});
If you are splitting the frontend and the backend with Vue and Express, you should probably build and host the Vue part statically and then have your Express running on Heroku.
Here is a guide on how to deploy your express app, and then you build and deploy your static Vue page, here are the docs for deploying Vue.

Accessing express routes on heroku directly without serving the react app

Express routes can not be reached directly without serving the react-app on heroku.
I have developed a react-app that runs with a node.js / express backend on heroku. Everything within the react-app works fine.
Now i need to access an express route (e.g. https://example.com/api/info) that makes a call to a mongo db and should only return some JSON.
The problem is, that express always serves the react-app. From within the react-app i can however access the express routes and use them for e.g. login/signup (https://example.com/api/users/login). I just can't access them in production on heroku directly without serving the react-app.
Since heroku decides the port on which the express app lives i can't add a proxy to the react-app's package.json
The react-app is build in the root>client folder.
Please find below the root index.js file of the node.js / express server
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const passport = require('passport');
const keys = require('./config/keys');
const auth = require('./routes/api/auth');
const mail = require('./routes/api/mail');
const newsletter = require('./routes/api/newsletter');
//connect to mongoDB
mongoose.connect(keys.mongoURI)
.then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));
const app = express();
// Body parser middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Passport Config
app.use(passport.initialize());
require('./services/passportJwt')(passport);
// Routes
app.use('/api/users', auth);
app.use('/api/mail', mail);
app.use('/api/newsletter', newsletter);
app.get('/api/info', (req, res) => { //ROUTE DOESN'T WORK, SERVES REACT-APP
res.json({ msg: "Some Info" });
});
// Serve React App in Production
if (process.env.NODE_ENV === 'production') {
// Express will serve up production assets, main.js/main.css
app.use(express.static('client/build'));
// Express will serve up the index.html file if it doesn't recognize the route
const path = require('path');
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
// Use Heroku port or 5000 when in dev
const PORT = process.env.PORT || 5000;
app.listen(PORT);
Expected result:
When reaching "https://example.com/api/info" a JSON output should be received { "msg": "Some info" }.
Instead the react-app is served and the react-app doesnt recognize the route "api/info" within the react-router.
Thanks in advance for your help.

Resources