Which is Better GraphQL Client and Utility Libraries?
graphql-tag vs graphql-tools vs apollo-client vs graphql.macro
1 Year
graphql-taggraphql-toolsapollo-clientgraphql.macroSimilar Packages:
What's GraphQL Client and Utility Libraries?

These libraries are essential tools for working with GraphQL in JavaScript applications. They provide various functionalities that enhance the development experience, from managing GraphQL queries and mutations to simplifying the integration of GraphQL with React and other frameworks. Each library serves a unique purpose, catering to different aspects of GraphQL implementation, such as client-side data management, query parsing, schema building, and macro capabilities for cleaner code.

NPM Package Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
graphql-tag6,395,5262,322-993 years agoMIT
graphql-tools635,3465,3462.68 kB1898 months agoMIT
apollo-client415,80719,352-5184 years agoMIT
graphql.macro23,382239-285 years agoMIT
Feature Comparison: graphql-tag vs graphql-tools vs apollo-client vs graphql.macro

Client-Side Management

  • graphql-tag: graphql-tag does not manage data itself but serves as a utility to define GraphQL queries in a more readable format. It simplifies the process of embedding queries directly in your components, allowing you to keep your data-fetching logic close to where it is used without the need for additional management features.
  • graphql-tools: graphql-tools is focused on server-side schema management rather than client-side data management. It provides utilities for building GraphQL schemas, merging multiple schemas, and defining resolvers, making it essential for developers looking to create robust GraphQL APIs.
  • apollo-client: Apollo Client excels in managing local and remote data with its powerful caching mechanism. It allows developers to seamlessly integrate GraphQL queries and mutations into their applications, providing a unified API for data fetching and state management. Its ability to handle optimistic UI updates and subscriptions makes it suitable for dynamic applications that require real-time data synchronization.
  • graphql.macro: graphql.macro enhances client-side management by allowing developers to write GraphQL queries as tagged template literals, which are then transformed at build time. This results in cleaner code and eliminates the need for string concatenation, improving the readability of data-fetching logic.

Ease of Use

  • graphql-tag: graphql-tag is straightforward and easy to use, requiring minimal setup. It is particularly beneficial for developers who want to quickly define queries without the overhead of a full client library. Its simplicity makes it a great choice for smaller projects or when experimenting with GraphQL.
  • graphql-tools: graphql-tools has a steeper learning curve due to its focus on schema manipulation and server-side development. However, once mastered, it provides powerful capabilities for building and managing GraphQL schemas, making it invaluable for backend developers.
  • apollo-client: Apollo Client is designed to be user-friendly, with extensive documentation and a strong community. Its integration with popular frameworks like React and Vue makes it easy to adopt, even for developers new to GraphQL. The API is intuitive, allowing for quick setup and effective data management without deep knowledge of GraphQL internals.
  • graphql.macro: graphql.macro is easy to integrate into existing projects and offers a simple syntax for writing queries. Its macro capabilities allow for cleaner code, but developers need to be familiar with the build process to leverage its full potential.

Performance

  • graphql-tag: graphql-tag has minimal performance overhead since it only parses GraphQL queries. It does not include any data management features, which keeps the bundle size small and improves performance in applications where complex state management is not required.
  • graphql-tools: graphql-tools is efficient for schema manipulation but does not directly impact client-side performance. Its performance is primarily relevant in server-side contexts, where it helps streamline schema definitions and resolver implementations, leading to faster API responses.
  • apollo-client: Apollo Client optimizes performance through its caching strategies, which reduce the number of network requests and improve loading times. It intelligently updates the cache based on the results of queries and mutations, ensuring that the UI reflects the latest data without unnecessary re-fetching.
  • graphql.macro: graphql.macro can enhance performance by reducing the size of the codebase through cleaner syntax. However, its impact on performance is more about code maintainability and readability than runtime efficiency.

