Have you ever tried creating multiple portfolios using React?
And then ended up deploying each on a separate server 🥲
In this blog, we will learn how you can utilize the power of a single ExpressJS/NodeJS server and serve multiple React apps.
(For deployment, I am using Heroku, feel free to use any other)
How it works? 🤔
- Each React app creates its own
build
folder - Each
build
folder generated will be served at a separate subpath by the single server
And that's it!
Step 1: Preparing React apps
To allow our ExpressJS serve these apps, we need to specify a unique build path for each app.
For instance, 3 apps, first is ran at root /
, second at /app2
& third at /app3
To make this possible the build generated should include this relative path.
Update the build
command in package.json
for each additional React app.
Add PUBLIC_URL=/<something>
to package.json
build property.
For instance,
for second app, scripts
property in package.json
will look something like
"scripts": {
...
"start": "PORT=3001 PUBLIC_URL=/app2 react-scripts start",
"build": "PUBLIC_URL=/app2 react-scripts build",
...
},
& for third app
"scripts": {
...
"start": "PORT=3001 PUBLIC_URL=/app3 react-scripts start",
"build": "PUBLIC_URL=/app3 react-scripts build",
...
},
Step 2: Preparing Server
For this tutorial, I'll be using ExpressJs/NodeJs server, but the concept can applied to any server. That is
Each
build
folder generated will be served at a separate subpath by a single server
In your parent server file (I am using server.js
), for each additional app add the following
const buildPath = path.join(__dirname, '<react app folder path>/build')
app.use('/<your build path>', express.static(buildPath))
app.get('/<your build path>/*', function(req,res) {
res.sendFile(adminBuildPath)
})
For instance, for our 3 React apps example, server.js
will look like:
...
const app1BuildPath = path.join(__dirname, '../app1/build')
// serve static content of app 1 at root \ path
app.use(express.static(app1BuildPath))
app.get('/*', function(req,res) {
res.sendFile(app1BuildPath)
})
const app2BuildPath = path.join(__dirname, '../app2/build')
// serve static content of app 2 at root \app2 path
app.use('/app2', express.static(app2BuildPath))
app.get('/app2/*', function(req,res) {
res.sendFile(app2BuildPath)
})
const app3BuildPath = path.join(__dirname, '../app3/build')
// serve static content of app 3 at root \app3 path
app.use('/app3', express.static(app3BuildPath))
app.get('/app3/*', function(req,res) {
res.sendFile(app3BuildPath)
})
...
BONUS: Heroku deployment
Prerequisites: Heroku CLI
Now that everything is prepared, let's deploy our changes on Heroku.
Heroku CLI makes deployment a lot easier. It runs 3 commands, namely install
, start
& build
. Hence, we need to fix the parent package.json
file and include those.
install
: should install all the dependencies of all the appsstart
: should start the node/express serverbuild
: should run build command for each app
For instance, for the 3 apps example, it will look like:
...
"scripts": {
"start": "node server/server.js",
"install": "cd server && npm i && cd ../app1 && npm i && cd ../app2 && npm i && cd ../app3 && npm i",
"build": "cd app1 && npm run build && cd ../app2 && npm run build && cd ../app3 && npm run build"
},
...
To initiate the deployment run the following in your Terminal
If you don't have an Heroku app already created
// creates an Heroku app
heroku create
Finally, to deploy from the main
branch (update branch name if using something else, like master
)
git push heroku main
For more details, you can refer this video
Happy coding!!