Effortless GraphQL in Next.js: Elevate Your DX with Codegen and more

ptvty

ptvty

Posted on June 25, 2024

Effortless GraphQL in Next.js: Elevate Your DX with Codegen and more

Introduction

GraphQL endpoints are gaining popularity for their flexibility, efficient data fetching, and strongly typed schema. Putting these powers in hands of API consumers will elevate the Developer Experience (DX) and leads to building robust and maintainable applications. Combining Next.js, GraphQL, and TypeScript offers a powerful stack that can significantly improve your productivity and code quality.

In this article, I will walk you through setting up a Next.js project that uses Hasura for an instant GraphQL endpoint. We will demonstrate how to achieve code auto-completion and type hinting in VSCode using a few tools and extensions and one of GraphQL's superpowers - introspection. By the end of this guide, you'll have a seamless development setup that boosts your efficiency and code accuracy.

Outline

In this article we will walk through the following steps:

  • Creating a sample GraphQL endpoint, we will use Hasura Cloud.
  • Installing prerequisites and creating a fresh Next.js app.
  • Minimal wiring of a GraphQL endpoint in our Next.js app.
  • Installing extensions and tools for GraphQL IntelliSense in VS Code.
  • Setting up tools for typed variables and responses in useQuery hook.
  • Enhancing npm run dev to concurrently run all the required tools.

Setting Up Hasura

Visit Hasura Cloud and create an account. Click "New Project" in the projects tab.

Hasura Cloud's New project settings

Select desired options and proceed. Your project will be created instantly, click "Launch Console". Switch to the "DATA" tab and click "Connect Neon Database". Neon is essentially a Postgres database on a serverless platform, you can read more on the Neon's website.

Click

Wait a while and click "default" database in the sidebar. Click the first template, "👋 Welcome to Hasura!" in the "Template Gallery" page, then click "Install Template".

Click

We are almost done, just head to the "API" tab and copy both GrphQL endpoint URL, and the string in front of x-hasura-admin-secret request header. To manage our Hasura endpoint URL and admin secret, we'll use environment variables.

Setting Up Prerequisites and creating a fresh Next.js Project

Ensure you have the following:

  • Basic understanding of Next.js and GraphQL.
  • Node.js and npm/yarn installed.
  • Visual Studio Code installed.
  • A running Hasura instance (I'll use Hasura Cloud's free tier).

Now, let's create a new Next.js project. We will install the necessary dependencies in the next steps. Initialize a New Project:

npx create-next-app@latest my-graphql-app # Proceed with default choices
code my-graphql-app # Open the project in Visual Studio Code 
Enter fullscreen mode Exit fullscreen mode

Configuring for Minimal GraphQL Endpoint Access

Switch to VS Code, create a blank file, .env.local, this is Next.js's default file for storing dev environment variables. Add your Hasura Cloud's endpoint URL and the x-hasura-admin-secret value:

NEXT_PUBLIC_GQL_URL="https://charmed-finch.hasura.app/v1/graphql/"
NEXT_PUBLIC_HASURA_ADMIN_SECRET="FHU82EdNTGfMSExUkip4TUtLtLM1T..."
Enter fullscreen mode Exit fullscreen mode

Note that environment variables prefixed with NEXT_PUBLIC_ are exposed to the client-side. I'm using Hasura admin secret for the sake of simplicity, and you should use a proper authentication method for your real project, see Hasura's Authentication and Authorization for more info.

We will urql a rather minimal GraphQL client:

npm i urql
Enter fullscreen mode Exit fullscreen mode

Open app/page.tsx and replace the default content with this minimal query:

"use client"
import { Client, Provider, cacheExchange, fetchExchange, gql, useQuery } from "urql";

const Customer = () => {
  const CUSTOMERS_QUERY = gql`
    query CustomersQuery {
      customer { first_name }
    }
  `;
  const [{ data }] = useQuery({
    query: CUSTOMERS_QUERY,
  });
  return JSON.stringify(data);
}

const client = new Client({
  url: process.env.NEXT_PUBLIC_GQL_URL ?? '',
  exchanges: [cacheExchange, fetchExchange],
  fetchOptions: {
    headers: {
      "x-hasura-admin-secret": process.env.NEXT_PUBLIC_HASURA_ADMIN_SECRET ?? ''
    }
  },
});

export default function Home() {
  return <Provider value={client}>
    <Customer />
  </Provider>;
}
Enter fullscreen mode Exit fullscreen mode

