Query Batching

Villus has support for query batching but it is not configured out of the box, this is because not all GraphQL implementations support query-batching. So you would need to manually import it and configure it with villus client.

The batch plugin is available as its own package under the name @villus/batch

Basic Batching

First, add the plugin to your dependencies using yarn or npm:

bashyarn add @villus/batch
# Or
npm install @villus/batch

Then import the batch plugin from villus and pass it at the very end of the plugins array in client configuration:

vue<script setup>
import { useClient } from 'villus';
import { batch } from '@villus/batch';

useClient({
  url: 'https://test.com/graphql',
  use: [batch()],
});
</script>

danger

Careful not to use batch with the default fetch plugin, both of them act as a fetcher and there can only be 1 fetcher plugin for villus at any given time.

And that’s it, all your nested components that use useQuery or useMutation will automatically be batched together in a single request:

vue<template>
  <div>
    <ul v-if="postsWithTitle">
      <li v-for="post in postsWithTitle.posts" :key="post.id">{{ post.title }}</li>
    </ul>
    <ul v-if="postsWithId">
      <li v-for="post in postsWithId.posts" :key="post.id">{{ post.title }}</li>
    </ul>
  </div>
</template>

<script setup>
import { useQuery } from 'villus';

// Both will be sent in a single request
const firstQuery = useQuery('{ posts { title } }');
const secondQuery = useQuery('{ posts { id } }');
</script>

Batching timeout

Batching is done by waiting for a specific time which is 10ms by default since the last executed query, and all queries executed within this time window will be batched together.

You can configure that time window by passing a timeout option to the batch function configuration:

vue<script setup>
import { useClient } from 'villus';
import { batch } from '@villus/batch';

useClient({
  url: 'https://test.com/graphql',
  use: [batch({ timeout: 50 })],
});
</script>

This will add a 50ms time window between queries to be batched together.

Batched operations limit

You can also introduce a limit on how many operations can be executed in a batch. Usually, it is a good idea to make sure you don’t include a lot of operations in a single batch which could have an inverse effect on performance since the total execution time now depends on all the operations being executed.

You can configure the batch limit by passing a maxOperationCount option to the batch function configuration:

vue<script setup>
import { useClient } from 'villus';
import { batch } from '@villus/batch';

useClient({
  url: 'https://test.com/graphql',
  use: [batch({ maxOperationCount: 5 })],
});
</script>

By default, it is 10.

Excluding certain operations

You can also exclude certain operations from being batched by passing an exclude option to the batch function configuration:

vue<script setup>
import { useClient } from 'villus';
import { batch } from '@villus/batch';

useClient({
  url: 'https://test.com/graphql',
  // Exclude all queries named "Posts"
  use: [batch({ exclude: ({ query }) => /query Posts/.test(query) })],
});
</script>

Options

You can customize a few aspects of the batch plugin:

The available options are:

OptionTypeDescription
fetchtypeof window.fetchPass this option if you plan to be specific about the fetch polyfill that will be used, by default it tries to find window.fetch on the browser or global.fetch on Node.js depending on the execution environment
timeoutnumberThe number of milliseconds to wait for before executing the batched queries
maxOperationCountnumberThe maximum number of operations to be included in a single batch
exclude(operation: ClientPluginOperation, ctx: PluginContext) => booleanIf returns true, the operation won’t be batched and will be fetched in a single non-batched request

Code

You can check the source code for the batch plugin and use it as a reference to build your own