• Stars
    star
    192
  • Rank 202,019 (Top 4 %)
  • Language Vue
  • License
    MIT License
  • Created almost 5 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Easy Minimal GraphQL client integration with Nuxt.js.

nuxt-graphql-request

πŸ“‘ GraphQL Request Module

ci npm version Dependencies npm downloads code style: prettier License: MIT

Easy Minimal GraphQL client integration with Nuxt.js.

Features

  • Most simple and lightweight GraphQL client.
  • Promise-based API (works with async / await).
  • Typescript support.
  • AST support.
  • GraphQL Loader support.

πŸ“– Release Notes

Setup

Install with yarn:

yarn add nuxt-graphql-request graphql --dev

Install with npm:

npm install nuxt-graphql-request graphql --save-dev

nuxt.config.js

module.exports = {
  buildModules: ['nuxt-graphql-request'],

  graphql: {
    /**
     * An Object of your GraphQL clients
     */
    clients: {
      default: {
        /**
         * The client endpoint url
         */
        endpoint: 'https://swapi-graphql.netlify.com/.netlify/functions/index',
        /**
         * Per-client options overrides
         * See: https://github.com/prisma-labs/graphql-request#passing-more-options-to-fetch
         */
        options: {},
      },
      secondClient: {
        // ...client config
      },
      // ...your other clients
    },

    /**
     * Options
     * See: https://github.com/prisma-labs/graphql-request#passing-more-options-to-fetch
     */
    options: {
      method: 'get', // Default to `POST`
    },

    /**
     * Optional
     * default: true (this includes cross-fetch/polyfill before creating the graphql client)
     */
    useFetchPolyfill: true,

    /**
     * Optional
     * default: false (this includes graphql-tag for node_modules folder)
     */
    includeNodeModules: true,
  },
};

Runtime Config

If you need to supply your endpoints at runtime, rather than build time, you can use the Runtime Config to provide your values:

nuxt.config.js

module.exports = {
  publicRuntimeConfig: {
    graphql: {
      clients: {
        default: {
          endpoint: '<client endpoint>',
        },
        secondClient: {
          endpoint: '<client endpoint>',
        },
        // ...more clients
      },
    },
  },
};

Usage

Component

asyncData

import { gql } from 'nuxt-graphql-request';

export default {
  async asyncData({ $graphql, params }) {
    const query = gql`
      query planets {
        allPlanets {
          planets {
            id
            name
          }
        }
      }
    `;

    const planets = await $graphql.default.request(query);
    return { planets };
  },
};

methods/created/mounted/etc

import { gql } from 'nuxt-graphql-request';

export default {
  methods: {
    async fetchSomething() {
      const query = gql`
        query planets {
          allPlanets {
            planets {
              id
              name
            }
          }
        }
      `;

      const planets = await this.$graphql.default.request(query);
      this.$set(this, 'planets', planets);
    },
  },
};

Store actions (including nuxtServerInit)

import { gql } from 'nuxt-graphql-request';

// In store
export default {
  actions: {
    async fetchAllPlanets({ commit }) {
      const query = gql`
        query planets {
          allPlanets {
            planets {
              id
              name
            }
          }
        }
      `;

      const planets = await this.$graphql.default.request(query);
      commit('SET_PLANETS', planets);
    },
  },
};

GraphQL Request Client

Examples from the official graphql-request library.

Authentication via HTTP header

In nuxt.config.ts

// nuxt.config.ts

module.exports = {
  graphql: {
    clients: {
      default: {
        endpoint: 'https://swapi-graphql.netlify.com/.netlify/functions/index',
        options: {
          headers: {
            authorization: 'Bearer MY_TOKEN',
          },
        },
      },
    },
  },
};
Incrementally setting headers

If you want to set headers after the GraphQLClient has been initialised, you can use the setHeader() or setHeaders() functions.

// Set a single header
this.$graphql.default.setHeader('authorization', 'Bearer MY_TOKEN');

