Can't understand client side routing - reactjs

So I was looking into the p2p.chat.I modified it a bit to have a better room encoding technique and noise suppression based on RNN noise.
I ran the npm run bundle cmd to generate the production build and tried hosting using the express server. But I was not able to emulate the client-side routing as seen on the webpack dev output. It doesn't use react-router.
I have no idea how to host this web-app.
p2p.chat

okay got it fixed after replacing the contents of jam.js to this
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, '')));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, '', 'index.html'));
});
app.listen(9000);
I removed the directory reference in it

Related

live reload when running express with CRA

I have my create react app setup similar to this setup. https://www.newline.co/fullstack-react/articles/using-create-react-app-with-a-server/
All is working great so far.
when I'm running on localhost:3000 i'm seeing hot reloading as CRA dev server is taking care of that for me.
Now when I run my app using my express server localhost:8081 i'm loading my html file and assets from CRA build folder which obviously means I'm only going to get the built files.
What i'd like to do is when running in port localhost:8081 I can get a reload of development changed files and not just the static build files.
The reason for this is let's say I'm using an authentication setup where I need to check if user is logged in before I allow the * route to proceed otherwise redirect to another route in express. I want to be able to check for this when working in development.
If I run the dev server localhost:3000 then I no longer get the route change loading my html files from express. Only the api call would work from express.
Here is my setup in express:
const express = require("express");
const path = require("path");
const PORT = process.env.PORT || "8081";
const app = express();
const indexPath = path.join(__dirname, "../build/index.html");
app.use(express.static(path.resolve(__dirname, "../build"), { index: false }));
app.get("/test", (req, res) => {
res.json({ message: "welcome to backend" });
});
app.get("*", (req, res) => {
console.log("sending index.html");
res.sendFile(indexPath);
});
app.listen(PORT, () => console.log(`listing on port ${PORT}`));
This express route will only work when using in localhost:8081 which is getting the build files.
app.get("*", (req, res) => {
console.log("sending index.html");
res.sendFile(indexPath);
});
But this never runs when working in dev server localhost:3000 so I can not do any authentication on this route when working in development mode. This would mean to test this I would have to keep rebuilding the build folder which is crazy.
I'm running my client in one terminal and my server in another. I also restarted both multiple times. The proxy as I said works in my package file for the /test route when called using fetch .
This a similar unanswered question I found:
create-react-app + nodejs (express) server

My MERN app is deployed on Namecheap / cPanel but it's not accessing Mongo Atlas DB

