Cannot GET / MERN stack deployment on heroku - node.js

Hi i am having trouble when trying to deploy my mern stack to heroku. every way i have tried to deploy it i get the same error of get the error Cannot GET /. i have gone through the tutorials but still no luck
this is my server. js file
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const users = require("./routes/api/users");
const payees = require("./routes/api/payees");
const transactions = require("./routes/api/transactions");
const path = require('path')
const app = express();
// Bodyparser middleware
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json());
// DB Config
const db = require("./config/keys").mongoURI;
// Connect to MongoDB
mongoose
.connect(
db,
{ useNewUrlParser: true }
)
.then(() => console.log("MongoDB successfully connected"))
.catch(err => console.log(err));
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
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/payees", payees);
app.use("/api/transactions", transactions)
if(process.env.NODE_ENV === '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 ${port} !`));
module.exports = { app };
and this is my package.json file
{
"name": "STUBANK",
"version": "1.0.0",
"description": "",
"main": "server.js",
"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\"",
"test": "mocha",
"heroku-postbuild": "cd client && npm install && npm run build"
},
"author": "Ojini Jude",
"license": "MIT",
"dependencies": {
"#material-ui/core": "^4.11.2",
"axios": "^0.21.1",
"bcryptjs": "^2.4.3",
"body-parser": "^1.18.3",
"chai": "^4.2.0",
"chai-http": "^4.3.0",
"classnames": "^2.2.6",
"crypto-random-string": "^3.3.0",
"dotenv": "^6.2.0",
"express": "^4.16.4",
"is-empty": "^1.2.0",
"jsonwebtoken": "^8.5.1",
"jwt-decode": "^3.1.2",
"mdbreact": "^5.0.1",
"mocha": "^8.2.1",
"mongoose": "^5.3.6",
"particles-bg": "^2.5.0",
"passport": "^0.4.1",
"passport-jwt": "^4.0.0",
"password-validator": "^5.1.1",
"react": "^17.0.1",
"react-bootstrap": "^1.4.0",
"react-dom": "^17.0.1",
"react-dropdown": "^1.9.0",
"react-redux": "^7.2.2",
"react-router-dom": "^5.2.0",
"react-scripts": "^4.0.1",
"react-search-box": "^2.0.2",
"react-search-field": "^1.2.0",
"react-select": "^3.1.1",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"supertest": "^6.0.1",
"validator": "^13.5.1"
},
"devDependencies": {
"concurrently": "^4.1.2",
"nodemon": "^1.19.4"
},
"engines": {
"node": "12.16.0"
}
}
Any help would be greatly appreciated.
file structure

Related

How to do server side rendering with node reactjs?

