How can I deploy a GraphQL API and its React Client on Heroku?

Viewed 99

I have created an application with a GraphQL API and a React Client. My project's structure is as follows:

project
│   README.md    
│
└───server
│   │   package.json
│   │   
│   └───src
│       │   index.ts
│       │
│       └───entity/migration/resolver/etc.
│       │   ...
│   
└───client
│   │   package.json
│   │
│   └───public
│   │   │   index.html
|   |   |   ...
│   │   │
│   └───src
│       │   index.js
│       │
│       └───components
│       │   ...

I'd like to deploy this entire app to Heroku, but I'm not quite sure how to do so. On my local machine, I have my server running on localhost:4000 and my client running on localhost:3000, and my client makes requests to my server using @apollo/client. Would I need to deploy two separate apps to Heroku, or is there a way to deploy these both as one app?

Here's the code from my server/src/index.ts:

import dotenv from "dotenv"
import "reflect-metadata"
import { ApolloServer } from "apollo-server"
import { buildSchema } from "type-graphql"
import { createConnection } from "typeorm"

(async () => {  
  await createConnection()  

  const apolloServer = new ApolloServer({
    schema: await buildSchema({
      resolvers: [`${__dirname}/resolver/*.ts`],
    })
  })

  const port = process.env.PORT || 4000
  apolloServer.listen(port, () => {
    console.log(`Server started on port: ${port}`)
  })
})()

And here's the code from my client/src/index.js:

import React from "react"
import ReactDOM from "react-dom"
import { ApolloClient, ApolloProvider, InMemoryCache } from "@apollo/client"

import App from "./components/App"

const client = new ApolloClient({
    uri: process.env.ENDPOINT || "http://localhost:4000",
    cache: new InMemoryCache()
})

ReactDOM.render(<ApolloProvider client={client}><App /></ApolloProvider>, document.getElementById("root"))
1 Answers

It's a long topic to be covered that's exactly what I have started developing recently, the entire source code is available on Github at https://github.com/mdarif/project-management

This is MERN app where I have deployed Server/Client and MongoDB all in once on Heroku, there is also a Dockerize Version of the same MERN app available using Github Actions.

Below important things should be taken care of:

  • Environment variables for Dev and Config Vars on Heroku
  • Add Handler to Client Build in server/index.js or server.js
// Serve Frontend
if (process.env.NODE_ENV === 'production') {
  // Set build folder as static folder
  app.use(express.static(path.join(__dirname, '../client/build')))

  app.get('*', (req, res) => {
    res.sendFile(path.join(__dirname, '../client/build/index.html'))
  })
} else {
  app.get('/', (req, res) => {
    res.status(200).json({ message: 'Welcome to the Project...' })
  })
}
  • Add Scripts to package.json (server)
  "scripts": {
    ...
    "heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix client && npm run build --prefix client"
  },
  • Make sure to test your client & server build separately
  • Connecting Heroku to GitHub
    • Go to heroku.com
    • Choose Connect to GitHub as the deployment method
    • If your GitHub account isn’t connected to Heroku, do so
    • Search for, and choose the project repository we created in the previous step
    • Enable automatic deployments and select the deployment branch
    • Click on Deploy Branch

And that’s it! You’re done. Your app would now be deployed. If you face errors, you can debug them using Heroku’s logs.

Related