Deploy unlimited React Apps using single ExpressJS Server on Heroku

Deploy unlimited React Apps using single ExpressJS Server on Heroku

·

3 min read

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! easy-meme

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 explanation-of-each-path-served

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 apps
  • start: should start the node/express server
  • build: 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!!