villus

website·Indexed 35 days ago

https://villus.logaretm.com/

A minimal and fast GraphQL client for Vue.js with a small API footprint and bundle size under 4kb. It provides composition functions like useQuery(), useMutation(), and useSubscription() to manage GraphQL API states, along with support for TypeScript codegen, query batching, and a plugin-based architecture for caching and file uploads.

Tokens
12.8K
Snippets
72
Records
86
Agent score
58%

What's inside villus

  1. Overview of villus GraphQL client for Vue.js

    villus is a minimal, lightweight GraphQL client for Vue.js designed for both small projects and large complex applications. It provides a flexible alternative to Apollo Client, focusing on a small footprint while offering quality-of-life defaults like simple query caching. It is written in TypeScript and supports the Vue.js Composition API.
  2. Overview of villus GraphQL client

    villus is a small and fast GraphQL client for Vue.js with a bundle size under 4kb. It features built-in caching, TypeScript support for typed query responses and variables, reactivity via the Composition API, and native support for the Vue <Suspense /> component API.
  3. Implement in-memory caching with the Villus Cache Plugin

    The Cache Plugin provides a simple in-memory cache for Villus queries that persists until the page reloads or the client is destroyed. It does not apply to mutations, as those always require a fresh server response. The plugin is included by default in any Villus client unless otherwise specified.
    <script setup>
    import { useClient, cache, fetch } from 'villus';
    
    useClient({
      use: [cache(), fetch()],
    });
    </script>
  4. Configure villus client with plugins

    villus uses a plugin-based architecture to handle network requests, caching, and deduplication. By default, villus includes fetch (network execution), cache (in-memory cache), and dedup (removes duplicate pending queries). These are provided via the defaultPlugins() function. To add custom or additional plugins, pass a use array to the useClient configuration.
    <script setup>
    import { useClient, defaultPlugins } from 'villus';
    
    useClient({
      url: '/graphql',
      use: [...defaultPlugins()], // If not provided, defaultPlugins will be used by default
    });
    </script>
  5. Execute GraphQL operations using the Fetch Plugin

    The Fetch Plugin is a critical component of villus that executes GraphQL queries and mutations against a GraphQL API. It is included by default in any villus client unless explicitly specified otherwise. To ensure GraphQL operations are actually sent to the server, the client must have the fetch plugin, a batch plugin, or a custom equivalent plugin configured.
  6. Implement reactive queries

    If the query passed to useQuery is a ref or computed property, Villus treats it as a reactive query and will automatically re-fetch the data whenever the query string itself changes.
    <script setup>
    import { computed, ref } from 'vue';
    import { useQuery } from 'villus';
    
    const id = ref(1);
    
    const FetchTodo = computed(() => {
      return `query FetchTodo { 
          todo (id: ${id.value}) { text } 
        }
      `;
    });
    
    const { data } = useQuery({
      query: FetchTodo,
    });
    
    // Changing id.value will trigger an automatic re-fetch
    </script>
  7. Map subscription data to a specific format

    You can pass a mapper function as the second argument to useSubscription. This function receives the current result and returns a transformed value, which then becomes the data property returned by the hook. This is ideal for extracting specific fields or converting results to booleans.
    <script setup>
    import { useSubscription } from 'villus';
    
    const LastMessage = `
      subscription LastMessage {
        lastMessage {
          id
          from
          message
        }
      }
    `;
    
    const { data: lastMessage } = useSubscription(
      { query: LastMessage },
      ({ data }) => {
        return data?.lastMessage;
      },
    );
    
    // lastMessage.value will contain the mapped object
    </script>
  8. Perform basic mutations with useMutation

    The useMutation function allows you to execute GraphQL mutations. Unlike useQuery, it does not execute automatically and does not accept a variables option in its configuration. Mutations always use a network-only cache policy because they represent user actions.
    <template>
      <div>
        <div v-if="data">
          <p>{{ data.likePost.message }}</p>
        </div>
        <button @click="execute()">Submit</button>
      </div>
    </template>
    
    <script setup>
    import { useMutation } from 'villus';
    
    const LikePost = `
      mutation {
        likePost (id: 123) {
          message
        }
      }
    `;
    
    const { data, execute } = useMutation(LikePost);
    </script>
  9. Implement GraphQL subscriptions using the handleSubscriptions plugin

    Because GraphQL subscriptions are constant streams of data rather than single requests, Villus uses the handleSubscriptions plugin to manage them. The plugin requires a subscription forwarder: a function that receives the operation (query and variables) and returns an object containing a subscribe method that accepts an observer.
    <script setup>
    import { useClient, handleSubscriptions, defaultPlugins } from 'villus';
    import { createClient } from 'graphql-ws';
    
    // 1. Create your WebSocket client
    const wsClient = createClient({
      url: 'ws://localhost:9005/graphql',
    });
    
    // 2. Define the subscriptions handler
    const subscriptionsHandler = handleSubscriptions(operation => {
      return {
        subscribe: obs => {
          wsClient.subscribe(
            {
              query: operation.query,
              variables: operation.variables,
            },
            obs
          );
    
          return {
            unsubscribe: () => {
              // Handle cleanup if necessary
            },
          };
        },
      };
    });
    
    // 3. Install the handler in the Villus client
    const client = useClient({
      url: 'http://localhost:4000/graphql',
      use: [subscriptionsHandler, ...defaultPlugins()],
    });
    </script>
  10. Migrate useSubscription reducer arguments from Villus 2.x to 3.0

    In Villus 3.0, the argument order for the useSubscription() reducer function has been flipped to improve TypeScript detection with TypedDocuments and increase versatility. The first argument is now the new subscription result (incoming data), and the second argument is the previous reduced value.
    // Villus 2.x
    function reduceMessages(old, incoming) {
      // reduce values
    }
    
    // Villus 3.0
    function reduceMessages(incoming, old) {
      // reduce values
    }
  11. Execute a GraphQL subscription using useSubscription

    The useSubscription function allows you to listen to GraphQL subscriptions. It accepts a configuration object (containing the query and optional variables) and an optional callback handler to process incoming data and errors.
    <script setup>
    import { ref } from 'vue';
    import { useSubscription } from 'villus';
    
    const NewMessages = `
      subscription NewMessages {
        newMessages {
          id
          from
          message
        }
      }
    `;
    
    const messages = ref([]);
    useSubscription({ query: NewMessages }, ({ data, error }) => {
      if (data) {
        messages.value.push(...data.newMessages);
      }
      if (error) {
        // Handle errors
      }
    });
    </script>
  12. Configure multiple GraphQL providers in one application

    To query multiple different GraphQL APIs within the same application, create separate parent components for each client and call useClient within them. This scopes the specific client to the children of that respective parent component.
    <!-- ComponentA -->
    <script setup>
    import { useClient } from 'villus';
    useClient({
      url: '{GITHUB_API_ENDPOINT}',
    });
    </script>
    
    <!-- ComponentB -->
    <script setup>
    import { useClient } from 'villus';
    useClient({
      url: '{MY_API}',
    });
    </script>