Search code examples
reactjsexpressgraphqlapolloapollo-server

Deploying react/apollo-server app onto Heroku


What I'm trying to do is deploy react / apollo-server full stack app to heroku. Thus I' trying to serve static client files from express/apollo-server backend, like this:

const path = require('path');

const express = require('express');
const app = express();
const cors = require('cors');
const { ApolloServer } = require('apollo-server');

const { schema } = require('./schema');
const { resolvers } = require('./resolvers');

app.use(cors());

app.use(express.static('public'));

app.get('*', (req, res) => {
  res.sendFile(path.resolve(__dirname, 'public', 'index.html'));
});

const server = new ApolloServer({
  typeDefs: schema,
  resolvers,
});

server.listen({ port: process.env.PORT || 4000 }).then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`);
});

For some reason I don't understand client is not served while deployed to heroku. On heroku URL I'm getting: GET query missing. If I set graphql to enabled in production I can see it, I can play with resolving data. But client is not rendered. I'm guseing app.get with * is not working and then index.html is not catched.

How can I fix that?

Thanks!


Solution

  • The error you are getting is because you are only exposing the server from ApolloServer to the port 4000 and not exposing the app with the frontend client application.

    In order to have the fullstack app deployed, you also have to expose the app, in order to do that you can use applyMiddleware from ApolloServer and bind both apollo server and the frontend client, something like:

    .....
    
    app.get('*', (req, res) => {
      res.sendFile(path.resolve(__dirname, 'public', 'index.html'));
    });
    
    const server = new ApolloServer({
      typeDefs: schema,
      resolvers,
    });
    
    server.applyMiddleware({
      path: '/my-frontend', // you should change this to whatever you want
      app,
    });
    
    app.listen({ port: process.env.PORT || 4000 }, () => {
      console.log(`🚀  Server ready at http://localhost:4000`);
    });
    

    Now you should be able to navigate to http://localhost:4000/my-frontend and see your client application.