Skip to main content

Motivation

From previously working on a large GraphQL codebase, the boilerplate involved with shipping new features often slowed me down.

What#

gqless is a fundamentally new approach to a GraphQL client. It makes using your API enjoyable, by generating queries at runtime based upon the data your app consumes.

Your app#

const App = () => {
const { me, users } = useQuery();
return (
<div>
Hello {me.name}!
{users({ limit: 10 }).map((user) => (
<User key={user.id || 0} user={user} />
))}
</div>
);
};

Generated query#

query {
me {
name
}
users(limit: 10) {
id
name
}
}

Why#

We wanted a GraphQL client that lets you forget you're using GraphQL.

I also wanted to tackle some issues shared across all existing GraphQL clients:

  • Slow Typescript DX. Typescript should speed up your workflow, not slow it down

  • Inefficient queries, due to underutilized nesting. Relay is a solution, but has even more boilerplate ๐Ÿ˜ข

Workflow comparison#

Lets say you've just added a new field to your API, and want it displayed within multiple places in the UI:

type User {
username: String!
+ avatarUrl(size: Int!): String!
}

Conventional client#

First you'd need to search your components, and identify which queries need updating. After referring to your browser for documentation, you'd then update the query

query UserProfile(avatarSize: Int!) {
user {
...
+ avatarUrl(size: $avatarSize)
}
}

Typically you'd then run a type generator to create types for each query (changes may not be reflected in IDE straight away).

Finally you'd do the task you set out to do - updating the components,

const UserProfile = ({ id }: { id: string }) => {
const { data } = useQuery(USER_PROFILE, {
variables: { id, avatarSize: 100 },
});
return <img src={data.user.avatarUrl} />;
};

Using gqless#

Just update the UI, and the queries generated at runtime will reflect your changes.

import { User } from './gqless';
const UserProfile = ({ user }: { user: User }) => {
return <img src={user.avatarUrl({ size: 100 })} />;
};
Last updated on by Nate Wienert