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
Related
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 read bunch of blogs about MERN application deployment on Heroku but they all are uses separate package.json for client and server!
Is it possible to use one package.json file?
My Project Structure
My package.json
{
"name": "ecommerce",
"version": "0.1.0",
"private": true,
"author": "Dweep Panchal",
"license": "ISC",
"dependencies": {
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/user-event": "^7.2.1",
"braintree-web-drop-in-react": "^1.1.1",
"concurrently": "^5.2.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.1.2",
"react-scripts": "3.4.1",
"react-stripe-checkout": "^2.6.3",
"body-parser": "^1.19.0",
"braintree": "^2.22.0",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-jwt": "^5.3.3",
"express-validator": "^6.4.0",
"formidable": "^1.2.2",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.15",
"mongoose": "^5.9.7",
"stripe": "^8.46.0",
"uuid": "^7.0.3"
},
"scripts": {
"server": "cd ./backend && node app.js",
"start": "concurrently \"npm run server\" \"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:8000",
"devDependencies": {
"nodemon": "^2.0.3"
},
"engines": {
"node": "10.16.0",
"npm": "6.9.0"
}
}
app.js
require("dotenv").config({ path: "../.env" });
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const cors = require("cors");
const app = express();
// Routes
const authRoutes = require("./routes/auth");
const userRoutes = require("./routes/user");
const categoryRoutes = require("./routes/category");
const productRoutes = require("./routes/product");
const orderRoutes = require("./routes/order");
const stripeRoutes = require("./routes/stripepayment");
const braintreeRoutes = require("./routes/braintreepayment");
// DB Connection
mongoose
.connect(
`mongodb+srv://${process.env.DB_NAME}:${process.env.DB_PASS}#${process.env.DB_PROJECT}-xi8tq.mongodb.net/${process.env.DB_PROJECT}?retryWrites=true&w=majority`,
{
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
useFindAndModify: true,
}
)
.then(() => console.log("DB Connected!"))
.catch(() => console.log("Failed to Connect DB"));
// Middleware
app.use(bodyParser.json());
app.use(cookieParser());
app.use(cors());
// My Routes
app.use("/api", authRoutes);
app.use("/api", userRoutes);
app.use("/api", categoryRoutes);
app.use("/api", productRoutes);
app.use("/api", orderRoutes);
app.use("/api", stripeRoutes);
app.use("/api", braintreeRoutes);
// Server Connection
const port = process.env.BACKEND_PORT || 8000;
app.listen(port, () => console.log(`Server Running at Port ${port}`));
When i deployed this application on heroku then project url shows:
Invalid Host header
Whole project: https://github.com/dweep612/ecommerce
Let me quickly explain how deploying any Reactjs and express to heroku work. The goal is to generate a build folder with npm run build and then starting the server to serve static content from that build folder.
In the heroku documentation, it states that heroku-postbuild runs before the start scripts. This is a perfect place to do npm run build to generate a build folder and then using the start script to run your server code. From there your server should be using express.static and pointing where ever you generated your build folder.
That is why people like to use a server package.json because it won't interfere with the react start script. Now the problem I immediately see is that you are not using the scripts correct nor are you pointing at that build folder that you are suppose to generate.
In your package.json create a start script that starts your app.js file and then create a heroku-postbuild that will generate a build folder. Like below
"scripts": {
"start": "cd ./backend && node app.js",
"heroku-postbuild": "npm run build",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
After that you should have app.use(express.static(<<location of build folder>>)) in your app.js . Add the code below in your app.js
if (process.env.NODE_ENV === "production") {
app.use(express.static("../build"));
}
The reason I said ../build is because your build folder is outside of the backend folder.
I also checked out your entire code and there are other small configuration issue. For example, if you are deploying to heroku , you should be using process.env.PORT
Yes it's possible, if your backend serves your frontend. Two package.json is useful when your backend and your frontend run on two separate node programs.
The invalid host headers are probably due to how your server handles headers, but since you didn't posted a minimal reproducible example, as of now we can't help you further.
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
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.