I am trying to create a simple node.js app on heroku. Here is my app.js:
console.log("Starting App")
const express = require('express')
const app = express()
const port = 3000
app.listen(process.env.PORT || port, () => console.log(`App listening on port ${port}!`))
app.get('/', (req,res) => {
res.sendFile(__dirname+'/public/index.html')
})
app.get('/style', (req,res) => {
res.sendFile(__dirname+'/public/main.css')
})
app.get('/script', (req,res) => {
res.sendFile(__dirname+'/public/script.js')
})
app.get('/changelog', (req,res) => {
res.sendFile(__dirname+'/public/changelog.txt')
})
here is my package.json file:
{
"name": "",
"version": "0.0.0",
"description": "",
"main": "/App.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.16.4"
}
}
and here is my Procfile:
web: node app.js
I am deploying this to heroku via github, and whenever I run the program it gives me an error, saying Cannot find module '/app/app.js.' I have made everything lowercase and removed forward slashes. I still get this error: Error: Cannot find module '/app/app.js' Can anyone help?
In package.json, change "main": "/App.js" to "main": "app.js"
make sure package.json is at the same level as app.js
If app.js is in another folder, make sure to provide the full path from directory holding the package.json file.
Related
EDIT: To be clear, this only happening when i'm trying to host the app. Works PERFECT during local environment testing..
When trying to fetch data from my backend getting an error in Chrome saying that JS is not enabled. (IT IS) so that is not the issue..
Thinking there may be an issue with my package.json maybe if the commands are incorrect for use on the host machine? Have tried Render & Heroku same issues.
I had tried to run the commands within my local environment and the app works flawlessly fetching data as intended. Only when hosting the app do I not get any data back from the server when making API call from the front end, instead get JS not enabled error in the Network tab and no errors on Front End that I can see..
Hosted app to see network error: https://elf-invasion.herokuapp.com/
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"
}
}
I am having a difficult time trying to figure out what is going on here. When I deploy my React/Express app to Heroku, everything builds and deploys with no errors, but my React frontend is completely blank.
I am getting this errors in the browser console:
Uncaught SyntaxError: Unexpected token < 1.b1e0c624.chunk.js:1
Uncaught SyntaxError: Unexpected token < main.48d62be5.chunk.js:1
manifest.json:1 Manifest: Line: 1, column: 1, Unexpected token.
Here is how my server.js file is setup to send the root index.html file:
app.use('/static', express.static(path.join(__dirname, 'client/build')));
app.get('*', function(_, res) {
res.sendFile(path.join('/app/client/build/index.html'), function(err) {
if (err) {
console.log(err);
res.status(500).send(err);
}
});
});
And this is what the top portion (code redacted for brevity) of my React apps package.json looks like:
{
"name": "client",
"version": "0.1.0",
"homepage": "https://radiant-tor-66940.herokuapp.com/",
"private": true,
}
I figured setting the homepage in the client's package.json would do it but nothing. I am really unsure what to do here. I am thinking that something might be off with a path or something like that.
Update
This is still an issue for me. Below I have shared more code in hopes that this is can aid in my case. I am getting a new error this time when the page loads:
{"errno":-2,"code":"ENOENT","syscall":"stat","path":"/app/server/client/build/index.html","expose":false,"statusCode":404,"status":404}
This error above is being sent from the error block in this code:
app.get('*', function(req, res) {
res.sendFile('/client/build/index.html', { root: __dirname }, function(err) {
if (err) {
res.status(500).send(err);
}
});
});
I have changed my server.js file to serve the index.js file like this versus using a template literal (trying anything at this point):
//Express
const express = require('express');
const app = express();
const port = process.env.PORT || 8000;
//Core Node Modules
const fs = require('fs');
const path = require('path');
//Middleware
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(express.static(path.join(__dirname, '/client/build')));
app.get('*', function(req, res) {
res.sendFile('index.html', { root: __dirname }, function(err) {
if (err) {
res.status(500).send(err);
}
});
});
app.listen(port, err => {
if (err) console.info(`Error: The server failed to start on ${port}`);
else console.info(`****** Node server is running on ${port} ******`);
});
This is the root level package.json for my server. I have added the heroku-postbuild script to build the React app located in client:
"scripts": {
"test": "jest",
"start": "node server/server.js",
"heroku-postbuild": "cd client && npm install --only=dev && npm install && npm run build"
},
"engines": {
"node": "~9.10.1",
"npm": "~5.6.0"
}
Here is the package.json for the React app located in /client:
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.19.0",
"lodash": "^4.17.11",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react-redux": "^6.0.0",
"react-router-dom": "^4.3.1",
"react-scripts": "2.1.3",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
"styled-components": "^4.1.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"proxy": "http://localhost:8000/"
}
Here is what the files looks like on the Heroku server:
1st image: Root Directory
2nd image: /client directory
3rd image: /client/build directory
4th image: /client/build/static directoy
The issue was in my server.js file.
Originally it was express.static(path_join(__dirname, '/client/build'))
it needed to be: express.static(path_join(__dirname, '../client/build'))
This is the case because my server.js file is located in /server and it was trying to find /client/build inside of /server instead of the root app directory on Heroku.
As we don't have access to your server, it's hard to tell the reason behind your problem. I would guess you misconfigured your express server as those three error messages indicate, that the server only returns the index.html file.
And as HTML is not valid Javascript, you get unexpected token errors.
I would also guess, that the following line has no effect at all, which means there are no files in this folder (or not those you want to access).
app.use('/static', express.static(path.join(__dirname, 'client/build')));
Trying to work with reactjs (create-react-app) and now including expressjs. What I've done is
move my folder/* to folder/client/* (deleting node_modules)
cd folder/client/ and npm install to recreate the node_modules
*it works as before, the app renders well
cd folder and npm init
npm install express --save
write the folder/server.js
add the proxy settings in /folder/client/package.json
npm run start in /folder and in /folder/client
Then, I go to localhost:3000 and I get the reactjs app, without express anywhere. Then I go to localhost:8080 and I get the express result, which is indeed the same page as before but without being executed by react (nothing wrong here, I assume)
And then I go to localhost:3000/test and it gets proxied to express, where I see in the terminal the console.log of server.js
So I cannot proxy localhost:3000, but I can localhost:3000/whatever. What is wrong?
server.js
const express = require('express');
const path = require('path'); // haven't installed, should I?
const app = express();
app.use(express.static(path.join(__dirname, 'build'))); // of no use here
app.get('/ping', function (req, res) { // this one works
return res.send('pong');
});
// app.get('', function (req, res) { // doesn't work
// app.get('*', function (req, res) { // doesn't work
// app.get('.', function (req, res) { // doesn't work
// app.get('.*', function (req, res) { // doesn't work
// app.get('./', function (req, res) { // doesn't work
app.get('./*', function (req, res) { // doesn't work
console.log('hey') // never seen
res.sendFile(path.join(__dirname, 'client/src', 'index.html'));
});
app.get('/test', function (req, res) { // this one works
console.log('hey2') // I do see this when calling localhost:3000/test
res.sendFile(path.join(__dirname, 'client/src', 'index.html'));
});
app.listen(process.env.PORT || 8080);
package.json (/)
{
"name": "ouyea",
"version": "0.1.1",
"description": "This project was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app).",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"repository": {
"type": "git",
"url": "git+https://xxxx"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://xxxx"
},
"homepage": "https://xxxx",
"dependencies": {
"express": "^4.16.4"
}
}
package.json (/client)
{
"name": "client",
"version": "0.1.1",
"private": true,
"dependencies": {
"axios": "^0.18.0",
"googleapis": "^33.0.0",
"papaparse": "4.6.0",
"react": "^16.4.2",
"react-dom": "^16.4.2",
"react-scripts": "1.1.4",
"semantic-ui-css": "^2.4.0",
"semantic-ui-react": "^0.82.5"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"proxy": {
"": { // I know comments don't work, but I put them here for clarity, none of them worked
// "*": {
// ".": {
// "/": {
"target": "http://localhost:8080"
},
"/test": {
"target": "http://localhost:8080"
}
}
}
The purpose of the express server is to simply a) render the base HTML page from your dist folder, and b) supply data from endpoints that you set up as routes in Express which can be accessed by your React client application. There are apps (universal) that can render React pages from Express but that's not what you're doing here with create-react-app.
I trying deploy my MERN app to heroku.
After build success on heroku doesn't see a API routes:
Steps:
On localhost I run concurrently node server and client (create-react-app).
Server on port 5000 and client on port 3000.
After this I fetch from API routes /hotels Array with items and connect it to Redux store and display it.
Properly behavior:
Localhost: works fine
Heroku: broken (didn't connect with API)
This is my server.js file:
const express = require('express');
const path = require('path');
const app = express();
const http = require('http');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const cookieSession = require('cookie-session');
const passport = require('passport');
const morgan = require('morgan');
const keys = require('./API/config/keys');
//######### MODELS #########
require('./API/models/Users');
//######### SERVICES #########
require('./API/services/passport');
//######### MONGODB CONNECT #########
mongoose.connect(MONGO_CONNECT);
//######### ROUTES #########
const hotelsRoutes = require('./API/routes/hotels');
const countRoutes = require('./API/routes/count');
const topRoutes = require('./API/routes/top');
// Use routes
app.use('/hotels', hotelsRoutes);
app.use('/count', countRoutes);
app.use('/top', topRoutes);
app.use(morgan('dev'));
app.use('/uploads', express.static('uploads'));
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use(
cookieSession({
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
keys: [keys.cookieKey]
})
);
app.use(passport.initialize());
app.use(passport.session());
require('./API/routes/authRoutes')(app);
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;
const server = http.createServer(app);
server.listen(port);
Package.json (server):
{
"name": "root-react-hotel-app",
"version": "0.1.0",
"main": "server.js",
"scripts": {
"client": "cd client && yarn start",
"start": "node server.js",
"start-api": "nodemon server.js",
"dev": "concurrently \"yarn start-api\" \"yarn client\"",
"build": "cd client && npm install && yarn build"
},
"devDependencies": {
//
},
"dependencies": {
//
}
}
Package.json (client):
{
"name": "client-react-hotel-app",
"version": "0.1.0",
"private": true,
"proxy": {
"/auth/google": {
"target": "http://localhost:5000"
},
"/api/*": {
"target": "http://localhost:5000"
},
"/*": {
"target": "http://localhost:5000"
}
},
"dependencies": {
// Here are dependencies
},
"scripts": {
"build-css": "node-sass-chokidar src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
"start-js": "react-scripts start",
"start": "npm-run-all -p watch-css start-js",
"build-js": "react-scripts build",
"build": "npm-run-all build-css build-js",
"eject": "react-scripts eject",
"compile:sass": "node-sass src/css/styles.scss src/css/styles.css -w",
"generate:doc": "sassdoc src/css/abstracts/_mixins.scss",
"test": "cross-env NODE_ENV=test jest --config=jest.config.json",
"test-coverage": "cross-env NODE_ENV=test jest --coverage --config=jest.config.json",
"test-ci": "cross-env NODE_ENV=test jest --config=jest.config.json --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js"
},
"devDependencies": {
// Here are devDependencies
}
}
Also trying with static.json file and Procfile:
{
"root": "client/build/",
"setupFiles": [
"<rootDir>/client/src/setupTests.js"
]
}
Anyone can help?
Since your express server is serving both your react bundle and your api routes, in:
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
You need to protect your api routes in the 'app.get' when deploying to heroku (production mode). You can use a simple regex in order to serve all routes to your react bundle except '/api' (or whatever your api endpoint looks like, /API in your case above). It works running locally because you are running your api and react app on separate ports, not the same server.
Usually something like:
if (process.env.NODE_ENV === 'production') {
app.get(/^\/(?!api).*/, (req, res) => { // don't serve react app to api routes
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
};
I am trying to create a simple rest endpoint using node.js.
I am following the tutorial https://medium.freecodecamp.com/building-a-simple-node-js-api-in-under-30-minutes-a07ea9e390d2
the folder structure is notable/app/routes/ and the routes folder contains the index.js and note_routes.js files
I am able to run the command npm run dev, and the output shown is:
> notable#1.0.0 dev /Users/tejanandamuri/Desktop/notable
> nodemon server.js
[nodemon] 1.11.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node server.js`
We are live on 8000
after this. in the postman, when I try to call the http://localhost:8000/notes, it is returning 404 error with the response body Cannot POST /notes
Here are my files:
server.js:
const express = require('express');
const MongoClient = require('mongodb').MongoClient;
const bodyParser = require('body-parser');
const app = express();
const port = 8000;
require('./app/routes')(app, {});
app.listen(port, () => {
console.log('We are live on ' + port);
});
index.js:
// routes/index.js
const noteRoutes = require('./note_routes');
module.exports = function(app, db) {
noteRoutes(app, db);
// Other route groups could go here, in the future
};
note_routes.js
module.exports = function(app, db) {
app.post('/notes', (req, res) => {
// You'll create your note here.
res.send('Hello')
});
};
package.json:
{
"name": "notable",
"version": "1.0.0",
"description": "my first rest api",
"main": "server.js",
"dependencies": {
"body-parser": "^1.17.2",
"express": "^4.15.3",
"mongodb": "^2.2.28"
},
"devDependencies": {
"nodemon": "^1.11.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js",
"dev": "nodemon server.js"
},
"author": "venkata",
"license": "ISC"
}
Change line 6 in server.js to require('./routes/note_routes')(app, {});
This assumes your file tree looks something like this:
.
+--/node_modules // this contains a ton of sub-folders
+--/routes
+ +--index.js
+ +--note_routes.js
+--package.json
+--server.js