I have a server on express.js and there is a static folder in its root directory, it contains several react apps, something like this:
app:
static:
react1
react2
I am trying to make sure that when accessing the /react1 and /react2 addresses, the express will display the required application.
app.js:
app.use (express.static(path.join(__ dirname, "static")));
app.use ("/", indexRouter);
index.router:
router.get('/react1', (req, res) => {
res.sendFile(path.join (__dirname, '..', 'static', 'react1', 'index.html'))
});
router.get('/react2', (req, res) => {
res.sendFile(path.join (__dirname, '..', 'static', 'react2', 'index.html'))
});
When I try to navigate through these handles, I get a blank page. What am I doing wrong?
Your app.js & index.router looks fine.
You might wanna add * to the router.
For instance
router.get('/react1/*', (req, res) => {
I think the issue is in how the static content is built.
Make sure to add PUBLIC_URL to build script in package.json.
For instance: "build": "PUBLIC_URL=/admin react-scripts build",
You can refer this youtube video for a detailed explanation.
Related
It’s the first time I deployed a full-stack app I created on Render and all seems to be working fine except for the fact that my routes are not found when I reload the component. I’ve got a general idea why as I did a research online but I haven’t managed to solve the problem yet.
Here’s my server file
const express = require("express");
const dotenv = require("dotenv");
const connectDB = require("./config/db");
const path = require("path");
const cors = require("cors");
const corsOptions = {
origin: "*",
credentials: true,
optionSuccessStatus: 200,
};
const app = express();
app.use(cors(corsOptions));
// read variables and save them as environment variables
dotenv.config({path: "./.env"});
// Init Middleware
app.use(express.json({extended: false}));
// data from req object is added to it(middleware)
app.use(express.json());
// Define Routes
app.use("/api/data", require("./routes/data"));
app.use("/api", require("./routes/collection"));
app.use(`/api/item`, require("./routes/item"));
app.use(`/api`, require("./routes/under"));
app.use("/api/users", require("./routes/users"));
app.use("/api/auth", require("./routes/auth"));
app.use("/api/email", require("./routes/email"));
app.use("/api/basket", require("./routes/basket"));
app.use("/api/size", require("./routes/size"));
app.use("/api/wishlist", require("./routes/wishlist"));
app.use("/api/checkout", require("./routes/checkout"));
app.use("/api/payment_confirmation", require("./routes/confirmation"));
const PORT = process.env.PORT || 5000;
// Connect to Database
connectDB();
// Load React App in production
if (process.env.MODE === "production") {
app.use(express.static(path.join(__dirname, "build")));
app.get("*", (req, res) => res.sendFile(path.resolve(__dirname, "build", "index.html")));
} else {
app.get("/", (req, res) => {
res.send("Welcome to the home page");
});
}
app.listen(PORT, () => {
console.log(`App running on port ${PORT}`);
});
That's my package.json and my scripts
“scripts”: {
“start”: “node app.js”,
“server”: “nodemon app.js”,
“client”: “npm start --prefix …/client”,
“client:install”: “npm install --prefix client”,
“build”: “npm install --prefix client && npm run build --prefix client”,
"dev": "concurrently \"npm run server\" \"npm run client\""
}
That's my repo if you want to have a look at the file structure.
enter link description here
enter link description here
I get this error on the console
Error: ENOENT: no such file or directory, stat '/opt/render/project/client/build/index.html'
Although on the events log it says that build is successful so I'm not sure what the correct folder would be.
Thanks in advance
When I downloaded the app and ran it on my system reloading the page, it seems like the server cannot find the routes defined in your server file. This is because your server is configured to handle all routes in your React app's index.html file.
your client-side routes will match the routes defined in your React app, and the server will only serve the index.html file for the initial request.
In your server file, modify your app.get("*")method to serve the index.html file only for the initial request:
if (process.env.MODE === "production") {
app.use(express.static(path.join(__dirname, "build")));
app.get("*", (req, res) => {
// Serve index.html for the initial request
if (req.originalUrl === '/') {
res.sendFile(path.resolve(__dirname, "build", "index.html"));
} else {
// Serve static files for all other requests
res.sendFile(path.join(__dirname, "build", req.originalUrl));
}
});
}
I want to serve two defferent angular apps on two different routes: domain.com/admin for admin app and domain.com/customer for customer app.
app.use("/admin", express.static(path.join(process.cwd(), "web/dist/admin")));
app.use("/customer", express.static(path.join(process.cwd(), "web/dist/customer")));
app.get("/admin/**", (req, res) => {
res.sendFile(path.join(process.cwd(), "web/dist/admin/index.html"));
});
app.get("/customer/**", (req, res) => {
res.sendFile(path.join(process.cwd(), "web/dist/customer/index.html"));
});
This works, apps are on the routes where they have to be. But I'm getting these error from angular:
Seems like angular can't get files from the server. Is there something like baseUrl, a path for angular to get the files from?
I am trying to use express to render a few different html files from my public folder. These are all static files. I also want to render a 404 page if a route is an invalid route is called. Here is my code.
const express = require("express")
const app = express()
app.use(express.static("public"))
app.get("/", (req, res) => {
res.render("index")
})
app.get("/about", (req, res) => {
res.render("about")
})
app.get("/contact-me", (req, res) => {
res.render("contact-me")
})
app.get("*", (req, res) => {
res.status(404).send("404 for all pages not defined in routes")
})
app.listen(8080)
The first route to render index.html works and the 404 status works, but all the other routes give me an error of "No default engine was specified and no extension provided." I tried added an ejs view engine, but the code still doesn't work. All html files are named properly and live in the "public" folder. Any help on this would be amazing! Thanks much!
You need to use handlebars for handling it. To see an example check this repo
Is there a way to access the root public directory without using ../../../ something like this. The below code works fine, but just thought the way i am accessing my public folder is bit messier.
router.get('/', function(req, res) {
res.sendFile('index.html', { root: path.join(__dirname, '../../public') });
});
Application structure:
/app
--node-modules
--public
--app //contains all angularjs related files
--assets //contains images and js libraries
--index.html
--server
--routes
--index.js //this holds all the route related code
On way is to use app-root-path. It is a module that helps you access your application's root path from anywhere in the application without resorting to relative paths.
var appRoot = require('app-root-path');
router.get('/', function(req, res) {
res.sendFile('index.html', { root: path.join(__dirname, appRoot + '/public') });
});
I'm having an error serving static views on a Heroku app. Strangely, Heroku seems to append "app" to the front of my static file paths, and I'm not sure why. The path should be "public/views/index.html."
I recently tried this proposed solution from Stack, but it didn't seem to work: Node.js, can't open files. Error: ENOENT, stat './path/to/file'
The get requests from my server:
app.use(express.static(__dirname + '/public'));
app.get('/', function (req, res) {
res.sendFile(__dirname + '/public/views/index.html');
});
// profile page
app.get('/profile', function (req, res) {
// check for current (logged-in) user
req.currentUser(function (err, user) {
// show profile if logged-in user
if (user) {
res.sendFile(__dirname + '/public/views/profile.html');
// redirect if no user logged in
} else {
res.redirect('/');
}
});
});
Does anyone have any idea why Heroku would append "app" to my paths?
All the paths work correctly on a local server. Thanks!
The accepted. solution here of using PWD instead of __dirname is quite wrong. sendFile works on Heroku the same way it works anywhere else:
res.sendFile(path.join(__dirname, 'public', 'views', 'index.html'));
This is because the global __dirname variable inside Heroku is set to /app. Use process.env.PWD instead of __dirname.
Looks like this hasn't had an update in a while, but I ran into the same Heroku root directory confusion, but when I changed my code to use 'path' instead of __dirname, it worked.
path.join(__dirname, '..', 'views', 'email', `${template}.pug`),