Routing doesn't work after doing react build - node.js

So I created a routing as shown below,
import React from "react";
import ReactDOM from "react-dom";
import MainComponent from "./components/mainComponent";
import LoaderComponent from "./components/loaderComponent";
import * as serviceWorker from "./serviceWorker";
import { Route, BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(
<Router>
<div>
<Route exact path="/home" component={MainComponent} />
<Route exact path="/loader" component={LoaderComponent} />
<Route exact path="/" component={MainComponent} />
</div>
</Router>,
document.getElementById("root")
);
serviceWorker.unregister();
The routing works absolutely fine when the app is started through
npm run start
When I hit localhost:3000/home it renders the MainComponent.
But after the build, it says Cannot GET /home
npm run build
When checking the app(after build) through nodeJs, only the default routing () works. Remaining routes throw Cannot GET error in the browser.
Attached below the nodejs server.js file
const express = require("express");
const bodyParser = require("body-parser");
const path = require("path");
const dotenv = require("dotenv");
dotenv.config();
require("./db/db_connection");
require("./scheduler");
const app = express();
//This is to make sure request body is accessible in express
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
//Router for the api end points
const leaderboardRoutes = require("./routes");
app.use("/api/v1", leaderboardRoutes);
//Views are present inside build folder
app.use(express.static(path.join(__dirname, "build")));
//Application hosted port
const port = process.env.PORT || 3000;
app.listen(port, function () {
console.log(`Application running on port ${port}`);
});
I'm also attaching the package.json file for reference,
{
"name": "test-app",
"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",
"axios": "^0.19.2",
"body-parser": "^1.19.0",
"bootstrap": "^4.4.1",
"connect-timeout": "^1.9.0",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"http": "0.0.1-security",
"material-ui": "^0.20.2",
"mongoose": "^5.9.9",
"node-schedule": "^1.3.2",
"path": "^0.12.7",
"pure-react-carousel": "^1.25.2",
"react": "^16.13.0",
"react-bootstrap": "^1.0.0-beta.17",
"react-circular-progressbar": "^2.0.3",
"react-dom": "^16.13.0",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.0",
"request": "^2.88.2"
},
"scripts": {
"start": "react-scripts start",
"start-server": "npm run build && nodemon server.js",
"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"
]
}
}
Please help me in understanding what' going wrong or what I've missed.
Thanks in advance.

