Build and run multiple apps in single repo using Heroku

Consider a scenario where we want to serve static html pages and expose api from same web server. And static html is generated from react app using nodejs and api using ruby on rails. Usually, we can create 2 heroku apps : 1 app for api and 1 for serving html. If we want both served by 1 heroku app, it will be cost effective and easy to manage.

Because these are different applications built and deployed in different ways within same or different repositories, we need to give instructions to heroku about code within repo, artifacts and way to run the app. Here we will go through series of steps which we enable heroku to build react app and rails api from same repo and serve using rails server.

Installations

  • Heroku cli

Repository Setup

Assumption is we have already working api and react apps in separate folders.

  • Create a repo with two folders : api and client
  • Copy api into folder name: api
  • Copy react app into folder name: client
  • Add .buildpacks file to the root folder with following content:
    client=https://github.com/heroku/heroku-buildpack-nodejs.git#v114
    api=https://github.com/heroku/heroku-buildpack-ruby.git#v173
    
  • Add Procfile (name of the file is Procfile) to the root folder with following content:
    release: cd /app/api && rake db:migrate
    web: cd /app/api && bundle exec rails server
    
  • Add Gemfile (name of the file is Gemfile) to the root folder with following content:
    source 'https://rubygems.org'
      
    ruby "2.5.0"
    gem 'rails', '~> 5.1.4'
    
  • You can update needed rails and ruby versions in above Gemfile.

Heroku setup

  • If heroku app is not already created, create heroku app by running following command:
    heroku create
    heroku buildpacks
    
  • If there are existing buildpacks, remove using heroku buildpacks:remove
  • For adding buildpacks needed for multi app build and run, we need to run following commands:
    heroku buildpacks:add https://github.com/negativetwelve/heroku-buildpack-subdir
    heroku buildpacks:add heroku/ruby
    
  • 1st buildpack is custom pack to build separate folders with different frameworks. .buildpacks in the root folder is used by this buildpack to get the folders and needed buildpacks to build code within those folders.
  • 2nd buildpack is to make sure heroku configures app as ruby app and have needed runtime libraries for serving api and static pages. Gemfile in the root folder is used by heroku to get ruby and rails versions.

Build and running apps

  • Procfile is used by heroku to run the app. There are 2 steps in Procfile:
    • release step is pre-deployment step where we can run migrations and other operations before running the app.
    • web step is usually for running the app
  • As rails server will be used to serve html app(which is built from nodejs app), we need to make sure html is present in public folder of rails app. As part of build step of react app using nodejs, we need to copy built html app into public folder of rails app. Here are scripts needed to add in scripts section of package.json:
    "deploy": "mkdir -p ../api/public && cp -r ./build/* ../api/public",
    "postinstall": "npm run build && npm run deploy && echo 'Client deployed!'"
    
  • postinstall step will be triggered by heroku and html app will be copied to public folder of rails api.
  • Once these changes are done, we are good to run and deploy both apps in heroku using same command:
    git push heroku master
    

This way, we will be able to use same rails server to serve both api and html app in heroku.

References