I have created a sample project in reactjs and using node for backend. I have build react project with webpack. Now I want to render my react app from the server-side but got stuck with an error:
const express = require('express');
const path = require('path');
const logger = require('morgan');
const bodyParser = require('body-parser');
const cors = require('cors');
const { renderToString } = require("react-dom/server");
const { StaticRouter } = require("react-router-dom")
const React = require("react");
const App = require('./src/App')
const session = require('express-session');
const routes = require('./server/index');
const port = process.env.PORT || 3000;
const app = express();
app.use(express.static(path.join(__dirname, 'dist')));
app.use(cors());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
//app.use(cookieParser());
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', '*');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET,POST');
// Request headers you wish to allow
res.setHeader(
'Access-Control-Allow-Headers',
'X-Requested-With,content-type',
);
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
// end
app.use('/', routes);
app.use((req, res, next) => {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
if (app.get('env') === 'development') {
app.use((err, req, res, next) => {
res.status(err.status || 500);
res.json({
message: err.message,
error: err,
});
});
}
app.use((err, req, res, next) => {
res.status(err.status || 500);
res.json({
message: err.message,
error: {},
});
});
router.get("*", (req, res) => {
// Render the component to a string.
const html = ReactDOMServer.renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);
const finalDocument =`<html>
<head>
<title>Your App Title</title>
</head>
<body>
<div id="root">${html}</div>
</body>
</html>
`;
res.send(finalDocument);
});
app.listen(port, () => {
console.log('Api Server running on port' + port);
});
module.exports = app;
package.json
{
"name": "ssrnodereact",
"version": "0.1.0",
"private": true,
"dependencies": {
"#material-ui/core": "^4.12.2",
"#material-ui/icons": "^4.11.2",
"#testing-library/jest-dom": "^5.14.1",
"#testing-library/react": "^11.2.7",
"#testing-library/user-event": "^12.8.3",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"cryptr": "^6.0.2",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"express-session": "^1.17.2",
"formik": "^2.2.9",
"helmet": "^4.6.0",
"morgan": "^1.10.0",
"nodemailer": "^6.6.3",
"path": "^0.12.7",
"pg": "^8.7.1",
"prettier": "^2.3.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-ga": "^3.3.0",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"typescript": "^4.3.5",
"web-vitals": "^1.1.2",
"yup": "^0.32.9"
},
"scripts": {
"build": "webpack --mode production",
"start": "npm run build && nodemon server.js",
"test": "react-scripts test",
"eject": "react-scripts eject",
"format": "prettier --write ./**/*.{js,jsx,ts,tsx,css,md,json,html} --config ./.prettierrc"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"#babel/core": "^7.15.0",
"#babel/preset-env": "^7.15.0",
"#babel/preset-react": "^7.14.5",
"babel-loader": "^8.2.2",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^3.2.0",
"react-hot-loader": "^4.13.0",
"ts-loader": "^8.3.0",
"webpack": "^4.44.0",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "^3.11.2"
}
}
Got following error:
error
I have tried the following solutions but have not been able to resolve the error:
React Serverside rendering Unexpected token, JSX and Babel
I'm not sure if React is a framework that suits your needs. Server-side rendering can be accomplished much easier and more efficiently using a framework like NextJS.
You can check this plugin and it has examples for you to do the SSR easily.

How to use a Postgres db on heroku with Axios and Vue?

I making a spa with Vue and want to deploy this on Heroku and provision a database with Postgres.
I managed to get the app to run on Heroku, with a node server. I added the db and the connection (in the same file) and it is working in production.
But I want to make the HTTP-request to de the db with Axios and test this locally before deployment. And this is where I'm stuck.
I've copied the DATABASE_URL the a .env, but still no access to the database. When I print the value to the console it is always undefined.
My server.js:
const express = require("express");
const serveStatic = require("serve-static");
const path = require("path");
const port = process.env.PORT || 8080;
// Connection to the database
const { Client } = require('pg');
const client = new Client({
connectionString: process.env.DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
});
client.connect();
client.query('SELECT table_schema,table_name FROM information_schema.tables;', (err, res) => {
if (err) throw err;
for (let row of res.rows) {
console.log(JSON.stringify(row));
}
client.end();
});
//
const app = express();
//here we are configuring dist to serve app files
app.use("/", serveStatic(path.join(__dirname, "/dist")));
// this * route is to serve project on different page routes except root `/`
app.get(/.*/, function (req, res) {
res.sendFile(path.join(__dirname, "/dist/index.html"));
});
app.listen(port);
console.log(`app is listening on port: ${port}`);
UserService.js:
import axios from 'axios';
// the single Axios instance we use for calls
const apiClient = axios.create({
//baseURL: 'http://localhost:5000',
baseURL: process.env.DATABASE_URL, // with ssl?
withCredentials: false, // this is the default
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
});
export default {
/* with pagination */
getUsers() {
console.log(process.env.DATABASE_URL);
return apiClient.get('/users');
},
};
package.json:
{
"name": "test-deploy-heroku",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"start": "node server.js"
},
"dependencies": {
"axios": "^0.21.1",
"core-js": "^3.6.5",
"dns": "^0.2.2",
"express": "^4.17.1",
"pg": "^8.5.1",
"pg-native": "^3.0.0",
"vue": "^2.6.11",
"vue-router": "^3.2.0",
"vuetify": "^2.4.0",
"vuex": "^3.4.0"
},
"devDependencies": {
"#vue/cli-plugin-babel": "~4.5.0",
"#vue/cli-plugin-eslint": "~4.5.0",
"#vue/cli-plugin-router": "~4.5.0",
"#vue/cli-plugin-vuex": "~4.5.0",
"#vue/cli-service": "~4.5.0",
"#vue/eslint-config-prettier": "^6.0.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^6.2.2",
"prettier": "^2.2.1",
"sass": "^1.32.0",
"sass-loader": "^10.0.0",
"vue-cli-plugin-vuetify": "~2.3.1",
"vue-template-compiler": "^2.6.11",
"vuetify-loader": "^1.7.0"
}
}
I copied the config vars to my local .env file
heroku config:get CONFIG-VAR-NAME -s >> .env
And the started the process with
heroku local
But I still can not connect to the db with axios.
I searched all over, but didn't find an answer.
You may need to add require('dotenv').config() to the top of your server.js file
if (process.env.NODE_ENV === 'development') require('dotenv').config()