I have not used react-scripts but after build, if its showing Cannot GET /*, then it seems to me that the files are going into some directory under the build directory, meaning the path you're trying to access is not complete. You might want to check that and use in your build configuration.
For example, in my case, I used a mount path for my application, so it looked like:
http://localhost:3000/myapp where myapp was the mount path.
Then I had used public name for a directory in webpack config path for I wanted to put my files in there, and then I had used publicPath with value myapp, which means files were going into build/public/myapp, so when I hit the URL above, the server looked for index file in this path and loaded the file.

Related

Is it possible to host MERN application on Heroku using single package.json?

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.

Refused to load the image 'https://diary2020.herokuapp.com/favicon.ico'

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

Deploy React with Heroku

Hi i'm trying to deploy my project with heroku but it's impossible i don't understand
I already did like that on other project but this time it doesn't works in my server.js i have this code :
const express = require("express");
const graphqlHTTP = require("express-graphql");
const cors = require("cors");
const schema = require("./schema");
const path = require("path");
const app = express();
//allow Cross origin
app.use(cors());
app.use(
"/graphql",
graphqlHTTP({
schema,
graphiql: true
})
);
app.use(express.static('public'));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, 'public', 'index.html'));
});
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
In my app.js who is in my Client folder i modify uri for AplolloClient :
import React from 'react';
import './App.css';
import Logo from "./logo.png";
import Matchs from './components/Matchs'
import MatchDetail from './components/MatchDetail'
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "#apollo/react-hooks";
import { BrowserRouter as Router, Route } from "react-router-dom";
const client = new ApolloClient({
uri: "/graphql"
});
function App() {
return (
<ApolloProvider client={client}>
<Router>
<div className="container">
<img
src={Logo}
alt="Nba App"
style={{ width: 300, display: "block", margin: "auto" }}
/>
<Route exact path="/" component={Matchs} />
<Route exact path="/match/:gameId" component={MatchDetail} />
</div>
</Router>
</ApolloProvider>
);
}
export default App;
in my package.json from my client folder i add a proxy :
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"#apollo/react-hooks": "^3.1.3",
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.3.2",
"#testing-library/user-event": "^7.1.2",
"apexcharts": "^3.15.5",
"apollo-boost": "^0.4.7",
"classnames": "^2.2.6",
"graphql": "^14.6.0",
"lodash.flowright": "^3.5.0",
"react": "^16.12.0",
"react-apexcharts": "^1.3.6",
"react-apollo": "^3.1.3",
"react-dom": "^16.12.0",
"react-icons": "^3.9.0",
"react-router-dom": "^5.1.2",
"react-scripts": "3.3.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build && mv build ../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"
]
},
"proxy": "http://localhost:5000"
}
And i made a script to build and move in public/build
But when i deploy in heroku i have always
VM165:1 POST http://localhost:4000/graphql net::ERR_CONNECTION_REFUSED
But i don't know where he take this Url because i think i change all places where it could be problematic
Thanks a lot

Deployed my app on heroku but got error: Failed to load resource: net::ERR_CONNECTION_REFUSED

My app's front-end is Reactjs and backend is Node js. I used express server and graphql-express server. I deployed my app successfully. But it starts with data is loading and then nothing shows. But if I run locally npm start then the heroku app is start working.
This is the error I get it in browser
This is my server's package json file. If i run in terminal npm run dev. It opens my react js app.
{
"name": "backend",
"version": "1.0.0",
"description": "personish vol 2",
"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": "ISC",
"dependencies": {
"concurrently": "^5.0.2",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-graphql": "^0.9.0",
"graphql": "^14.5.8",
"pg": "^7.15.1",
"pg-hstore": "^2.3.3",
"sequelize": "^5.21.3"
}
}
This is my react's package json
{
"name": "client",
"version": "0.1.0",
"private": true,
"engines": {
"node": "13.3.0",
"npm": "6.13.0"
},
"dependencies": {
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.3.2",
"#testing-library/user-event": "^7.1.2",
"apollo-boost": "^0.4.7",
"axios": "^0.19.0",
"firebase": "^7.6.1",
"graphql": "^14.5.8",
"pg": "^7.15.1",
"react": "^16.12.0",
"react-apollo": "^3.1.3",
"react-dom": "^16.12.0",
"react-dropzone": "^10.2.1",
"react-redux": "^7.1.3",
"react-redux-firebase": "^3.0.5",
"react-router-dom": "^5.1.2",
"react-scripts": "3.3.0",
"redux": "^4.0.4",
"redux-firestore": "^0.11.0",
"redux-thunk": "^2.3.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"
]
}
}
This is my express and graphql-express server.
const express = require("express");
const app = express();
const graphqlHTTP = require("express-graphql");
const schema = require("./schema");
const cors = require("cors");
const path = require("path");
app.use(cors());
app.use(
"/graphql",
graphqlHTTP({
schema,
pretty: true,
graphiql: true
})
);
app.use(express.static(path.join(__dirname, "build")));
app.get("/*", (req, res) => {
res.sendFile(path.join(__dirname, "build", "index.html"));
});
const port = process.env.PORT || 8081;
app.listen(port, () =>
console.log(`✅ Example app listening on port ${port}!`)
);
This is my react's app file. Where I use Apollo boost to connect with react app and node js app. I think the error comes from here, dont know how to fix it
import React from "react";
import { ApolloClient, HttpLink, InMemoryCache } from "apollo-boost";
import { ApolloProvider } from "react-apollo";
const client = new ApolloClient({
link: new HttpLink({
uri: "http://localhost:8081/graphql"
}),
cache: new InMemoryCache()
});
This is my heroku app
https://databaseapp2020.herokuapp.com/
your heroku dyno/app would have a name, you would use that to hit your graphql from say a graphiql playground on your laptop, or your react-app... if your heroku app was actually named databaseapp2020 and running then you would use the following assuming your cors was setup properly in the dyno environment variables
https://databaseapp2020.herokuapp.com/graphql

React is compiled with no errors but no component is displayed on browser

I am new to React.
I have Installed React using npm install create-react-app .
I have created a server.js file, and my file structure is here.
package.json
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.17.1",
"babel-loader": "^7.1.2",
"body-parser": "^1.18.2",
"classnames": "^2.2.5",
"express": "latest",
"lodash": "latest",
"morgan": "^1.9.0",
"prop-types": "latest",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-scripts": "1.0.17",
"validator": "^9.2.0",
"webpack-hot-middleware": "^2.21.0",
"html-webpack-plugin": "latest"
},
"scripts": {
"start": "nodemon --watch server --exec babel-node -- server.js",
"start-dev": "node server.js",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-preset-env": "^1.6.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-react-hmre": "^1.1.1",
"nstall": "^0.2.0",
"react-hot-loader": "^3.1.3",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
"redux-thunk": "^2.2.0",
"webpack": "^3.10.0",
"webpack-dev-middleware": "^2.0.3"
}
}
server.js File
import path from "path";
import express from 'express';
import webpack from 'webpack';
import webpackMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import webpackConfig from './webpack.config.dev';
import bodyParser from 'body-parser';
import users from './src/Actions/users';
const app = express();
app.use(bodyParser.json());
app.use('/api/users',users);
const compiler = webpack(webpackConfig);
app.use(webpackMiddleware(compiler, {
hot:true,
publicPath: webpackConfig.output.publicPath,
noInfo: true
}));
app.use(webpackHotMiddleware(compiler));
app.use(express.static('public'));
app.get('*',(req,res)=>{
res.sendFile(path.join(__dirname,'./public/index.html'));
});
app.listen(5001, () => console.log('Example app listening on port 5001!'));
Webpack.config.js file
const path = require('path');
const webpack = require('webpack');
module.exports = {
devtool:'eval-source-map',
entry: [
'webpack-hot-middleware/',
path.resolve(__dirname, './src/index.js')
],
output:{
path: path.join(__dirname, 'public'),
filename: "[name].bundle.js",
publicPath: '/'
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
],
devServer: {
hot: true,
inline: false,
contentBase: "./"
},
module:{
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loaders: [
'react-hot-loader/webpack',
'babel-loader?' +
'babelrc=false,' +
'presets[]=es2015,' +
'presets[]=react'
]
}]
},
resolve:{
extensions:['.js']
}
}
On running npm run start . It listens to the sufficient port and it compiles everything with no errors. But, On Browser it displays no components of React. It just Runs and does nothing.
src/index.js File
import React from 'react';
import ReactDOM from 'react-dom';
import registerServiceWorker from './registerServiceWorker';
import { BrowserRouter, Link, Route } from 'react-router-dom'
import {Provider} from 'react-redux';
import thunk from 'redux-thunk';
import { createStore, applyMiddleware } from 'redux';
import App from './App';
import Greet from './Greetings';
import SignupPage from './signup/signup';
const stores = createStore(
(state = {}) => state,
applyMiddleware(thunk)
);
ReactDOM.render((
<Provider store={stores}>
<BrowserRouter >
<div>
<Route component={App}>
</Route>
<div id={'jumbo'} className='container css'>
<Route exact path='/' component={Greet}/>
<Route path='/signup' component={SignupPage}/>
</div>
</div>
</BrowserRouter>
</Provider>
), document.getElementById('app'));
registerServiceWorker();
How can I clear my code. I did not know where i did mistakes. Help me !!
Thanks in advance. :-)
I think you are confused with what create-react-app does and how it works. From create-react-app docs:
You don’t need to install or configure tools like Webpack or Babel.
They are preconfigured and hidden so that you can focus on the code.
Just create a project, and you’re good to go.
Under the hood it builds your project with webpack.
So if you want to modify/add webpack you should look at npm run eject command.
Running npm run eject copies all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. Commands like npm start and npm run build will still work, but they will point to the copied scripts so you can tweak them. At this point, you’re on your own.
So seems like you dont need your own webpack.config.js file. Moreover if you would like to have the webpack development server proxy your API requests to your API server you can add the next: "proxy": "http://localhost:3001/" into your package.json file to allow webpack-dev-server redirect your requests to your server.
Hope it make sence

Resources