Integration with Frameworks

  • graphql-tag: graphql-tag is framework-agnostic and can be used with any JavaScript framework. Its simplicity allows it to be easily integrated into existing projects without the need for extensive modifications, making it versatile for various use cases.
  • graphql-tools: graphql-tools is primarily used in server-side applications and integrates well with Node.js and Express. It is not directly tied to any front-end framework, but it can be used alongside Apollo Server or other GraphQL server implementations to enhance schema management.
  • apollo-client: Apollo Client integrates seamlessly with popular frameworks like React, Vue, and Angular, providing hooks and higher-order components that simplify data fetching and state management. This makes it a preferred choice for developers building modern web applications that require a strong connection between UI and data.
  • graphql.macro: graphql.macro is designed to work with modern JavaScript build tools and can be integrated into projects using Babel or Webpack. Its macro capabilities make it particularly useful in React applications, where it can simplify the way queries are written and managed.

Community and Support

  • graphql-tag: graphql-tag, being a utility library, has a smaller community compared to Apollo Client. However, it benefits from the broader GraphQL community, with many resources available for learning and troubleshooting.
  • graphql-tools: graphql-tools has a dedicated user base, especially among backend developers. While its community is not as large as Apollo Client's, it offers solid documentation and examples to help developers effectively use the library.
  • apollo-client: Apollo Client has a large and active community, providing extensive documentation, tutorials, and support resources. This makes it easier for developers to find solutions to common problems and share knowledge, fostering a collaborative environment for learning and development.
  • graphql.macro: graphql.macro is relatively new and has a smaller community. However, it is gaining traction among developers looking for cleaner syntax in their GraphQL queries, and its integration with popular build tools is well-documented.
How to Choose: graphql-tag vs graphql-tools vs apollo-client vs graphql.macro
  • graphql-tag: Select graphql-tag if you want a lightweight solution for parsing GraphQL queries directly in your JavaScript code. It is particularly useful for embedding queries in your components without the overhead of a full client library, making it a great choice for simple applications or when you want to keep your bundle size small.
  • graphql-tools: Opt for graphql-tools when you need to build and manipulate GraphQL schemas programmatically. It is perfect for creating mock data, merging multiple schemas, or defining resolvers, making it a go-to choice for server-side development and schema management.
  • apollo-client: Choose Apollo Client if you need a robust and feature-rich GraphQL client that supports caching, state management, and real-time updates through subscriptions. It is ideal for applications that require complex data handling and integration with React or other frameworks.
  • graphql.macro: Use graphql.macro if you prefer a more concise syntax for writing GraphQL queries within your JavaScript files. It allows you to leverage the power of macros to avoid string literals, improving code readability and maintainability, especially in large codebases.
README for graphql-tag

graphql-tag

npm version Build Status Get on Slack

Helpful utilities for parsing GraphQL queries. Includes:

  • gql A JavaScript template literal tag that parses GraphQL query strings into the standard GraphQL AST.
  • /loader A webpack loader to preprocess queries

graphql-tag uses the reference graphql library under the hood as a peer dependency, so in addition to installing this module, you'll also have to install graphql.

gql

The gql template literal tag can be used to concisely write a GraphQL query that is parsed into a standard GraphQL AST. It is the recommended method for passing queries to Apollo Client. While it is primarily built for Apollo Client, it generates a generic GraphQL AST which can be used by any GraphQL client.

import gql from 'graphql-tag';

const query = gql`
  {
    user(id: 5) {
      firstName
      lastName
    }
  }
`

The above query now contains the following syntax tree.

{
  "kind": "Document",
  "definitions": [
    {
      "kind": "OperationDefinition",
      "operation": "query",
      "name": null,
      "variableDefinitions": null,
      "directives": [],
      "selectionSet": {
        "kind": "SelectionSet",
        "selections": [
          {
            "kind": "Field",
            "alias": null,
            "name": {
              "kind": "Name",
              "value": "user",
              ...
            }
          }
        ]
      }
    }
  ]
}

Fragments

The gql tag can also be used to define reusable fragments, which can easily be added to queries or other fragments.

import gql from 'graphql-tag';

const userFragment = gql`
  fragment User_user on User {
    firstName
    lastName
  }
`

The above userFragment document can be embedded in another document using a template literal placeholder.

const query = gql`
  {
    user(id: 5) {
      ...User_user
    }
  }
  ${userFragment}
`

