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

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.

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 :

Basic express setup: not sending anything to local port

I created a frontend app and now trying to incorporate backend into it.
ON the same frontend app i added an index.js file in the root directory, and installed express and required it in index.js file.
Very basic setup as below:
const express = require('express')
const cors = require('cors')
const port = process.env.PORT || 3001
const app = express()
app.get('/', (req, res) => {
res.send({
greetings: 'hi'
})
})
app.listen(port, () => {console.log(`Server on port ${port}`)})
Server is successfully on port 3001 as per my terminal, however, on localhost:3001 I'm not seeing any json response I set up in app.get.
It says Cannot GET / instead. When i inspected in devtool(Network) it says 404.
This seems a very straightforward setup, but what could've gone wrong here?
i just figured why. I installed nodemon but my “start” script is “node index.js”. Should’ve used “nodemon index.js”
Working now with nodemon index.ks
Your code is fine, There are no errors, I tested it and it works as expected.
However few things to note, Keep Backend in Seperate folder/dirctory unless required.
Coming back to your question, There are many possiblity such as some modules are not installed properly
try running following command
//this will install if any library is currupt or not installed properly
npm i
if it doesn't work then try clearing cache
Also keep in mind, In nodeJS dev server does not automatically refresh changes, you need to restart server to see changes or you can use dev dependancy called Nodemon (this will auto restart server on saving changes)

How to deploy ReactJS web application on a windows server using Node.JS?

I have developed a ReactJS app using the create-react-app on my local windows 10 machine..
Now, I want to deploy this application on a on-premise windows 2008 R2 server. I do not have much experience with this. When I searched over the internet, all the articles are talking about either deploying into IIS or in cloud. But, I do not want to use IIS and I have On-Premise server.
Is there any other way to deploy and host this ReactJS application on Windows server machine? Maybe just using the Node.JS?
Create the build using npm run build and write a nodejs script with express to serve the build directory.
The nodejs script would be like this:
start-server.js
const express = require("express");
const path = require("path");
const basePath = '';
const app = express();
app.use(basePath + "/", express.static(path.resolve(__dirname + "/build")));
app.get("*", (request, response) => {
response.sendFile(path.resolve(__dirname + "/build/index.html"));
});
app.listen(port);
To start the server:
node start-server.js

Elastic Beanstalk Problem: Connection timing out when running my Node.js Express server

I'm trying to deploy my MERN app on Elastic Beanstalk, and I seem to be running into a final problem that I just cannot solve.
My app works fine when running my server locally (running node server), but when running on elastic beanstalk, the page never loads.
Upon inspection, the static elements are not being loaded, as seen in Dev Tools:
Image showing ERR_CONNECTION_TIMED_OUT in dev tools
I checked all the EB logs and did not find any errors or helpful messages.
I'm thinking the problem is with EB not being able to find my static files somehow. It should however, my build files are not ignored by git and are deployed to EB.
Here's some background about my project:
My backend and client code are in one project, with the following structure:
project
server.js
frontend
build
static
index.html
I run my app by building the react site, then running "node server" which runs great
Here is the relevent code from my server.js :
const port = process.env.PORT || 8081;
app.use(express.static(path.join(__dirname, 'frontend/build')));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'frontend/build/index.html'));
});
app.listen(port, () => {
console.log(`Server is running on port: ${port}`);
});
The server is successfully sending logs that the server is running and that the database has established a connection. So it seems the server is fine, it's just that the front-end is the problem.
eb config file:
option_settings:
aws:elasticbeanstalk:container:nodejs:
NodeCommand: "npm start"
aws:elasticbeanstalk:application:environment:
PORT: 8081
NODE_ENV: production
aws:elasticbeanstalk:container:nodejs:staticfiles:
/static: /frontend/build/static
I'm at a loss on how to solve this. The EB was deployed through the CLI and I haven't messed with any settings. I'm letting EB know where my static files are, and I believe it would say not found, rather than timing out.
Any help would be appreciated
Solved.
The problem was with using Helmet in my express server. I had ommited the code, thinking it not relevant, but here is the top portion of server.js, with the last line being the relevant portion:
const AWS = require('aws-sdk');
const cors = require('cors');
const express = require('express');
const helmet = require('helmet');
const mongoose = require('mongoose');
const path = require('path');
let Download = require('./models/Download.js');
require('dotenv').config();
const app = express();
const port = process.env.PORT || 8081;
app.use(helmet());
Not using helmet solves the issue.
To be honest, I'm not sure why this is the problem.
I assume that the problem is that helmet provides some security that my bare bones EB simply is not providing.
EDIT: Specifically, the problem is with CSP. Setting contentSecurityPolicy to false in Helmet is enough to fix the issue.

Stop Past Express JS or React Builds from Running

I have been developing an app from the create-react-app starting project.
Today I have been doing the following on my local machine:
deploying my react app using react-scripts start
deploying my react app by using react-scripts build then either serving the build by either...
(A) using the [npm module serve][] as follows serve -p 4001
(B) or attempting to server using a express app like follows:
Express app:
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'build')));
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(4001);
I've just restarted my computer and it's still serving the site at:
http://localhost:4001/ and I cannot figure out how to stop it.
I wouldn't mind the continuous deployment of this server but when I build the project again. The changes are not reflected.
The only work around I've come up with is to now deploy at port 4025 and use the Express method coded above.
How the hell can I get rid of this weird residual app that continues to run (via some react process) at port 4001?
I'd really like that port back for sake of keeping it the same across different machines :(
Turns out that chrome keeps react apps running even if the server stops providing them.
Go to chrome://serviceworker-internals and unregister them.

Resources