Imagine having a collection of famous dishes as a chef. Everyone asks for the recipe, requiring details like ingredients, quantities, cooking time, and preparation time. To avoid repeating yourself, you can write a recipe book or post it on a blog. You can update it in one place if there is any change in the recipe.
Codegen solves this problem if you use typescript for front-end development. It ensures that frontend and backend types, schemas, and other elements stay synchronized.
The End Goal
By the end of this article, we're striving for a better and smoother development experience like this:
Before we begin experimenting with our code, let's first understand
The Power of GraphQL Codegen: Why It Matters for Your Project
Are you using TypeScript for your front-end development? If so, you're likely aiming for strict typing across the board – from UI components to services and business logic. With the help of frameworks like @types/..packages, this becomes a smooth process.
But here's the challenge: What about the data you retrieve from external services?
You might know the structure and types of the external data, making manual type definitions seem simple. However, here's the twist: if the backend team alters variable types, adds new ones, or removes existing ones, maintaining consistency across your codebase becomes nearly impossible.
Now, let's talk about GraphQL. You might already be aware that GraphQL APIs are strongly typed and built around a GraphQL schema. Through GraphQL operations like queries, mutations, fragments, and subscriptions, you can efficiently fetch data on the client side.
But before we dive into the world of generated types, let's take a quick look at how it works behind the scenes. Understanding this process will give you a solid foundation for harnessing GraphQL codegen's potential effectively.
How does GraphQL Code Generator Work?
In order to generate code and types, GraphQL Code Generator depends on 2 main core concepts GraphQL Introspection and GraphQL AST.
Introspection is the ability to query which resources are available in the current API schema. Given the API, via introspection, we can see the queries, types, fields, and directives it supports.
The type \_\_Schema is the one that defines the Schema the API provides. It returns which types the Schema has, the queryType, the mutationType, and the subscriptionType.
Let's take an example using Gitthub API:
It represents the type we define in our system. A simple User type is illustrated below-
__typename is a special field in GraphQL that provides the name of the object type associated with a specific GraphQL object. This reserved field, along with id, holds importance because well-known clients like Apollo and Relay leverage them for client-side caching purposes.
GraphQL AST :
Abstract Syntax tree is a structure that is used in compilers to parse the code we write and convert it into a tree structure that we can traverse programmatically.
When a user initiates a request, GraphQL performs a crucial task – it merges the user's query document with the schema definition that we've set for our resolver. This combination is presented in the form of an Abstract Syntax Tree (AST). This AST plays a pivotal role in determining the requested fields, included arguments, and more.
Once the GraphQL types (both schema types and operations) are identified, the code generator comes into play. It collaborates with various sets of plugins to craft specific code snippets and types tailored to your needs.
Let's delve into this process as it pertains to the
GraphQL Code Generator Flow Chart
Within our flow chart, we harnessed the power of TypeScript in combination with TypeScript-Operations and TypeScript-React-Apollo for seamless GraphQL integration. Beyond that, a wealth of GraphQL plugins stands ready to elevate our development journey.
Now that we've explored the GraphQL code generator, its significance, and its mechanics, it's time to seamlessly incorporate it into our project.
Step 1: Setup
Create a new project react/nextJs by running the following command
npx create-next-appor, clone the project by running these commands and skip the next steps-
Step 2: Install dependencies
Applications that use Apollo Client require two main packages
graphQL. Run the following command to install both packages-
In our example application, we're going to use Star Wars API
Step 3: Initialise Apollo client
Next, we'll ApolloClient and connect react using ApolloProvider; here, uri is our graphQL server URL, and the cache is an instance of InMemoryCache, which Apollo Client uses to cache data after fetching them.
Apollo Client has been configured. Now to generate relevant
types of Query and Mutation we need
GraphQL Codegen CLI as we discussed earlier.
Step: 4 Install GraphQL Codegen dependencies
In addition, we're installing extra packages that include plugins designed to generate query types, pre-built hooks, and functions.
Step 5: Create a codegen.ts file
To set things up, navigate to your project's root directory. Here, create a file named
codegen.ts. Then, copy and paste the following content into this newly created file.
Let's start by breaking down the contents of the CodegeConfig file:
schema: This is the URL of your GraphQL server.
documents: For larger applications, handling numerous queries can become complex. To keep our code organized, we're adopting a pagewise query file system.
src/types/graphql.tsx: This is where all the generated data will be stored.
plugins: A series of plugins work together to generate types, hooks, and components. You can explore more available Codegen Plugins.
But what if your API needs an authentication token? Or what if you're dealing with multiple APIs that can't coexist in the same folder? In such cases, the following configuration can come to the rescue.
Step 6: Head to package.json and add these scripts
It's finally time to generate types; go ahead and open your terminal and run yarn generate or npm generate.
If you come across something like this, congratulations – you've just unlocked the finest GraphQL frontend experience, complete with fully typed Queries and Mutations! Now, let's delve into what we've accomplished and how to make the most of it.
Writing GraphQL Queries
In the past, we employed the useQuery hook from @apollo/client by passing the query into the hook to retrieve data, as shown below:
And with the help of generated hooks, we can directly use them instead of
useAllFilmsQuery()hook gets triggered as soon as the page URL hits.
- If there is a case when you only want to hit query after some action like a button click we have
When dealing with deeply nested data, it's a common challenge to lose track of key pairs or run into errors caused by potential
null | undefined values. Debugging such errors can be quite a headache.
The major benefit of adopting this approach, in my view, is twofold: type safety and time efficiency. By doing so, our IDE's IntelliSense becomes a guiding light, offering insights into the structure of the data response. This accelerates app development and ensures early detection of bugs during code composition.
Generate More than Just Types
As mentioned earlier, codegen plugins offer more than just type and hook generation. One such plugin is
typescript-react-apollo, designed to generate both Higher Order Components (HOC) and Query Components.
Creating React Components with Apollo
Navigate to the codegen.ts file and switch
true. Then, execute
yarn generate in your terminal.
And then use it in your code:
Type Destructuring Tips
Accessing specific key values within an object offers several methods, one being
object["someKey"]. Now, applying a similar approach, let's dive into type destructuring.
In our scenario, consider the presence of
allFilms within the data structure. To determine its type, we start with the overall data type –
AllFilmsQuery (matching your query's name, appended with "QUERY"). The type of
allFilms is then represented as
However, situations can arise where your external data nests deeply, potentially with parent elements that are either
undefined. In a specific case, like
allFilms, it could be an array with the possibility of being
Then how to get what would be the type of films object. For this, we can not simply use
- First, select NonNullable value of AllFilmsQuery and pick
allFilmssomething like this-
- And then using the same logic select films
This method is very useful while looping through data or passing nested values in child components.
In this article, our goal was to clarify the necessity of codegen in your project, outlining how it operates and bridges the gap between GraphQL and TypeScript.
When crafting apps, my focus is on crafting code that's both easy to understand and straightforward, all while minimizing excessive effort. This approach has proven instrumental in reaching this aim.
Feel free to reach out with any questions, suggestions, or insights you might have. If you find this information intriguing and potentially valuable to others, don't hesitate to share it with