Note: While it may seem redundant to have to both embed the userFragment variable in the template literal AND spread the ...User_user fragment in the graphQL selection set, this requirement makes static analysis by tools such as eslint-plugin-graphql possible.

Why use this?

GraphQL strings are the right way to write queries in your code, because they can be statically analyzed using tools like eslint-plugin-graphql. However, strings are inconvenient to manipulate, if you are trying to do things like add extra fields, merge multiple queries together, or other interesting stuff.

That's where this package comes in - it lets you write your queries with ES2015 template literals and compile them into an AST with the gql tag.

Caching parse results

This package only has one feature - it caches previous parse results in a simple dictionary. This means that if you call the tag on the same query multiple times, it doesn't waste time parsing it again. It also means you can use === to compare queries to check if they are identical.

Importing graphQL files

To add support for importing .graphql/.gql files, see Webpack loading and preprocessing below.

Given a file MyQuery.graphql

query MyQuery {
  ...
}

If you have configured the webpack graphql-tag/loader, you can import modules containing graphQL queries. The imported value will be the pre-built AST.

import MyQuery from 'query.graphql'

Importing queries by name

You can also import query and fragment documents by name.

query MyQuery1 {
  ...
}

query MyQuery2 {
  ...
}

And in your JavaScript:

import { MyQuery1, MyQuery2 } from 'query.graphql'

Preprocessing queries and fragments

Preprocessing GraphQL queries and fragments into ASTs at build time can greatly improve load times.

Babel preprocessing

GraphQL queries can be compiled at build time using babel-plugin-graphql-tag. Pre-compiling queries decreases script initialization time and reduces bundle sizes by potentially removing the need for graphql-tag at runtime.

TypeScript preprocessing

Try this custom transformer to pre-compile your GraphQL queries in TypeScript: ts-transform-graphql-tag.

React Native and Next.js preprocessing

Preprocessing queries via the webpack loader is not always possible. babel-plugin-import-graphql supports importing graphql files directly into your JavaScript by preprocessing GraphQL queries into ASTs at compile-time.

E.g.:

import myImportedQuery from './productsQuery.graphql'

class ProductsPage extends React.Component {
  ...
}

Webpack loading and preprocessing

Using the included graphql-tag/loader it is possible to maintain query logic that is separate from the rest of your application logic. With the loader configured, imported graphQL files will be converted to AST during the webpack build process.

Example webpack configuration

{
  ...
  loaders: [
    {
      test: /\.(graphql|gql)$/,
      exclude: /node_modules/,
      loader: 'graphql-tag/loader'
    }
  ],
  ...
}

Create React App

Preprocessing GraphQL imports is supported in create-react-app >= v2 using evenchange4/graphql.macro.

For create-react-app < v2, you'll either need to eject or use react-app-rewire-inline-import-graphql-ast.

Testing

Testing environments that don't support Webpack require additional configuration. For Jest use jest-transform-graphql.

Support for fragments

With the webpack loader, you can import fragments by name:

In a file called query.gql:

fragment MyFragment1 on MyType1 {
  ...
}

fragment MyFragment2 on MyType2 {
  ...
}

And in your JavaScript:

import { MyFragment1, MyFragment2 } from 'query.gql'

Note: If your fragment references other fragments, the resulting document will have multiple fragments in it. In this case you must still specify the fragment name when using the fragment. For example, with @apollo/client you would specify the fragmentName option when using the fragment for cache operations.

Warnings

This package will emit a warning if you have multiple fragments of the same name. You can disable this with:

import { disableFragmentWarnings } from 'graphql-tag';

disableFragmentWarnings()

Experimental Fragment Variables

This package exports an experimentalFragmentVariables flag that allows you to use experimental support for parameterized fragments.

You can enable / disable this with:

import { enableExperimentalFragmentVariables, disableExperimentalFragmentVariables } from 'graphql-tag';

Enabling this feature allows you declare documents of the form

fragment SomeFragment ($arg: String!) on SomeType {
  someField
}

Resources

You can easily generate and explore a GraphQL AST on astexplorer.net.