How to connect React SPA with NodeJS? - node.js

Folks I would like to ask for a resolution for this use case if it's possible or not.
Use Case
The functionality currently is that both React and Node code are in the same repo. Where we build the React and the build is placed in /public/ directory. NodeJS loads the static files from the /public/ directory and serve the SPA.
The required functionality is that:
React SPA build will live on server A
NodeJS build will live on server B
How can I serve the static files located in Server A from Server B?

Add this line to your server code (assuming you are using expressJS).
Also I would call name react project client/ instead of serverB.
// file:<project-root-dir>/server/main.js
const STATIC_FILES = path.join(__dirname, '../client/', 'build') // feel free to change `client` to `serverB`
//..
const app = express()
//....
if (process.env.NODE_ENV === 'production') {
app.use(express.static(STATIC_FILES))
app.get('/*', (_, res) => res.sendFile(path.join(STATIC_FILES, 'index.html')))
}

Related

express app is not sending index.html file to client

So my express app has a small Node server setup so it can serve up the index.html file when the home route '/' is hit. This is a requirement of using the App Services from Azure, there has to be this server.js file to tell the server how to serve up the client, and i had a previous implementation of this working, however i wanted to change my file structure. previously i had, the client React app in a folder client and the server.js in a folder server along with all of the conrtollers and routes. i've since moved the server API to its own application as there are other apps that depend on it. and i moved the client up one directory into the main directory. Everything was working fine till the other day when all of the sudden when you hit the home route / it will not serve up the index.html file. if you hit any other route it works, if you even hit a button linking back to the homepage, it works, but it wont serve up the app from the / and i cannot for the life of me figure out why, on my development server there are no errors in the console. and im most definitely targeting the correct directory and place for the index. but its like the server isnt reading the route to serve up.
if (process.env.NODE_ENV === 'production') {
console.log('running');
app.use(express.static(path.resolve(path.join(__dirname, 'build'))));
// no matter what route is hit, send the index.html file
app.get('*', (req, res) => {
res.sendFile(path.resolve(path.join(__dirname, 'build', 'index.html')));
});
} else {
app.get('/', (req, res) => {
res.send('API is running...');
});
}
So here im saying if the NODE_ENV is in production make the build folder static, and then whatever route is hit. (Note: i also tried this app.get with other route formats such as /* or / all have the same issues. however in my previous iteration when the client and server where deployed in the same location, /* is what i used.) The .env varialbes are setup correctly, as when the server is ran, itll console log running.. but even if i put a console log inside of the app.get() its like its never hit unless i access the route from something else first.
for example, if i place a console log inside of app.get that states hit whenever the route is hit, hitting / directly does nothing, but if i go to /login itll serve up the correct html on the client and console log hit in the terminal...
If you are having server files inside the client react app, then we are basically accessing file which are not inside our server file. So, we can serve static files using the following code:
const express = require("express");
const app = express(); // create express app
const path = require('path');
app.use(express.static(path.join(__dirname, "..", "build")));
app.use(express.static("build"));
app.listen(5000, () => {
console.log("server started on port 5000");
});
Now in your packages.json of the client react app change the name of start tag under scripts tag to start-client. Then add this following tag to the scripts tag:
"start":"npm run build && (cd server && npm start)",
Basically, this will build the react app and start the server.
It should look like this :
Also in the packages.json of your server add the following tag under script tag
"start":"node server.js"
So when you run the following command npm start it should look like this :

Error trying to render the index.html that ng build generates with node and express

I want to deploy an application that I perform with the MEAN stack on Heroku, but I encounter 1 problem.
I have this folder structure, my node server, with a public folder, where is the dist / fronted folder and all the files generated by Angular's ng build --prod, it works when I start the server and browse normally, but if I refresh the page or write a route myself, I get these errors:
Errores
Sorry for my English.
If your are building a MEAN stack, you probably have a server.js or index.js or app.js as an entry point to your application. An SPA by definition manages all the routes within the router configuration. But if you try to refresh or type a route yourself, it is like you were trying to access that folder on the server (ex: www.mywebsite.com/about, here the folder about might not exist on the server, it is just known by your Angular app)
My suggestion is that you try to add this fix to the app.js (or server.js or app.js) file, so all unexisting routes or refresh go back to your index.html:
// Check your port is correctly set:
const port = process.env.PORT || 8080;
// Is saying express to put everything on the dist folder under root directory
// Check the folder to fit your project architecture
app.use(express.static(__dirname + "/dist"));
// RegEx saying "capture all routes typen directly into the browser"
app.get(/.*/, function(req, res) {
// Because it is a SPA, all unknown routes will redirect to index.html
res.sendFile(__dirname + "/dist/index.html");
});
app.listen(port);
This guy shows full deploy on Heroku with Angular: https://www.youtube.com/watch?v=cBfcbb07Tqk
Hope it works for you!

