With GraphQL Codegen
Supercharge your development experience in TypeScript projects with Nacelle Storefront SDK 2.x and GraphQL Codegen
GraphQL Codegen x Nacelle
What is GraphQL Codegen?
GraphQL Code Generator is a powerful tool that automates the creation of TypeScript types related to GraphQL operations. Key benefits include:
- Strong Typing: GraphQL Codegen generates TypeScript type definitions based on your GraphQL schema. This ensures type safety throughout your codebase, reducing the chances of runtime errors and improving developer experience.
- Automatic Code Generation: With GraphQL Codegen, you can automatically generate TypeScript types based on your GraphQL schema and the GraphQL queries used in your project. This saves development time and keeps your frontend and backend code in sync.
- Improved Productivity: GraphQL Codegen significantly boosts developer productivity in TypeScript projects. It reduces the time spent on writing repetitive code, improves type safety, and enables seamless integration with existing workflows, resulting in faster development cycles.
- Consistency: By generating code from a central source of truth, i.e., your GraphQL schema, GraphQL Codegen ensures consistency across different parts of your TypeScript codebase. Any changes made to the schema or operations trigger regeneration of code, making it easy to keep your code up-to-date.
- Boilerplate Reduction: GraphQL Codegen eliminates repetitive code by automatically generating code for data fetching, serialization, and deserialization. This reduces manual effort and helps maintain a clean and concise codebase.
How to configure GraphQL Codegen
There are a number of ways to configure GraphQL Codegen. To understand the art of the possible, we recommend reading the GraphQL Code Generator documentation. Below is an example setup that will work well with TypeScript projects that use Nacelle Storefront SDK version 2.x.
Prepare our code editor
If using VSCode, we'll want to install the GraphQL for VSCode extension. This will provide syntax highlighting and autocomplete for GraphQL queries.
Install dependencies
Assuming that TypeScript is already installed in the project, the only devDeps that we'll need are related to GraphQL Codegen and GraphQL Config.
npm i -D @graphql-codegen/cli @graphql-codegen/client-preset graphql graphql-config
Next, we'll install Nacelle Storefront SDK 2.x as a regular dependency:
npm i @nacelle/storefront-sdk@latest
Create a GraphQL Codegen config file
Because we installed GraphQL Config alongside GraphQL Codegen, we can rely on a single configuration file to manage both tools. Create a file called graphql.config.json
in the root of the project and add the following:
{
"schema": "<your-nacelle-storefront-api-endpoint>",
"documents": "src/**/*.{graphql,js,ts,jsx,tsx}",
"extensions": {
"codegen": {
"ignoreNoDocuments": true,
"generates": {
"./src/gql/": {
"preset": "client"
}
}
}
}
}
Write a GraphQL query
In your project's src
directory, create a named GraphQL query with the /* GraphQL */
comment at the beginning of a tagged template literal. Be sure to give the query a unique name. For example:
/* GraphQL */ `
query FirstTenProducts {
allProducts(filter: { first: 10 }) {
edges {
node {
nacelleEntryId
}
}
}
}
`;
Run GraphQL Codegen
Let's begin by adding the following scripts to the package.json
file:
{
"scripts": {
"codegen": "graphql-codegen",
"codegen:watch": "graphql-codegen --watch"
}
}
Next, we'll run the following command to generate TypeScript types for our GraphQL query:
npm run codegen
We can supercharge our development workflow by running the codegen in watch mode, so that the generated types are updated as we create and update our GraphQL queries:
npm run codegen:watch
Use the generated types
After Codegen has run for the first time, we'll have a graphql
function that's exported from src/gql/index.ts
. This function accepts a GraphQL query and returns a Promise that resolves to the query's response data. Let's wrap our earlier GraphQL query with this new graphql
function:
import { graphql } from './gql';
const ProductsDocument = graphql(/* GraphQL */ `
query FirstTenProducts {
allProducts(filter: { first: 10 }) {
edges {
__typename
node {
nacelleEntryId
}
}
}
}
`);
Get fully-typed data from the Nacelle Storefront SDK
Nacelle Storefront SDK 2.x's query
method accepts the output of the GraphQL Codegen graphql
function. Let's use the ProductsDocument
query that we created earlier to create a typesafe response:
import { StorefrontClient } from '@nacelle/storefront-sdk';
import { graphql } from './gql';
const client = new StorefrontClient({
storefrontEndpoint: '<your-nacelle-storefront-api-endpoint>'
});
const ProductsDocument = graphql(/* GraphQL */ `
query FirstTenProducts {
allProducts(filter: { first: 10 }) {
edges {
__typename
node {
nacelleEntryId
}
}
}
}
`);
const { data: productsData } = await client.query({
query: ProductsDocument
});
Our development environment is now fully aware of the type of the productsData
returned by our GraphQL query. This gives us a great autocomplete experience:
If we try to provide this data to a function or UI component that expects a different type, our editor will warn us of the mismatch.
Enriching GraphQL queries with suggested fields
Because we've also configured GraphQL Config, we can enjoy suggestions and autocomplete for our GraphQL queries in our code editor. For example:
Enhancing type accuracy with __typename
in typedFields
__typename
in typedFields
Nacelle Storefront GraphQL API users with access to Typed Fields can take advantage of more precise data fetching with smaller data payloads. Using the Storefront SDK with GraphQL Codegen offers a stellar Typed Fields querying experience. But to get the most out of the Typed Fields experience in a TypeScript project, it’s important to know how to effectively leverage __typename
to unlock a smooth and typesafe development experience.
Using __typename
for type narrowing
__typename
for type narrowingAs described in the GraphQL spec, we can request the __typename
of any object in our query. The __typename
property acts as a type identifier, enabling you to deal with union types contained in Content.typedFields
. Let’s take a look at an example.
Example
Let's explore a practical application using a codegen-driven query:
import { StorefrontClient } from "@nacelle/storefront-sdk";
import { graphql } from "./gql";
const client = new StorefrontClient({
storefrontEndpoint: "<my-nacelle-storefront-graphql-endpoint>"
});
const TypedFieldsQueryDocument = graphql(/* GraphQL */ `
query TypedContentQuery($filter: ContentFilterInput) {
allContent(filter: $filter) {
edges {
node {
nacelleEntryId
typedFields {
__typename # <-- IMPORTANT!
... on FullSnackRecipeClubArticleFields {
relatedArticles {
edges {
node {
title
}
}
}
}
... on FullSnackRecipeClubBasicTasteFields {
handle
name
relatedRecipe {
handle
}
}
}
}
}
}
}
`);
const { data: contentData } = await client.query({
query: TypedFieldsQueryDocument,
variables: { filter: { first: 10 } },
});
Let’s consider the value of contentData?.allContent.edges.map((edge) => edge.node)
. This is an array of Content
data, but because we’ve specified Content Type-specific fields of interest with Inline Fragments, our nodes' typedFields
data could either be of type MyCmsArticleFields
or MyCmsBasicTasteFields
. Without leveraging __typename
in a conditional block, TypeScript can’t know whether a node’s typedFields
correspond to MyCmsArticleFields
or MyCmsBasicTasteFields
. Let’s take a look at how to leverage __typename
to unlock a fully typesafe experience:
contentData?.allContent.edges.forEach(({ node }) => {
if (node.typedFields?.__typename === "FullSnackRecipeClubArticleFields") {
// now we have access to `typedFields` that are
// specific to our `article` content type's fields
node.typedFields.relatedArticles?.edges.map(({ node }) => node?.title);
}
});
Using this technique in our TypeScript x GraphQL Codegen x Nacelle Storefront SDK project ensures our code is typesafe and enhances developer experience with powerful autocomplete.
Summary
By generating TypeScript types based on your GraphQL schema and queries, GraphQL Codegen ensures type safety throughout your codebase, reduces the chances of runtime errors, and improves developer productivity. By taking the time to configure GraphQL Codegen and GraphQL Config in your TypeScript project, you'll be able to enjoy long-lasting benefits of strong typing and automatic code generation.
Updated about 1 year ago