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.
Related
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"
}
I am trying to get a simple "Hello World" on Firebase.
I am have running fine locally, as it's a very simple app.
Directory Structure is:
/
--/client
----/public
------/src
--------/App.js
----/...
----/package.json
--/public
--/app.js
--/package.json
--/...
package.json at /
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start:all": "concurrently \"npm run start\" \"npm --prefix client run start\" --kill-others",
"start": "node app.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"concurrently": "^5.2.0",
"cors": "^2.8.5",
"express": "^4.17.1"
}
}
app.js at /
const express = require('express');
const cors = require('cors');
const app = express();
const port = 5000;
app.use(cors());
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.get('/test', (req, res) => {
res.json('TEST ROUTE!');
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
package.json at /client
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/user-event": "^7.2.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.1"
},
"proxy": "http://localhost:5000",
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build && npm run clean && mv build ../public",
"clean": "rimraf ../public",
"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"
]
}
}
App.js at /client/src/
import React from 'react';
import './App.css';
const App = () => {
fetch('/test')
.then((response) => response.json())
.then((data) => console.log(data));
return <div className="App">REACT App.js</div>;
};
export default App;
running
npm run start:all
Will result in Express running on 5000 and React running on :3000
I will then see the message from my client "React App.js" and the server via the browser console "TEST ROUTE".
When I run:
firebase deploy
I see the message from the frontend "React App.js", but I in the console I see:
localhost:5000/test:1 Failed to load resource: net::ERR_CONNECTION_REFUSED
(index):1 Uncaught (in promise) TypeError: Failed to fetch
How do I deploy this app to Firebase so that the frontend and backend can talk to each other?
Firebase Hosting does not support deployment of node apps (or any backend code). It just serves static assets like HTML, CSS, JS, and images.
Firebase Hosting does support proxying requests to Cloud Functions, which can run code on nodejs, and even Express apps. This requires significantly more complex setup and deployment, and you can't use app.listen() - you must accept the framework that Cloud Functions provides for handling your API endpoints. Read the documentation for more information.
I have created my Blog using MERN application.
So now I am hosting this in digitalocean server but I am getting ECONNREFUSED error.
I have followed most of the document in both youtube and other for hosting it.
I can see my client running on ex: http://154.23.54.44:3000 but it is not running without :3000 as well as neither connecting my mlab conection.
Any suggestion for solving this and running this aplication in real production
Many Thanks.
//server package.json
"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\"",
"heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix client && npm run build --prefix client"
}
//server.js
const express = require('express');
const mongoose = require('mongoose');
const path = require('path');
const config = require('config');
const app = express();
//bodyParser middleware
app.use(express.json());
//DB config
const db = config.get('mongoURI');
//connect to mongo
mongoose
.connect(db, {useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true})
.then(() => console.log('MongoDB connected...'))
.catch(err => console.log(err));
//use routes
app.use('/api/users', require('./routes/api/users'));
app.use('/api/auth', require('./routes/api/auth'));
// 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 || 80;
app.listen(port, () => console.log(`Server started on PORT ${port}`));
//client (package.json)
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.3.2",
"#testing-library/user-event": "^7.1.2",
"axios": "^0.19.2",
"bootstrap": "^4.4.1",
"bootstrap-less": "^3.3.8",
"moment": "^2.24.0",
"node-sass": "^4.13.1",
"react": "^16.13.1",
"react-dom": "^16.13.1"
},
"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"
]
},
"proxy": "http://localhost:5000"
}
//error on production
I built an app using React and Node Js and now I want to deploy it over Firebase. I am new to these frameworks and just couldn't figure out what went wrong.
While running the server locally everything works fine but when I run 'firebase serve' I get a response that says "You need to enable JavaScript to run this app".
The app is deployed here -> Expense Tracker
You can see the XHR request, transactions, in dev tools.
Thanks in advance.
client/package.json:
{
"name": "expense-tracker",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.4.1",
"#testing-library/user-event": "^7.2.1",
"axios": "^0.19.2",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-scripts": "3.4.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"
]
},
"proxy": "http://localhost:5000"
}
server.js:
const path = require('path');
const express = require('express');
const dotenv = require('dotenv');
const colors = require('colors');
const morgan = require('morgan');
const transactions = require('./routes/transactions');
const connectDB = require('./config/db');
dotenv.config({ path: './config/config.env' });
const app = express();
app.use(express.json());
if (process.env.NODE_ENV === 'development') {
app.use(morgan('dev'));
}
app.use('/api/v1/transactions', transactions);
if (process.env.NODE_ENV === 'production') {
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 in ${process.env.NODE_ENV} mode on port ${PORT}`.yellow.bold));
firebase.json:
{
"hosting": {
"public": "client/build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
}
}
package.json:
{
"name": "expense-tracker",
"version": "1.0.0",
"description": "Backend for Expense Tracker",
"main": "server.js",
"scripts": {
"start": "node server",
"server": "nodemon server",
"client": "npm start --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\""
},
"author": "Keshavram Kuduwa",
"license": "MIT",
"dependencies": {
"colors": "^1.4.0",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"firebase-admin": "^8.10.0",
"mongoose": "^5.9.4",
"morgan": "^1.9.1"
},
"devDependencies": {
"concurrently": "^5.1.0",
"nodemon": "^2.0.2"
},
"homepage": "."
}
I think you are trying to run this express-node instance as a firebase function
try doing
exports.app = functions.https.onRequest(app);
at the end of your server.js file
OR
create firebase hosting and a firebase function
run your website in firebase hosting and run your node-express instance as a firebase function
I used MERN(MongoDb, Express, React js, Node) technology for my app. It works locally fine. but When I deployed in heroku I am getting internal server error. I might made mistake in setup but I can't see it.
In google Chrome console I got this error: Refused to load the image 'https://diary2020.herokuapp.com/favicon.ico' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.
When I used Heroku logs I got this:
This is my server setup:
require("dotenv").config();
const express = require("express");
const cors = require("cors");
const morgan = require("morgan");
const app = express();
const logs = require("./src/logs.js/logs");
const mongoose = require("mongoose");
const path = require("path");
const helmet = require("helmet");
//middlewares
app.use(cors());
app.use(morgan("dev"));
app.use(express.json());
app.use(helmet());
//connect to db
mongoose
.connect(process.env.MONGODB_URI, {
useUnifiedTopology: true,
useNewUrlParser: true
})
.then(() => console.log("DB Connected!"))
.catch(err => {
console.log(err);
});
app.use("/api", logs);
app.use(express.static(__dirname + "build")); //
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "build", index.html));
});
const port = process.env.PORT || 5000;
app.listen(port, () => {
console.log(`Server is running port ${port}`);
});
In my client folder first run npm run build then I cut it and pasted it outside of the client. Then I connected to server. As you can above. But it does not recognize the build's index.html
This is my backend package.json
{
"name": "form",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"start": "node server.js",
"server": "node server.js",
"client": "npm start --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\""
},
"author": "alak",
"license": "MIT",
"dependencies": {
"concurrently": "^5.1.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"helmet": "^3.21.3",
"heroku": "^7.39.0",
"jquery": "^3.4.1",
"mongoose": "^5.9.3",
"morgan": "^1.9.1",
"path": "^0.12.7",
"react-router-dom": "^5.1.2", //I MISTAKENLY INSTALLED IT.BUT I THINK IT SHOULD NOT BE A PROBLEM
"react-transition-group": "^4.3.0" //I MISTAKENLY INSTALLED IT. BUT I THINK IT SHOULD NOT BE A PROBLEM
}
}
This is React's package.json
{
"name": "client",
"version": "0.1.0",
"engines": {
"node": "13.10.1",
"npm": "6.13.7"
},
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.3.2",
"#testing-library/user-event": "^7.1.2",
"moment": "^2.24.0",
"react": "^16.13.0",
"react-dom": "^16.13.0",
"react-scripts": "3.4.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"proxy": "http://localhost:5000",
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
The ReferenceError you're seeing is caused by index.html not being wrapped in quotations - node is trying to evaluate the html property of an object named index which I'm willing to bet is not what you meant.
app.use(express.static(__dirname + "build")); //
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "build", index.html)); // <- try "index.html"
});
The probable reason why you getting this error is likely because you've added /build folder to your .gitignore file or generally haven't checked it into git. So when you git push heroku master, build folder you're referencing don't get push to heroku. And that's it shows this error.
T its work properly locally