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.
- Put the working frontend in a subdirectory of root (such as
/frontend
). - 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). -
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”,
-
Add the following to
api/app.js
(orapi/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 ("https://stackoverflow.com/") in the string is important!)
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname + '/../frontend/build/index.html'))
})
- 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 withnpm run dev
, but onlyheroku-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"
},
- Make sure you install all backend package dependencies in the root directory, or you will get errors.
- Make sure your
/Procfile
has something likeweb: node api/app.js