front end not being deployed in Heroku

I'm trying to deploy my first MERN website to heroku. I have been following different tutorials but I am having trouble connecting the front end with the back end, although they connect fine in development mode.
Just to clarify: the only one that is bein deployed is the server side. I am not being able to deploy the front end.
client's package.json proxy:
"proxy": "http://localhost:5000"
Server package.json:
{
"name": "pictshare",
"version": "1.0.0",
"description": "Image Sharing Application",
"main": "server.js",
"scripts": {
"start": "node server.js",
"server": "nodemon server",
"build": "cd client && npm run build",
"install-client":"cd client && npm install",
"heroku-postbuild":"npm run install-client && npm run build",
"client": "npm start --prefix client",
"dev": "concurrently -n 'server,client' -c 'red, green' \"npm run server\" \"npm run client\""
},
"author": "",
"license": "MIT",
"dependencies": {
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.0",
"config": "^3.3.1",
"ejs": "^3.0.2",
"express": "^4.17.1",
"express-validator": "^6.4.0",
"form-data": "^3.0.0",
"gravatar": "^1.8.0",
"gridfs-stream": "^1.1.1",
"jsonwebtoken": "^8.5.1",
"merge-images": "^1.2.0",
"method-override": "^3.0.0",
"moment": "^2.24.0",
"mongoose": "^5.9.7",
"multer": "^1.4.2",
"multer-gridfs-storage": "^4.0.2",
"node": "^13.12.0",
"nodemailer": "^6.4.6",
"path": "^0.12.7",
"react-draggable": "^4.2.0",
"request": "^2.88.2"
},
"devDependencies": {
"concurrently": "^5.1.0",
"minimist": "^1.2.5",
"nodemon": "^2.0.2"
}
}
Server.js:
const express = require('express');
const connectDB = require('./config/db');
const app = express();
const bodyParser = require('body-parser')
connectDB();
//Initialize Middleware
app.use(express.json({ extended: false }));
app.use(bodyParser.urlencoded({ extended: false }))
app.get('/', (req, res) => res.send('API Running'));
...
app.use('/api/posts', require('./routes/api/posts'));
if (process.env.NODE_ENV === 'production'){
app.use(express.static('client/build'))
}
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
Mongoose:
const mongoose = require('mongoose');
const config = require('config');
const db = process.env.MONGODB_URI || config.get('mongoURI');
const connectDB = async () => {
try {
await mongoose.connect(db, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true,
useNewUrlParser: true,
});
console.log('MongoDB Connected...');
} catch(err) {
console.error(err.message);
process.exit(1);
}
}
module.exports = connectDB;
I really appreciate any ideas or points of views!!
Thank you so much everyone!
Maybe you already did the job, let me point out a thing here in your code:
app.use(express.static('client/build'))
you maybe need to put like this :
const app = express();
const path = require('path');
app.use('/static', express.static(path.join(`${__dirname}/client/build`)));
then just send the file when the server is online:
app.get('/*', (req, res) => {
res.sendFile(path.join(`${__dirname}/client/build/`));
});
If you have .env file. Try adding this NODE_ENV = production in it.

basic nodejs and express server setup not working

