Deploy the backend and frontend on the same Heroku app/dyno

23,789

Solution 1

I just successfully completed this goal using static files created during a heroku postbuild step, as described in this blogpost. I have a React frontend (could be anything though) and Express API backend. Each process has its own port in dev, but deploying on Heroku uses just one total.

  1. Put the working frontend in a subdirectory of root (such as /frontend).
  2. Put the working backend in a subdirectory of root (such as /api -- the blogpost assumes the backend remains in the root directory -- either way is fine).
  3. Proxy API requests from the frontend to the backend by adding this line to /frontend/package.json (replacing 5000 with your backend port):

    "proxy": "http://localhost:5000",

  4. Add the following to api/app.js (or api/index.js) in the backend (be sure the last part is AFTER you define the appropriate backend [or api] paths):

const path = require('path')

// Serve static files from the React frontend app
app.use(express.static(path.join(__dirname, '../frontend/build')))

// AFTER defining routes: Anything that doesn't match what's above, send back index.html; (the beginning slash ('/') in the string is important!)
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname + '/../frontend/build/index.html'))
})
  1. Edit the root directory's /package.json file with something like the following (note that using the concurrently package allows an easy way to run the whole app locally with npm run dev, but only heroku-postbuild is required here):

  "scripts": {
    "frontend": "cd frontend && npm start",
    "api": "cd api && nodemon app.js",
    "dev": "concurrently --kill-others-on-fail \"npm run api\" \"npm run frontend\"",
    "heroku-postbuild": "cd frontend && npm install && npm run build"
  },
  1. Make sure you install all backend package dependencies in the root directory, or you will get errors.
  2. Make sure your /Procfile has something like web: node api/app.js

Solution 2

Seems that you can put a package.json file on the root of the project and use scripts to invoke npm i in both folder.

https://devcenter.heroku.com/articles/nodejs-support#customizing-the-build-process

Something like cd front && npm i && cd ../back && npm i

But i should say that if they are running on different ports, it may not work as it seems that only one web process per procfile is available. this last point is to confirm.

Solution 3

You can define several entry points for your project in the Procfile :

web: cd front && npm i && npm start
server: cd backend && npm i && npm start

However, you have to upgrade to Hobby at least. It's 7$/dyno/month.

Share:
23,789

Related videos on Youtube

Maxime Dupré
Author by

Maxime Dupré

Updated on July 09, 2022

Comments

  • Maxime Dupré
    Maxime Dupré almost 2 years

    At the root of my project, I have a frontend and backend folder. Both folders contain a package.json that list their dependencies. How do I tell Heroku to run npm install on both folders when deploying the application? It seems like Heroku expects to have a single package.json file by default. Do I have to do something with a Procfile? The Heroku documentation doesn't seem to tell much about my specific question.

    Thanks for the help!

  • Maxime Dupré
    Maxime Dupré almost 8 years
    Yeah, I'm already doing that, although you can't use cd during the build (Heroku will give an error and make your build fail if you do), you need to do something like: "npm --prefix ./front install". I was hoping for a more Heroku "native" way of doing it. If I don't get such answer before the bounty is over, I will award you the bounty. Please update your answer with the information I just provided. Thanks!
  • malix
    malix almost 8 years
    or use a postinstall hook
  • Indy
    Indy over 3 years
    Thanks for the detailed explanation.. however Heroku doesn't allow me to set my own ports, so what would I fill in in 'proxy' in package.json?
  • Rohan Devaki
    Rohan Devaki almost 3 years
    what about adding the ENV variables? where should we do it?
  • Kevin Sylvestre
    Kevin Sylvestre about 2 years
    The issue with attempting to run a backend / frontend like this is the only dyno that can receive / process a web request is web. The Heroku docs clarify: devcenter.heroku.com/articles/procfile#the-web-process-type