Check your app in a browser, you should see the raw data.

Setting Up Visual Studio Code for GraphQL IntelliSense

  • Install GraphQL: Language Feature Support VS Code extension

  • The installed extension expects a GraphQL schema file, so we will use graphqurl to introspect the GraphQL endpoint and download the full schema into a schema.graphql file. We will also use dotenv-cli package to pass variables from the .env.local file to the graphqurl command.

  • Install required packages:

npm i -D graphqurl dotenv-cli
Enter fullscreen mode Exit fullscreen mode
  • And add to your package.json scripts:
"dev:introspect": "dotenv -e .env.local -- npm run dev:_introspect",
"dev:_introspect": "gq %NEXT_PUBLIC_GQL_URL% -H \"X-Hasura-Admin-Secret: %NEXT_PUBLIC_HASURA_ADMIN_SECRET%\" --introspect > schema.graphql",
Enter fullscreen mode Exit fullscreen mode
  • Run npm run dev:introspect and wait for the schema.graphql file to be generated in the project's root directory.

  • Create a blank file graphql.config.ts with the following content to hint the extension on where the schema file is and in which files the IntelliSense should work:

export default {
    schema: './schema.graphql',
    documents: ['**/*.{graphql,js,ts,jsx,tsx}'],
};
Enter fullscreen mode Exit fullscreen mode
  • Restart VS Code and test IntelliSense by editing the query:

GraphQL IntelliSense demo

Setting Up Codegen for Typed Query Variables and Responses

  • Install dependencies:
npm install -D @graphql-codegen/cli @parcel/watcher
Enter fullscreen mode Exit fullscreen mode
  • Add codegen.ts file to the project's root directory:
import { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  schema: {
    [process.env.NEXT_PUBLIC_GQL_URL?? '']: {
      headers: {
        "x-hasura-admin-secret": process.env.NEXT_PUBLIC_HASURA_ADMIN_SECRET ?? '',
      },
    },
  },
  documents: ['**/*.{ts,tsx}'],
  generates: {
    './__generated__/': {
      preset: 'client',
    }
  },
  ignoreNoDocuments: true,
};

export default config;
Enter fullscreen mode Exit fullscreen mode
  • Add to your package.json scripts:
"dev:codegen": "graphql-codegen --require dotenv/config --config codegen.ts dotenv_config_path=.env.local --watch",
Enter fullscreen mode Exit fullscreen mode
  • Use generated graphql function instead of urql's gql literal:
import { graphql } from '../__generated__/gql'

const CUSTOMERS_QUERY = graphql(`
  query CustomersQuery {
    customer { first_name }
  }
`);
Enter fullscreen mode Exit fullscreen mode
  • Great, now run npm run dev:codegen, edit the query, save the file, and wait a moment for the codegen to re-generate the type files. Enjoy typed variables and query responses.

GraphQL typed variables and responses

Running Everything Together

We'll use concurrently to run the introspection, codegen, and Next.js dev server all together.

  • Install Dev Dependencies:
npm install -D concurrently
Enter fullscreen mode Exit fullscreen mode
  • Rename the original dev script and add concurrently script to package.json as the new dev script:
"dev:next": "next dev",
"dev": "concurrently 'npm:dev:next' 'npm:dev:codegen' 'npm:dev:introspect'",
Enter fullscreen mode Exit fullscreen mode
  • Run the dev server as before:
npm run dev
Enter fullscreen mode Exit fullscreen mode

Benefits of Enhanced DX

By following these steps, you achieve the following benefits:

  • Code Auto-completion: Automatically suggests GraphQL queries and schema details as you type, reducing the need for constant reference checks.

  • Type Safety: Ensures that your GraphQL queries and mutations are type-safe, reducing runtime errors and improving maintainability.

  • Reduced Errors: With auto-completion and type hinting, the likelihood of making syntax or schema-related errors decreases significantly.

Conclusion

In this guide, we've shown you how to set up a Next.js project with GraphQL using urql, configure your environment for optimal DX with Hasura, and leverage TypeScript and VSCode tools to improve your coding experience. By integrating these technologies, you can streamline your development workflow, reduce errors, and build more robust applications.

By adopting these practices, you'll enhance your development workflow and enjoy a more productive and efficient coding experience. Happy coding!

💖 💪 🙅 🚩
ptvty
ptvty

Posted on June 25, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related