This should be very simple, steps I took:
1)used vue cli3 to create vue project (that worked fine).
2)created a server folder on the root level
3)created an index.js file
4)created api/routes/users.js
I am getting in the browser at http://localhost:4000/api/add Cannot GET api/add.
Here is my index file:
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const app = express();
//middleware
app.use(bodyParser.json());
app.use(cors());
const users = require('./api/routes/users');
app.use('api/add', users);
const port = process.env.PORT || 4000;
app.listen(port, () => console.log(`Listening on port ${port}...` ));
Below this is my users.js file:
const mongodb = require('mongodb');
const router = express.Router();
router.get('/', (req, res) => {
res.send('hello');
})
module.exports = router;
Here is what my package JSON looks like, not sure if this somehow creates problems since I first made the frontend and then started the backend.
{
"name": "fastpo",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"start": "node server/index.js",
"dev": "nodemon server/index.js",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.18.0",
"body-parser": "^1.18.3",
"cors": "^2.8.5",
"express": "^4.16.4",
"mongoose": "^5.4.11",
"morgan": "^1.9.1",
"nodemon": "^1.18.10",
"serve-favicon": "^2.5.0",
"vue": "^2.5.22",
"vue-compose": "^0.7.1",
"vuetify": "^1.3.0"
},
"devDependencies": {
"#vue/cli-plugin-babel": "^3.4.0",
"#vue/cli-plugin-eslint": "^3.4.0",
"#vue/cli-service": "^3.4.0",
"babel-eslint": "^10.0.1",
"eslint": "^5.8.0",
"eslint-plugin-vue": "^5.0.0",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.1",
"vue-cli-plugin-vuetify": "^0.4.6",
"vue-template-compiler": "^2.5.21",
"vuetify-loader": "^1.0.5"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {},
"parserOptions": {
"parser": "babel-eslint"
}
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
Forgot to add "/" here before api: app.use('api/add', users);
should be app.use('/api/add', users)

I get 404 error in the localhost even though I already did "npm run build"

I'm trying to send a small demo made with React to production. I did not make the demo with create-react-app, I did it by hand. I used express.js to serve the application.
When I run the command "SET NODE_ENV = production node server.js" (I'm in Windows, that's why SET) and I go to the localhost I keep getting GET / 404, even though I already made the command "npm run build".
Since it's the first time I do this, I really have no clue what happens.
This is my package.json:
{
"name": "app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --colors",
"serve": "webpack-dev-server --content-base build/ --color --
progress",
"start": "npm run build && npm run serve",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Pepe",
"license": "MIT",
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-eslint": "^8.2.2",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.4.0",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"css-loader": "^0.28.9",
"eslint": "3.15.0",
"eslint-config-airbnb": "14.1.0",
"eslint-loader": "^1.9.0",
"eslint-plugin-import": "2.2.0",
"eslint-plugin-jsx-a11y": "4.0.0",
"eslint-plugin-react": "6.10.0",
"extract-text-webpack-plugin": "^3.0.2",
"html-webpack-plugin": "^2.30.1",
"identity-obj-proxy": "^3.0.0",
"jshint": "^2.9.6",
"style-loader": "^0.20.2",
"url-loader": "^0.5.8",
"webpack": "^3.3.0",
"webpack-dev-server": "^2.9.7"
},
"dependencies": {
"bootstrap": "^4.0.0",
"compression": "^1.7.3",
"express": "^4.16.4",
"mime": "^1.4.1",
"morgan": "^1.9.1",
"normalize.css": "^8.0.0",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-router-dom": "^4.1.1",
"uuid": "^3.2.1"
},
"standard": {
"ignore": [
"/build/"
]
},
"eslintConfig": {
"extends": [
"standard",
"standard-jsx"
]
},
"stylelint": {
"extends": "stylelint-config-standard"
},
"optionalDependencies": {
"win-node-env": "^0.4.0"
}
}
And here is my server.js:
const { createServer } = require('http');
const express = require('express');
const compression = require('compression');
const morgan = require('morgan');
const path = require('path');
const normalizePortprocess = port => parseInt(port, 10);
const PORT = normalizePortprocess(process.env.PORT || 3000);
const app = express();
const dev = app.get('env') !== 'production';
if (!dev) {
app.disable('x-powered-by');
app.use(compression());
app.use(morgan('common'));
app.use(express.static(path.resolve(__dirname, 'build')));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'build', 'index.html'));
});
}
if (dev) {
app.use(morgan('dev'));
}
const server = createServer(app);
server.listen(PORT, err => {
if(err) throw new err;
console.log(`Server listen in ${PORT}`);
});
Everything would seem to work correctly except that despite having executed to many times the command "npm run build", still nothing appears
You are running in a development environment, and only handling that GET request if !dev.
if (!dev) { // here is the problem
// ...
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'build', 'index.html'));
});
}
Instead, either remove the if statement and always handle this route, or change it to if(dev).

Resources