Whilst trying to get my app live onto Heroku, I realized that there were a lot of kinks that I needed to get right. This post attempts to document the complete series of steps on getting both the frontend built statically and copied into the backend, as well as getting the backend hosted on heroku.
Steps on hosting both frontend and backend of your app on Heroku
Step 1: Ensure cors is installed in backend
npm install cors
Step 2: Add cors to index.js
const cors = require('cors')
app.use(cors())
Step 3: Add Procfile to backend
Create a file called Procfile with the following content:
web: npm start
And add it to the root of the backend repo.
Step 4: Change the PORT variable to:
process.env.PORT || 3001
Step 5: Make sure that you have heroku CLI installed on your laptop
If not, run brew tap heroku/brew && brew install heroku
Step 6: Create Heroku app
heroku create
Step 7: Push to Heroku
git push heroku main
If cannot, it might be because your code is not main branch. If it’s called master, do: git push heroku HEAD:master
Step 8: Go to Heroku console and change the Config Vars
Under settings, copy your .env variables into there.
Step 9: Check that site’s live
You should be able to access the api routes via the link generated.
Step 10: import static plugin in app.js
If you are not using React router, you can do something like:
app.use(express.state('build')) at the top of the middleware declaration.
For this case, I am using React Router in the frontend, which requires this particular set up:
Add this to the start of the middlewares:
app.use(express.static(path.join(__dirname, './build')));
And add this to the end of all the routes, right before unknownendpoint handler:
| |
Check out here1 for more reasoning.
Setting up frontend
Step 11: On the frontend, change all the calls to localhost:3001 to relative path:
/api/notes for instance
Step 12: Add a proxy on the frontend
Within package.json, add:
"proxy": "http://localhost:3001"
This will ensure that the request is redirected to 3001 if the resource is not found.
Step 13: Add the following scripts to package.json of Backend:
| |
This will ensure that you can just type npm run deploy:full to create a build folder on frontend and copy that into backend.
(Either do this) Step 14: Run npm run deploy:full
This should ensure that latest build is deployed into Heroku. Your app is now hosted and live.
(OR) Step 14: Check that latest frontend build works via backend
npm run build:ui -> this should build latest frontend and copy onto backend.
Run npm start in backend - it should be able to host your frontend.
The main problems I had this time was getting the routes right.
According to this answer, the reason is because React Router does all the routing in the browser, so you should be sending the
index.htmlfile to your users for every route. Thus that route sends theindex.htmlfile to every route that’s not matched by the routes above. Thus it’s important to add the catchall file sender below all the API routes, which was what worked in my case. ↩︎