GraphQL clients for JavaScript and Node.js
![Five Graphql Clients Javascript Nodejs]
GraphQL is a query language and runtime for APIs. It enables clients to specify queries and allows servers to validate data against a strongly typed schema.
Unlike REST APIs, GraphQL uses a single endpoint for all operations. GraphQL-based servers can only communicate via GraphQL queries. For simple projects, it’s feasible to use a REST client, like [Axios or fetch()] to send GraphQL queries. However, for larger, more complex projects that have advanced requirements, a GraphQL client is needed.
GraphQL clients make communication easier by abstracting away small details and implementing additional features, some of which include caching, query batching and deduplication, and static typing of GraphQL query results.
In this guide, we’ll compare the following five GraphQL clients and evaluate each in terms of functionality, community support, and size.
Let’s get started!
graphql-request
[graphql-request](https://graphql.org/code/)
is a very minimal GraphQL client. The library is isomorphic, meaning it supports both Node.js and browsers. It comes with first-class TypeScript support, so typings never become outdated. The library weighs just 5.2kB.
Activity
The graphql-request
GitHub repository activity is healthy, with 3.7K stars at the time of writing. On npm, graphql-request
is downloaded more than 1.3 million times weekly at the time of writing, so you shouldn’t have any trouble finding help online!
Pros
graphql-request
is simple to use, and there’s almost no learning curve:
import { GraphQLClient, gql } from 'graphql-request'
const query = gql`{
hero {
name
}
}`
const client = new GraphQLClient('<graphql-endpoint>')
const data = await client.request(query)
another example
async function main() {
const endpoint = 'https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr'
const query = gql`
query getMovie($title: String!) {
Movie(title: $title) {
releaseDate
actors {
name
}
}
}
`
const variables = {
title: 'Inception',
}
const data = await request(endpoint, query, variables)
console.log(JSON.stringify(data, undefined, 2))
}
main().catch((error) => console.error(error))
- Works on both server and client
- Support for TypeScript
- Very lightweight
- Strong community support
Cons
- No support for advanced features like query caching and deduplication
- No support for GraphQL subscriptions
Apollo Client
Apollo Client is an advanced GraphQL client only for frontends. It includes features for caching, query batching, query deduplication, and pagination. It can also be used to manage local state in place of a Redux store. The base library weighs about 33.9kB.
Apollo Client is written in TypeScript, so TypeScript support is excellent. It has integrations for popular frameworks and libraries like React, Next.js, Angular, and Vue.js. Apollo Client also has a Chrome extension for inspecting and making queries.
Activity
Apollo Client is updated at least once a month. It is downloaded more than 1 million times weekly on npm and has over 16K stars and 2K forks on GitHub at the time of writing.
Pros
- Robust and comprehensive
- Satisfies most use cases
- Support for TypeScript
- Integrations for popular UI libraries and frameworks
- Integrations for iOS and Android
- Chrome extension for inspecting queries
In addition to activity on npm and GitHub, Apollo Client enjoys online support in the form of a dedicated community forum. It also has commercial backing from Apollo GraphQL Inc.
Cons
- Steep learning curve for advanced features like query batching, persisted queries, and caching
What is URQL
URQL is a lightweight, extensible GraphQL client for React. Formidable introduced URQL in 2019 as an alternative to Apollo Client. URQL looks a bit similar to Apollo Client. Still, it also provides additional features and has better documentation, easy configuration, and support for features like offline mode, file uploads, and authentication.
How URQL is different from Apollo and others
Apollo is the most famous graphql client library within the react community, and you will be able to see some of the features in URQL are pretty similar to Apollo Client. Unlike Apollo Client, URQL comes with a single package where Apollo will require several packages to enable additional functionalities. The libraries' file size can be considered one significant difference since Apollo takes more than 100kb of size (with other libraries like apollo-boost + react-apollo), and urql takes 21.5kB. The size comparison shows the design philosophy and goals of urql. URQL is lightweight and extensible, and backed by the open-source community, which enabled URQL to solve persisted queries.
urql vs. Apollo vs. Relay
Why you should move to URQL
URQL was introduced as a result of Apollo’s growing complexity
- Built to be easy to use
- Performant and functional
- Logical default behavior and caching
- Easily extensible
Architecture of URQL
Uqrl takes a batteries-included approach where its architecture relies on unopinionated exchanges(plugins), allowing plug and play of features. By default, URQL will provide the adequate amount of features required to create a graphql application, and you can add more features through exchanges as you want. This plug-and-play architecture is the reason why URQL is a highly customizable and flexible GraphQL client.
Caching in URQL is fully customizable through the exchanges(plugins). URQL provides two different cashing mechanism
- Document Caching
Document caching behaves similar to the browser cache which helps to minimize sending the same requests to a GraphQL API repeatedly by caching the result of each query. Document caching will be available by default with URQL. - Normalized Caching
With time the application will grow, increasing the complexity of the data and the state managed by URQL. Normalized caching helps to avoid this complexity by denormalizing the JSON data back into a relational data structure, which stores all entities by a key that can be looked up directly to enable Normalized caching you will have to install the @urql/exchange-graphcache and include them in you URQL configuration.
Getting started with URQL
In this section, let's see how we can create a React application with the Graphql
Step 01: Installation
let’s install URQL on your React application through the following commands. These commands will install all the necessary
npx create-react-app urql-pokemons
cd urql-pokemons
yarn add urql graphql antd
Step 02: Configuring URQL
Configuring URQL is simple, and Configurations can do it in the index.js file of your React application. In this configuration, you will need to specify the endpoint of the graphql service that you are subscribing to through the parameter url. Any other options like additional headers can be configured through the fetchOptions section. After configuring the Client, you will need to pass it to the Provider Higher-Order component through the value prop, which wraps the entire application enabling you to access the graphql client throughout the application.
import { createClient, Provider } from 'urql';
const client = createClient({
url: process.env.REACT_APP_HASURA_URL,
fetchOptions: () => {
return {
headers: {
'content-type': 'application/json',
'x-hasura-admin-secret': process.env.REACT_APP_HASURA_SECRET
},
};
},
});ReactDOM.render(
<Provider value={client}>
<App />
</Provider>,
document.getElementById('root')
);
Step 03: Querying with URQL
Querying or calling queries and mutations through the URQL client is quite straightforward. URQL API provides two hooks in order to execute a Query and a Mutation. Both hooks provide a state to identify the state of the querying (fetching, error).
import { useQuery, useMutation } from 'urql';
const PokemonsQuery = `
query {
Pokemons_Pokemon {
id
name
power
description
}
}
`;
const createPokemon = `
mutation CreatePokemon($name: String!,$power:String!,$description:String!) {
insert_Pokemons_Pokemon(objects: { name: $name, power: $power, description: $description }) {
returning {
description
id
name
power
}
}
}`
const [{ data, fetching, error }] = useQuery({
query: PokemonsQuery,
});
const [{ fetching, error }, executeMutation] = useMutation(createPokemon)
Comments