Load this site: https://portfolio-website.azurewebsites.net/
Expected behaviour: Loads the site content properly.
Actual behaviour: You will see a blank page with no contents.
But try adding, /{anything} at the end of the url e.g. https://portfolio-website.azurewebsites.net/x, the website loads perfectly. React router is not catching the path "/" which is really confusing but when you go to about link and then click on home the site loads the homepage.
I am currently using azure, but the same results in heroku too. Help!
You can view the source code here and make contributions here: https://github.com/CrestNiraj12/portfolio-website
App.js
const App = ({ page, overflowHidden, isLandscape, dialogShow, loading }) => {
useEffect(() => {
if (overflowHidden) document.body.style.overflow = "hidden";
else document.body.style.overflow = "visible";
isLandscape(window.innerWidth > window.innerHeight);
}, [page, isLandscape, overflowHidden]);
const routes = [
{ path: "/", Component: Home, isExact: true },
{ path: "/about", Component: About, isExact: false },
{ path: "/update/posts/:postId", Component: EditPost, isExact: false },
{ path: "/posts/:postPath", Component: Post, isExact: false },
{ path: "/auth/login", Component: Login, isExact: false },
{ path: "/auth/register", Component: Signup, isExact: false },
{
path: "/auth/password/recover",
Component: ConfirmRecoverPassword,
isExact: false,
},
{ path: "/user/dashboard", Component: Dashboard, isExact: false },
{ path: "/posts", Component: Posts, isExact: false },
{ path: "/users", Component: Users, isExact: false },
{ path: "/user/addpost", Component: AddPost, isExact: false },
{ path: "/user/confirm/:token", Component: ConfirmMail, isExact: false },
{
path: "/password/recover/token/:token",
Component: ResetPassword,
isExact: false,
},
{ path: "/*", Component: Home, isExact: false },
];
return (
<>
<Flash />
{dialogShow && <Dialog />}
{loading && <Preloader />}
<Router history={createBrowserHistory()}>
{[HOME, ABOUT, ALL_POSTS, POST].includes(page) && <Navbar />}
<Switch>
{routes.map(({ path, Component, isExact }) => (
<Route
key={path}
path={path}
exact={isExact}
component={Component}
/>
))}
</Switch>
</Router>
</>
);
};
Server.js
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const passport = require("./backend/config/passport");
const session = require("express-session");
const MongoStore = require("connect-mongo")(session);
const helmet = require("helmet");
const path = require("path");
require("dotenv").config({
path: `.env.${process.env.NODE_ENV.trim() || "development"}`,
});
const app = express();
const port = process.env.PORT || 5000;
const postsRouter = require("./backend/routes/posts");
const usersRouter = require("./backend/routes/users");
const authenticationRouter = require("./backend/routes/authentication");
app.use(cors());
app.use(helmet());
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(express.static(__dirname + "/client/public"));
const url = process.env.CONNECTION_URL;
mongoose
.connect(url, {
auth: {
user: process.env.DB_USER,
password: process.env.DB_PASS,
},
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
useFindAndModify: false,
})
.catch((err) => console.log(err));
const connection = mongoose.connection;
const sessionStore = {
name: "authSession",
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: true,
cookie: { httpOnly: true },
store: new MongoStore({
mongooseConnection: connection,
secret: process.env.STORE_SECRET,
ttl: 24 * 60 * 60 * 1000,
autoRemove: "interval",
autoRemoveInterval: 10,
}),
};
if (process.env.NODE_ENV === "production") {
const hour = 24 * 60 * 60 * 1000;
app.set("trust proxy", 1);
sessionStore.cookie.secure = true;
sessionStore.cookie.maxAge = hour;
sessionStore.cookie.expires = new Date(Date.now() + hour);
}
app.use(session(sessionStore));
app.use(passport.initialize());
app.use(passport.session());
app.use("/posts", postsRouter);
app.use("/user", usersRouter);
app.use("/auth", authenticationRouter);
connection
.once("open", () => {
console.log("Established database connection!");
})
.catch((err) => console.log(err));
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"));
});
}
app.listen(port, () => console.log("Server running on port: " + port));
Server-side package.json
{
"name": "portfolio-website",
"version": "1.0.0",
"description": "My Personal website",
"main": "server.js",
"repository": {
"type": "git",
"url": "https://github.com/CrestNiraj12/portfolio-website.git"
},
"scripts": {
"start": "NODE_ENV=production node server",
"azure": "NPM_CONFIG_PRODUCTION=false npm run imagemin && npm install --prefix client && npm run build --prefix client",
"imagemin": "imagemin client/src/images/*.{jpg,png,gif} --out-dir=client/src/images",
"dev": "concurrently \"nodemon server\" \"cd client && npm start\" \"cd client && npm run watch-sass\"",
"serve": "serve -s client/build"
},
"author": "Niraj Shrestha",
"license": "ISC",
"engines": {
"node": ">=12.0.0",
"npm": ">=6.0.0"
},
"dependencies": {
"bcryptjs": "^2.4.3",
"connect-mongo": "^3.2.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-session": "^1.17.1",
"express-validator": "^6.6.0",
"helmet": "^3.23.3",
"imagemin-cli": "^6.0.0",
"lodash": "^4.17.19",
"mongoose": "^5.9.22",
"multer": "^1.4.2",
"nodemailer": "^6.4.11",
"nodemailer-smtp-transport": "^2.7.4",
"passport": "^0.4.1",
"passport-local": "^1.0.0"
},
"devDependencies": {
"concurrently": "^5.3.0",
"nodemon": "^2.0.4",
"serve": "^11.3.2"
}
}
You're serving react static files with express, before setting the reactjs routes:
app.use(express.static(__dirname + "/client/public"));
...
app.get("/*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
But the problem is : there is a static index.html
file in the react public folder. that's why you're seeing a blank page on root. it's the static index.html
file in react public folder, and it doesn't contains the react script tag. react-scripts
uses it and appends the react <script src="...">
tag to it. so you can't remove it. instead set a route for root that points to react, before serving the static files :
app.get("/", (req, res) => { // the root
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
}
...
app.use(express.static(__dirname + "/client/public")); // serving static files
...
app.get("/*", (req, res) => { // all remaining addresses
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
}