// Override all existing headers
this.$graphql.default.setHeaders({ authorization: 'Bearer MY_TOKEN' });
Set endpoint

If you want to change the endpoint after the GraphQLClient has been initialised, you can use the setEndpoint() function.

this.$graphql.default.setEndpoint(newEndpoint);
passing-headers-in-each-request

It is possible to pass custom headers for each request. request() and rawRequest() accept a header object as the third parameter

<script>
const requestHeaders = {
  authorization: 'Bearer MY_TOKEN',
};

export default {
  methods: {
    async fetchSomething() {
      const query = gql`
        query planets {
          allPlanets {
            planets {
              id
              name
            }
          }
        }
      `;

      // Overrides the clients headers with the passed values
      const planets = await this.$graphql.default.request(query, {}, requestHeaders);
      this.$set(this, 'planets', planets);
    },
  },
};
</script>

Passing more options to fetch

In nuxt.config.ts:

// nuxt.config.ts

module.exports = {
  graphql: {
    clients: {
      default: {
        endpoint: 'https://swapi-graphql.netlify.com/.netlify/functions/index',
        options: {
          credentials: 'include',
          mode: 'cors',
        },
      },
    },
  },
};

Or using setHeaders / setHeader:

// Set a single header
this.$graphql.default.setHeader('credentials', 'include');
this.$graphql.default.setHeader('mode', 'cors');

// Override all existing headers
this.$graphql.default.setHeaders({
  credentials: 'include',
  mode: 'cors',
});

Using GraphQL Document variables

<script>
import { gql } from 'nuxt-graphql-request';

export default {
  methods: {
    async fetchSomething() {
      const query = gql`
        query planets($first: Int) {
          allPlanets(first: $first) {
            planets {
              id
              name
            }
          }
        }
      `;

      const variables = { first: 10 };

      const planets = await this.$graphql.default.request(query, variables);
    },
  },
};
</script>

Error handling

<script>
import { gql } from 'nuxt-graphql-request';

export default {
  methods: {
    async fetchSomething() {
      const query = gql`
        {
          Movie(title: "Inception") {
            releaseDate
            actors {
              fullname # "Cannot query field 'fullname' on type 'Actor'. Did you mean 'name'?"
            }
          }
        }
      `;

      try {
        const data = await this.$graphql.default.request(endpoint, query);
        console.log(JSON.stringify(data, undefined, 2));
      } catch (error) {
        console.error(JSON.stringify(error, undefined, 2));
        process.exit(1);
      }
    },
  },
};
</script>

GraphQL Mutations

<script>
import { gql } from 'nuxt-graphql-request';

export default {
  methods: {
    async fetchSomething() {
      const mutation = gql`
        mutation AddMovie($title: String!, $releaseDate: Int!) {
          insert_movies_one(object: { title: $title, releaseDate: $releaseDate }) {
            title
            releaseDate
          }
        }
      `;

      const variables = {
        title: 'Inception',
        releaseDate: 2010,
      };

      const data = await this.$graphql.default.request(mutation, variables);
    },
  },
};
</script>

Receiving a raw response

The request method will return the data or errors key from the response. If you need to access the extensions key you can use the rawRequest method:

import { gql } from 'nuxt-graphql-request';

const query = gql`
  query planets($first: Int) {
    allPlanets(first: $first) {
      planets {
        id
        name
      }
    }
  }
`;

const variables = { first: 10 };

const { data, errors, extensions, headers, status } = await this.$graphql.default.rawRequest(
  endpoint,
  query,
  variables
);
console.log(JSON.stringify({ data, errors, extensions, headers, status }, undefined, 2));

File Upload

<script>
import { gql } from 'nuxt-graphql-request';

