New SvelteKit course: fullstacksveltekit.com

How I use GraphQL in my SvelteKit applications

One thing that keeps coming up in most of the SvelteKit applications I work on, is the need to use some sort of APIs to fetch data, and display it in the UI. And occasionally, these APIs are GraphQL APIs. With time, I've learned how to find a workflow that works for me with GraphQL, and I've come up with a few tips and tricks that I'll share here.

https://www.datocms-assets.com/129313/1713243173-sveltekit-graphql.png

One thing that keeps coming up in most of the SvelteKit applications I work on, is the need to use some sort of APIs to fetch data, and display it in the UI. Whether it's for simple marketing websites, complex e-commerce sites, or full-blown SaaS applications.

And occasionally, these APIs are GraphQL APIs. With time, I've learned how to find a workflow that works for me with GraphQL, and I've come up with a few tips and tricks that I'll share here.

Why do I like using GraphQL in my SvelteKit applications?

I've had quite a love and hate story with GraphQL. My first experiences with it were not that great, and I had countless complaints about the mental model it introduced to me.

I was used to thinking in terms of RESTful APIs, and I found it challenging to wrap my head around the idea of writing queries in a whole new language.

But then, I started realizing a few advantages over REST APIs.

First, I like the idea of being able to write queries in a more declarative way . Yes, it's a bit more verbose, but then, it's also a lot more readable. And with the right tools, you can hugely improve the overall developer experience.

Second, being able to query exactly what you need from the API and nothing else is a massive plus. Mostly in terms of performance.

And finally, even though it's an entire new language for querying APIs, it's still straightforward to learn, and once you get the hang of it, it's powerful . Plus, you get a lot of flexibility in terms of how you structure your queries.

How to use GraphQL in your SvelteKit applications

My idea of web (JavaScript) development can be summed up in the following three points:

  1. Performance matters.  I don't consider web performance as an afterthought. It's a fundamental part of the web development process. And it's something that I'm very passionate about.

  2. TypeScript is great , and in most cases, there are more reasons to use it than not.  I've been using TypeScript for a while now, and, although it has its quirks, it's been a great experience so far. And it's part of one of the  strong opinions  I advocate to at my agency.

  3. A happy developer is a productive developer .  I highly believe that a happy developer is a productive developer. And I'm constantly investigating how to make my development process more enjoyable and efficient.

Why am I telling you this? Because the way I use GraphQL (and generally web technologies) is highly influenced by my vision of web development.

Type safe queries and mutations

The first thing I do whenever I have to use GraphQL on a project is to make sure I can use it in a type — safe way . Most of GraphQL APIs also come with a schema, and today, they are plenty of tools in the TypeScript ecosystem that can help you generate the types for your queries and mutations based on the schema.

One of the most popular is  GraphQL-Codegen .

Personally, I prefer to one another tool, less popular, but more powerful:  Genql . It acts as a GraphQL client, and a CLI tool that generates the types for your queries and mutations based on the schema.

Let's take the example of  this very website . The blogs, FAQs, recipes, changelog and other content are stored in DatoCMS. The CMS exposes a  content delivery GraphQL API  that I use to fetch the data.

Installing and setting up Genql

The first thing you need to do is to install the GenqL CLI (preferably globally). You can do it by running the following command:

code loading...

Once that's done, you can use the  genql  command to generate the types for your queries and mutations in a dedicated directory.

For this website, the command looks like this:

code loading...

Let's break down the command:

  • --endpoint  is the URL of the GraphQL API you want to use. You can also use the  --schema  option to specify the path to the schema file if you have one.

  • --output  is the directory where the generated types will be saved.

  • -H  can be used to add headers to the request. You can add as many headers as you want.

  • --esm  is a flag that specifies that the generated types should be exported as ES modules.

The  X-Exclude-Invalid  is a header specific to DatoCMS that tells the API to use strict mode for non-nullable GraphQL types.

Once you run the command, you should see a new directory called  src/lib/server/dato/generated  that contains the generated types for your queries and mutations.

Generated Genql folder for Om Recipes

Using the generated types

Now that we have the types generated, we can go ahead and create a client that will be used to make requests to the GraphQL API.

Mine looks like this:

code loading...

From there, I can create queries and mutations using the client (which will be type safe because it's coming from the generated types).

For example, here is how I fetch each individual article from the CMS:

code loading...

The returned type from the function looks like this:

code loading...

Quite handy, isn't it? Now I can use this in my components without worrying about missing or wrongly writing a property, or missing a nullable property.

Everything behind a CDN cache

You might be wondering, what are those extras headers that I'm adding to the client? Well, the answer is that I'm using a CDN cache for my GraphQL API.

code loading...

I'm in favor of using a cache in front of my GraphQL API because, in many situations, a great cache solution can make a huge difference in the performance of your application. You can comply with the caching headers of the original API, and also add your custom headers, caching control, etc.

In this case (and in many other projects), I'm using Stellate . It provides a GraphQL edge caching, rate limiting and API insights on top of your existing GraphQL API.

I'm not affiliated in any way with Stellate. It's just, in my opinion, a great product, that adds a lot of value.

The process for using Stellate is quite simple. Once you have your Stellate account, you can create a new service, add your GraphQL API endpoint as a source, as well as the headers that are required to make the requests (in this case, the  Authorization  and  X-Exclude-Invalid  headers).

You then have to update the automatically generated config file for Stellate (you can do this from the Stellate dashboard), and add the cache policies for your GraphQL API.

Mine looks like this:

code loading...

You can see that I'm adding a  maxAge  of 3600 seconds (1 hour), and a  swr  of 3600 seconds (1 hour). This means that the cache will be valid for 1 hour, and the SWR (stale-while-revalidate) will be valid for 1 hour.

I'm also specifying which resources I want to be applied to that cache policy.

Once that's done, you can just go ahead and replace your GraphQL API endpoint in your application with the generated Stellate endpoint. And you're good to go!

Stellate will automatically purge the API cache when you introduce changes to the original GraphQL API.

Om Recipes cms Stellate dashboard

For each request that comes in, Stellate will also give you a performance report, the query that was executed, the response time, which cache policy was used, and much more.

Om Recipes cms Stellate individual request

Wrapping up

That's it for today. I hope you found this post useful, and that you'll be able to use GraphQL in a more efficient and type safe way in your SvelteKit applications.

If you have any questions or comments, feel free to reach out to me on 𝕏 ( @iamsegbedji ) or by email ( [email protected] ).

Thanks for reading, and happy coding!