Effortless GraphQL in Next.js: Elevate Your DX with Codegen and more
ptvty
Posted on June 25, 2024
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.
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.
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".
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
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..."
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
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>;
}
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 aschema.graphql
file. We will also usedotenv-cli
package to pass variables from the.env.local
file to thegraphqurl
command.Install required packages:
npm i -D graphqurl dotenv-cli
- 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",
Run
npm run dev:introspect
and wait for theschema.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}'],
};
- Restart VS Code and test IntelliSense by editing the query:
Setting Up Codegen for Typed Query Variables and Responses
- Install dependencies:
npm install -D @graphql-codegen/cli @parcel/watcher
- 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;
- Add to your
package.json
scripts:
"dev:codegen": "graphql-codegen --require dotenv/config --config codegen.ts dotenv_config_path=.env.local --watch",
- Use generated
graphql
function instead ofurql
'sgql
literal:
import { graphql } from '../__generated__/gql'
const CUSTOMERS_QUERY = graphql(`
query CustomersQuery {
customer { first_name }
}
`);
- 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.
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
- Rename the original
dev
script and add concurrently script topackage.json
as the newdev
script:
"dev:next": "next dev",
"dev": "concurrently 'npm:dev:next' 'npm:dev:codegen' 'npm:dev:introspect'",
- Run the dev server as before:
npm run dev
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!
Posted on June 25, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.