5 Comments

Quick Next.js + GraphQL Integration via API Routes

This is a quick guide to getting a lightweight GraphQL server via API route in a Next.js app. This is not a detailed tutorial of how to create a beautiful, semantic GraphQL and Next.js toolkit.

Where we’re starting: A basic Next.js app with a Postgres database.

Where we’re going: A request to an api/graphql endpoint that gets real data back.

How we’re getting there:

  1. Install packages
  2. Add endpoint to the api directory
  3. Connect the Apollo Server to the database
  4. Update the resolvers
  5. Make a request and get that data

1. Install Packages

We’ll start simple and use the Apollo’s micro-service. It will give us everything we need for a lightweight server.

Run yarn add apollo-server-micro graphql.

2. Add an Endpoint in the api Directory

Building from the example that Next.js supplies, add a file in pages/api/ for the graphql endpoint.

// pages/api/graphql.ts
import { ApolloServer, gql } from 'apollo-server-micro'

const typeDefs = gql`
  type Query {
    users: [User!]!
  }
  type User {
    id: Int!
    firstName: String
  }
`

const resolvers = {
  Query: {
    users(parent, args, context) {
      return [{ firstName: 'Nextjs' }]
    },
  },
}

const apolloServer = new ApolloServer({ typeDefs, resolvers })

export default apolloServer.createHandler({ path: '/api/graphql' })

We want to make sure that the Apollo Server is parsing the request body rather than Next.js. In pages/api/graphql, add:

export const config = {
  api: {
    bodyParser: false,
  },
}

The Next.js doc have more about the Next.js API middleware.

3. Connect the Apollo Server to the Database

Next, let’s get real data by accessing the database from the resolver. When the Apollo Server is initialized, we can pass it a database connection directly or through a context.

For the sake of simplicity, we can get a database instance right in our GraphQL endpoint.

import knex from "knex";

const db = knex({
  client: "postgres",
  connection: {
    host: process.env.POSTGRES_HOST,
    user: process.env.POSTGRES_USER,
    password: process.env.POSTGRES_PASSWORD,
    database: process.env.POSTGRES_DB
  }
});

Now replace the server initialization with something like this:

const apolloServer = new ApolloServer({ typeDefs, resolvers, context => { db })

In practice, the database should likely be stored in a context with other tooling for the server. In that case, we can pass the whole context to the resolvers using the same means.

4. Update the resolvers

Now it’s time to make the resolvers return real data from the database. Using the connection we passed in, we can now query for the users.

const resolvers = {
  Query: {
    users(parent, args, { db }) {
      return db.select("*").from("users")
    },
  },
}

5. Make a request and get that data

The last step is making a query in the client and displaying data. We can make a request to the GraphQL endpoint in the getInitialProps for a page.

import * as React from "react";
import axios from "axios";
import { gql } from "apollo-server-micro";

interface IndexPageProps {
  users?: any;
}
const Index = ({ users }) => <>{JSON.stringify(users)}</>;

const getUser = gql`
  query {
    user {
      id
      firstName
    }
  }
`;

Index.getInitialProps = wrapWithPageContext(async () => {
  try {
    const response = await axios.post("http://localhost:3000/api/graphql", {
      query: getUsers
    });

    return { users: response.data };
  } catch (error) {
    return {};
  }
});

export default Index;

Made it! We are now successfully using GraphQL and Apollo via the Next.js API routes. We could make this cleaner by, for example, pulling in Apollo Client for helpful hooks on the client or using a code generator to have Typescript types that describe the GraphQL schema.