ISSUE
My app is hosted on Namecheap shared hosting, but it doesn't connect to my Mongo Atlas DB.
DETAILS
I'm very new to this, and have only deployed to Heroku. I tried to use them at first, but I couldn't figure out how to get the image file upload/retrieval working with S3.
So I'm trying Namecheap.
Anyways on the cPanel file directory, my app is in: /home/username/repositories/myapp
I also ran the npm run build command locally, and placed the contents of the newly-created /build/ directory inside cPanel's /home/username/public_html
I'm almost certain that it doesn't have to be done that way, but so far that's the only thing that gets my actual website to render on the browser.
I used cPanel's "Setup NodeJS App" menu to put my app up, and set the "Application Starter File" to server.js
My server.js file
const mongoose = require('mongoose');
const express = require('express');
const app = express();
const dotenv = require('dotenv');
const cors = require('cors');
const path = require('path');
// Activate dotenv for secure keys
dotenv.config();
// Middleware to recognize incoming Request Object as a JSON object
app.use(express.json());
// Local file storage
app.use('/uploads', express.static('uploads'));
// Bind Routes
const commissions = require('./routes/api/commissions');
const projects = require('./routes/api/projects');
const users = require('./routes/api/users');
// Use Routes
app.use(cors());
app.use('/commissions', commissions);
app.use('/projects', projects);
app.use('/users', users);
// Mongo connect
mongoose
.connect(process.env.URI || process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
})
.then(() => console.log("Connected to MongoDB"))
.catch(err => console.log(err));
// For Deployment
if(process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, 'client', 'build')));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'client', 'build', 'index.html'));
});
};
// Run server
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server started on port ${port}`));
I ran NPM install in cPanel (as well as a script in my package.json to run npm install on the client-side) hoping both of those would enable my app to work (like in development).
I also checked my Mongo Atlas IP Whitelist but it's already allowing for 0.0.0.0/0 (from my heroku deployment).
Also, the namecheap support staff opened Port 5000 for me, (I read in another forum that this was the solution for someone with a similar problem) but that did not work for me either.
Solved by:
Adding my Shared Hosting IP address (located in cPanel) to Mongo Atlas IP Whitelist
Contacting cPanel support and having them open the appropriate backend ports
Changing the NodeJS version of my app on cPanel's "Setup NodeJS App" menu
The biggest thing was the Node version. Node has many versions, but as of this post cPanel only has the following Node Version options:
12.19.1
11.15.0
10.22.0
9.11.2
8.17.0
6.17.1
My particular version is none of those, so I was informed to just select the highest version available. But that's what was breaking the connection to my Mongo Atlas DB.
I tested each of those options, and the one that worked was 8.17.0.

React routes with two parameters not working on react build

I'm using react router and everything works fine in development, but the production build of the react app is not working when I visit some routes with more than one parameter for example http://localhost:3000/me/edit.
I tried deploying in netlify with the _redirects file, also with nginx and also with serve. None of the three options worked.
It seems to be requesting a file inside the static folder. I will attach two images so you can see what I'm refering to.
This is what I can see under Sources tab:
When I visit http://localhost:3000/me it works fine and this is what I can see on chrome:
When I visit http://localhost:3000/me/edit if leads to a blank page, and it seems to be requesting a file inside me > static > edit which obviously does not exist; and this is what I can see on chrome:
So, I could finally solve this, the problem was that routes with more than one parameter either static or dynamic (eg: /me/edit or /user/:id) were looking for a file inside a folder, in this case me or user which do not exist.
Here's how I solved it:
I created a folder called 'production' inside this folder I ran npm init, I pasted the entire build folder generated by react. Then I created a file called server.js (which is the entry point I specified). This file contains the following:
const express = require('express')
const path = require('path');
const cors = require('cors')
// Initializing express
const app = express()
// Initializing middleware to indicate express where to serve the static files from:
app.use(express.static(path.join(__dirname, 'build')));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.use(cors())
const PORT = process.env.PORT || 4000
app.listen(PORT, () => console.log(`Server listening on port ${PORT} 🔥`))
In addition, I added this: <base href="/"> to my index.html file inside the build folder.
On the package.json I added the start script "start": "node server.js" and that's it, never was typing npm start so satisfactory 😂
The entire project now looks like this:

Bundle React/Express App for production

My app is built with "create-react-app" and also Express.js as back-end.
How should I set up for the app for production?
Here is my user.js file from Express:
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.json(['Hello World'])
});
module.exports = router;
I have "Proxy" setup in the package.json file in the React folder.
"proxy": "http://localhost:3001"
"create-react-app" has the command for build:
npm run build
Is my app bundled for production if I just run "npm run build" in the react folder or I have to setup something in my Express files?
If Express acts as both your API and your application server, at a basic level you'd need to setup Express to load the index.html of the React application when no other API routes are caught. You would do this by using sendFile() along with Node's path, registering a "catch-all" route after all your other API endpoints, in the main file for your Express application.
app.use('/users', usersRouter);
app.use('*', function (request, response) {
response.sendFile(path.resolve(__dirname, 'index.html'));
});
The path within sendFile() needs to point to the location of the index.html of the React client/frontend applicaiton. Exactly what goes into sendFile() entirely depends on the structure of your project. If for exampple you have the React application in a folder called client which has a build folder generated by create-react-app npm run build, the sendFile() would look like:
app.use(express.static(path.join(__dirname, 'client', 'build')));
// API route
app.use('/users', usersRouter);
app.use('*', function (request, response) {
response.sendFile(path.join(__dirname, 'client', 'build', 'index.html'));
});
The * in app.use() such as app.use('*', function (request, response)); means effectively all HTTP verbs (GET, POST, PUT, etc). If you do NOT put this after your API routes/paths, it will prevent your React client application from making calls to the API as it will catch all requests, order is very important.
Then you simply build the React application then run the Express application.
Hopefully that helps!

How to run multiple yo angular-fullstack applications on same server and port?

I have a development server where I test my applications. I want to simultaneously run multiple yo angular-fullstack applications on that server in different sub-directeries. Eg: example.com/project1 should take me to first project and example.com/project2 should take me to second project. I tried creating an express application at root level and running that after adding separate route for each project like,
app.use('/project1', require('project1')); but it's not working because the compressed js and css files are not getting included.
// REQUIRE
var path = require('path');
/* ... */
// ROUTES
app.get('/PROJ-1', function (req, res, next) {
res.sendFile(path.resolve(__dirname, 'PROJECT-1-PATH', 'index.html'));
});
app.get('/PROJ-2', function (req, res, next) {
res.sendFile(path.resolve(__dirname, 'PROJECT-2-PATH', 'index.html'));
});
I think this will works..

Resources