π TL:DR :
Serving react app is pretty simple if we does it directly through development environment( i.e. serve apps directly including their source_code), but how to serve react apps as bundled static assets (in production environment) will be the main focus of this article.
Going deep into working of this tools can feel get pretty cumbersome, if someone is heavily using tools like Create React App. (which works like magic and does all the heavy lifting behind seens). Hence, I will keep it simple.
Today, we will be deploying simple react app (using Node.js back end). The final project is pretty simple and could be used as base template for your next production ready app.
π Start Nodejs project
First thing first, we will start basic node app, which will serve as a back end for our react front end.
npm init --y
π© Add some utility
Now, we will install some packages like express, cors and dotenv. I am using dotenv for maintaining global values like NODE_ENV
or anything as needed.
npm i express dotenv cors --save
π Ignite the Server π
Now, we will create a simple index.js, which will serve our as API for the client application.
//--------------------- imports ---------------------
const express = require("express");
require("dotenv").config();
const cors = require("cors");
//--------------------- Init App ---------------------
const app = express();
const PORT = process.env.PORT || 5000;
//--------------------- Serve Assets ---------------------
if (process.env.NODE_ENV === "production") {
app.use(express.static("build"));
}
app.use(express.json());
app.use(cors());
app.get("/home", function (req, res) {
res.status(200).json({
status: true,
data: "Backend Responded "
})
})
app.listen(PORT, () => console.log(`Example app running on ${PORT}`));
This is dead simple web server, for react client.
Now, we will add a a script in package.json. Which will start server on specified port.
We will modify it later for client building stuff.
π¨ Create Front End App
Initialize react app using CRA (create react app) or you can configure it on your own using babel and webpack or which ever tool you wanna use (if you want that). I will be preferring CRA
Inside our back end project directory, initialize the front end project.
npx create-react-app frontend
After a while, we now have a new react app, which π±magically π± does nothing (beside spinning a huge blue react logo).
After it, modify content of package.json of front end project and add following code to it.
"proxy": "http://localhost:5001"
This will save us from typing API URL multiple times from our ajax calls, which we will be writing in front end component.
π Write a component
Before writing component, I will install axios (if preferred or use fetch) for back end communication.
cd front end
npm i axios
Then, create a basic component for testing and verifying purpose. Which will verify the connection between front end and back end.
import axios from "axios";
import { useEffect } from "react";
function App() {
const fetchData = async () => {
try {
let resonse = await axios("/home");
if (resonse.status) {
alert("hooray");
} else {
alert("OH ! Snap....");
}
} catch (err) {
console.log("err ", err.message);
}
};
useEffect(() => {
fetchData();
}, []);
return (
<div className="App">
<p > Testing Deployment </p>
</div>
);
}
export default App;
This component does only fetching of data and throwing an alert. Here, we are executing function of API call, directly in useEffect() for avoiding extra bit of code for testing purpose only.
Then, add the script in the back end project as
"client " : "cd frontend && npm run start"
This script will run the project and you will see the normal alert
π The Deployment Stuff
Until this point every thing is good.
Now, it's time to deploy it using static asset serving. Many tutorials are currently explaining, how to ship this kind of project on platforms like heroku or varcel. Which are pretty good. But, this platforms are friendly up to a certain extent. For ex.
- Heroku is free, but your free dyno will be inactivated if it is not actively getting used for a certain duration. Rebooting the slept dyno can take fairly large amount of time as compared to normal requests.*
For avoiding this, we end up serving the project's on paid servers, there we should serve the apps in this fashion.
For deployment, we will be generating the bundle of static files which will be served from Nodejs back end. We Already, added a snippet for this in index.js.
This way, whenever we are using it in production this will work as expected
Step 1 - Generate Bundle
Add script in package.json of back end project, for building the static asset from react source code
"build" : "cd frontend && npm run build"
This will change the current working directory and after that, it will generate the /build folder in front end project.
Step 2 - Place /build directory in root folder
move the build directory in the root of the project.
mv ./build ../
Step 3 - Set NODE_ENV to production
Afterwards, last step is to change/set the value of NODE_ENV (in .env file) as the "production" which depicts, we are in production mode and enable static asset serving.
NODE_ENV = production
content of .env file will look like this
PORT=5001
NODE_ENV=production
Now, for visit the url
http://localhost:5001/home
You will get the alert response and finally everything is working.
Now if we deployed this Nodejs project on any production ready cloud environment like
- AWS EC2 Instance
- Digital occean Droplet
- Virtual Machine
Then this will work as expected. Thus final directory structure will look like this
π Final Thoughts
This is one of way of serving the full stack application created using React and Nodejs. When, I was deploying this kind project, I haven't found any comprehensive guide, so I decided to write one !
Thanks for reading π
Top comments (11)
Hey Sudarshan ,
I have a query.
I am unable to connect the dots here. Now I have the react front end project ready with build folder and Nodejs is installed on a Linux server . Now how can I deploy this react project on to nodejs? I wanted nodejs to serve both static and dynamic requests.
nice question. So, when you create a
build
folder from react app then basically you end up with html, css and minified JS stuff. Now, for final deployment you will move this build folder to the Linux server and place it into the same directory as of your node.js server. Once done you can follow above article fromDeployment Stuff
Hope it will be helpful
Yes Sudarshan , this was the best article that I followed.
this is nice, this could work if a need to deploy a MERN app in a private server running other apps in LAMP?? there i need virtual host configs i think, but your setup could pull off this apache node deployment??
sorry for delayed reply !
I don't have proper understanding of apache. But, I can assure you it would work with your other apps until it's port is available !
Hope this will be helpful
Hi Sudarshan,
I have a query.
In development setup, we need to start the node server as well as the front end react app.
For production setup, we have built the react front end and have those as static data in build folder. Start only the node server.
Is my understanding right ? Please clarify.
You got that !
Because, we are serving the react build folder as the static asset of our nodejs backend π
Thanks for the clarification, Sudarshan.
One query which has been in my mind for a long time is => "Why do we need a Nodejs server? If my React app is connecting to an external api (Java for eg) can't we have just the React front end ?"
it's absolutely fine !
You can use node.js, django, spring / struts, rails or anything. But, you have to find a way to serve assets using that specific framework or technology
this is so simple...great..:
This is super interesting