What to do with my react application already built?

I finished my react application, and I already built it. I also have my express app for my server side ready. I saw in a video that you can pass the files from the "build" folder to the "public" folder of the server app, but this was done in a basic json-server. I tried to do the same in my express app folder, but it didn't work. Could you please tell me where should I bring my "build" folder? Thank you!
I think you want to serve you react app via express
You can try using below code to do it it will serve your react build folder via express
//define this static path which will point to your build folder inside your server folder
let root = path.join(__dirname, 'client/build/')
app.use(express.static(root))
//route you need to define in your main server file
app.get("*",(req,res)=>{
res.sendFile(path.join(__dirname, '/client/build/index.html'));
})
run the express app and then type the url in browser you will get redirected to react app

How to deploy NextJS application to Linux Server (CentOS 7) - VPS

I've got a question regarding building applications. I'm using simple VPS with node.js support. Now I do not know how to build my next.js application to production.
I want to deploy my application as static files.
I thought that I should use next build && next export then copy out dir to the server but during this process, I faced some issues - when I change route - everything is okay, but if I refresh the page - the page is not found because the server is looking for this file in directories. So how can I deploy my nextjs application in production mode with VPS server and static files?
I tried one thing which is not working fine probably or I did something wrong.
I added nodejs express server with
const express = require('express');
const next = require('next');
const dev = process.env.NODE_ENV !== 'production';
const app = next({dev});
const router = express.Router();
const handle = app.getRequestHandler();
app.prepare()
.then(() => {
const server = express();
server.get('*', (req, res) => {
return handle(req, res);
});
server.listen(3000, (err) => {
if (err) throw err;
console.log('> Ready on http://localhost:3000');
});
});
and start server with forever library NODE_ENV=production node server.js and it's working fine, but seems this is working in a wrong way - seems it's normal server like in dev mode - so it shouldn't be like that. (I see thunder icon on the right-bottom corner and I see all files which are same as in dev mode).
I want to deploy everything as static files.
Thank you for your help!
After you build and export you need to serve those files somehow. The reason the Express server works is because you are starting a HTTP server to serve the files.
So you need to serve those files either by using a static hosting provider (i.e. Vercel or Amazon S3). Otherwise you should start a server on your linux machine using something like serve to serve it at a port, similar to your Express server serving it as localhost:3000 which is then exposed on your VPS.

How to deploy a nodejs backend and vuejs frontend to the same Amazon EC2 instance

I have a vuejs frontend and an express nodejs backend. But I don't know how I can deploy both of them to the same Amazon EC2 instance with the same domain name pointing to them. Please can anyone help me with this? Or suggest a better way of doing this?
You can merge two repos and deploy both backend and frontend as follows
Inside your nodejs app, open a folder named client and put all the Vue project inside it.
If you are using Vue CLI, change your vue.config.js as follows to create a dist folder inside the root of the nodejs project like
const path = require('path');
module.exports = {
outputDir: path.resolve(__dirname, '../dist'),
};
Make all the get/post endpoints of nodejs application start with /api/ to not get conflict with the path that redirects all the requests to vue client app other than /api/ paths.
Run npm run build to create a dist folder inside nodejs root backend folder
If you are using express.js, serve dist folder with nodejs express backend like;
index.js
const express = require('express');
const app = express();
// Serve Vue Dist Folder
app.use(express.static(__dirname + '/dist'));
app.get('*', (req, res) => res.sendFile(__dirname + '/dist/index.html'));
nodejs with e.g. express can also serve static content. Just put your vuejs files in a static folder.

Resources