export default {
  methods: {
    handleFileUpload(file) {
      const mutation = gql`
        mutation uploadUserAvatar($userId: Int!, $file: Upload!) {
          updateUser(id: $userId, input: { avatar: $file })
        }
      `;

      const variables = { userId: 1, file };

      this.$graphql.default.request(mutation, variables);
    },
  },
};
</script>

Batch queries

<script>
import { gql } from 'nuxt-graphql-request';

export default {
  methods: {
    async fetchSomething() {
      const query1 = /* GraphQL */ `
        query ($id: ID!) {
          capsule(id: $id) {
            id
            landings
          }
        }
      `;

      const variables1 = {
        id: 'C105',
      };

      const query2 = /* GraphQL */ `
        {
          rockets(limit: 10) {
            active
          }
        }
      `;

      const query3 = /* GraphQL */ `
        query ($id: ID!) {
          core(id: $id) {
            id
            block
            original_launch
          }
        }
      `;

      const variables3 = {
        id: 'B1015',
      };

      try {
        const data = await this.$graphql.default.batchRequests([
          { document: query1, variables: variables1 },
          { document: query2 },
          { document: query3, variables: variables3 },
        ]);

        console.log(JSON.stringify(data, undefined, 2));
      } catch (error) {
        console.error(JSON.stringify(error, undefined, 2));
        process.exit(1);
      }
    },
  },
};
</script>

Cancellation

It is possible to cancel a request using an AbortController signal.

<script>
import { gql } from 'nuxt-graphql-request';

export default {
  methods: {
    async fetchSomething() {
      const query = gql`
        query planets {
          allPlanets {
            planets {
              id
              name
            }
          }
        }
      `;

      const abortController = new AbortController();

      const planets = await this.$graphql.default.request({
        document: query,
        signal: abortController.signal,
      });

      abortController.abort();
    },
  },
};
</script>

In Node environment, AbortController is supported since version v14.17.0. For Node.js v12 you can use abort-controller polyfill.

import 'abort-controller/polyfill';

const abortController = new AbortController();

Middleware

It's possible to use a middleware to pre-process any request or handle raw response.

Request & response middleware example (set actual auth token to each request & log request trace id if error caused):

function requestMiddleware(request: RequestInit) {
  const token = getToken()
  return {
    ...request,
    headers: { ...request.headers, 'x-auth-token': token },
  }
}

function responseMiddleware(response: Response<unknown>) {
  if (response.errors) {
    const traceId = response.headers.get('x-b3-traceid') || 'unknown'
    console.error(
      `[${traceId}] Request error:
        status ${response.status}
        details: ${response.errors}`
    )
  }
}

module.exports = {
  buildModules: ['nuxt-graphql-request'],

  graphql: {
    /**
     * An Object of your GraphQL clients
     */
    clients: {
      default: {
        /**
         * The client endpoint url
         */
        endpoint: 'https://swapi-graphql.netlify.com/.netlify/functions/index',
        /**
         * Per-client options overrides
         * See: https://github.com/prisma-labs/graphql-request#passing-more-options-to-fetch
         */
        options: {
          requestMiddleware: requestMiddleware,
          responseMiddleware: responseMiddleware,
        },
      },

      // ...your other clients
    },

    /**
     * Options
     * See: https://github.com/prisma-labs/graphql-request#passing-more-options-to-fetch
     */
    options: {
      method: 'get', // Default to `POST`
    },

    /**
     * Optional
     * default: true (this includes cross-fetch/polyfill before creating the graphql client)
     */
    useFetchPolyfill: true,

    /**
     * Optional
     * default: false (this includes graphql-tag for node_modules folder)
     */
    includeNodeModules: true,
  },
};

FAQ

Why use nuxt-graphql-request over @nuxtjs/apollo?

Don't get me wrong, Apollo Client is great and well maintained by the vue / nuxt community, I used Apollo Client for 18months before switching to graphql-request.

However, as I am obsessed with performances, Apollo Client doesn't work for me at all:

  • I don't need another state management as the Vue ecosystem is enough (Vuex & Persisted data).
  • I don't need an extra ~120kb parsed in my app for fetching my data.
  • I don't need subscriptions as I use pusher.com, there are also alternatives for a WS client: http://github.com/lunchboxer/graphql-subscriptions-client

Why do I have to install graphql?

graphql-request uses a TypeScript type from the graphql package such that if you are using TypeScript to build your project and you are using graphql-request but don't have graphql installed TypeScript build will fail. Details here. If you are a JS user then you do not technically need to install graphql. However, if you use an IDE that picks up TS types even for JS (like VSCode) then it's still in your interest to install graphql so that you can benefit from enhanced type safety during development.

Do I need to wrap my GraphQL documents inside the gql template exported by graphql-request?

No. It is there for convenience so that you can get the tooling support like prettier formatting and IDE syntax highlighting. You can use gql from graphql-tag if you need it for some reason too.

What's the difference between graphql-request, Apollo and Relay?

graphql-request is the most minimal and simplest to use GraphQL client. It's perfect for small scripts or simple apps.

Compared to GraphQL clients like Apollo or Relay, graphql-request doesn't have a built-in cache and has no integrations for frontend frameworks. The goal is to keep the package and API as minimal as possible.

Does nuxt-graphql-request support mutations?

Sure, you can perform any GraphQL queries & mutations as before πŸ‘

Development

  1. Clone this repository
  2. Install dependencies using yarn install or npm install
  3. Start development server using yarn dev or npm run dev

Roadmap

πŸ“‘ License

MIT License

More Repositories

1

nuxt-shopify

πŸ› Seamless Shopify Buy SDK integration with Nuxt.js.
TypeScript
353
star
2

bluise

πŸ„ Bluise - A Nuxt.js & Netlify CMS boilerplate.
Vue
171
star
3

bulmil

πŸ’„ A agnostic UI components library based on Web Components, made with Bulma & Stencil.
TypeScript
152
star
4

prisma-serverless

Prisma (Nexus) + Typescript + AWS Serverless Lambda = πŸŽ†
TypeScript
115
star
5

vue-places

Places component is based on places.js for Vue 2.x. Turn any <input> into an address autocomplete.
JavaScript
108
star
6

vue-embed

Vue 2.x component based on embed.js https://github.com/ritz078/embed.js
JavaScript
59
star
7

fastify-nuxtjs

Vue server side rendering support for Fastify with Nuxt
JavaScript
39
star
8

nuxt-ghost

Easy Ghost content API integration with Nuxt.js.
Vue
31
star
9

nuxt-stencil

Easy Stencil.js component library integration with Nuxt.js.
TypeScript
21
star
10

ui

CSS
5
star
11

sendle-node

Unofficial Node.js library for the Sendle API
TypeScript
4
star
12

cailloux

TypeScript
3
star
13

graphql-ethereum-address

Ethereum address scalar types for GraphQL
TypeScript
3
star
14

spera

Run & schedule your code in the background with a fully typed client
TypeScript
3
star
15

use-relay-pagination

React hook library to assist with GraphQL Relay pagination πŸ„β€β™‚οΈ
TypeScript
1
star
16

insomnia-plugin-user-agents

Insomnia plugin for generating user agents
JavaScript
1
star
17

mirage-iterm

🏝️ A port of the VS Code Mirage theme to iTerm2.
1
star
18

nuxt-dockerfile

🐳 Nuxt Dockerized
Dockerfile
1
star
19

atom-urple-syntax

Atom Urple Syntax theme
CSS
1
star
20

prismate

Just a quick simple boilerplate for prisma2 & apollo-server. Still very WIP
TypeScript
1
star
21

insomnia-plugin-cuid2

Insomnia plugin for generating cuids
JavaScript
1
star
22

vue2-superplaceholder

SuperPlaceholder based on superplaceholder.js for Vue 2.x.
JavaScript
1
star