Awesome
<p align="center"> <img src='./assets/VQL-Logo.svg' alt="VQL" width="500"> </p> <p align="center"> Clean up your Vue SFC Scripts by moving your graphql queries to their own block </p> <p align="center"> <a href="https://www.npmjs.com/package/vite-plugin-vue-gql" target="__blank"><img src="https://img.shields.io/npm/v/vite-plugin-vue-gql?color=a356fe&label=Version" alt="NPM version"></a> </p>Why?
When writing Vue clients for GraphQL APIs, I've noticed scripts in Vue SFC files have become over-filled with GraphQL queries and had a need to organize the code better without taking away from what makes SFCs great: Having all the code for a single component organized and in one place.
Moving queries to their own files would then create multiple files for a single component, cluttering the project more and reducing productivity in having to write components spanning multiple files.
Enter Vue GQL! I wrote this Vite plugin to allow placing GraphQL queries related to a component directly within the component file without cluttering scripts, by placing them within their own specialized <gql> tags.
⚠️ This Plugin is still in Development and currently only works with the
<script setup>
format
Install
# Install Plugin
npm i -D vite-plugin-vue-gql
# Install Peer Dependicies
npm i @urql/vue graphql
// vite.config.ts
import { defineConfig } from 'vite'
import Vue from '@vitejs/plugin-vue'
import Vql from 'vite-plugin-vue-gql'
export default defineConfig({
plugins: [
Vue(),
Vql(),
],
})
If you are using typescript, make sure you include the following in your tsconfig.json
{
"compilerOptions": {
"types": [
"vite-plugin-vue-gql/client"
]
}
}
Usage
Instead of import your functions from @urql/vue
you should now import them from the vql
package.
import { useQuery, useMutation, useSubscription } from 'vql'
<gql>
tags can have the following attributes, query
(not required), mutation
, subscription
, and name
. The first three attributes indicates what type of query it is while the name
attribute allows you to have multiple queries in the same Vue SFC.
<!-- Query-->
<gql></gql>
<!-- Mutation -->
<gql mutation></gql>
<!-- Subscription -->
<gql subscription></gql>
<!-- Named GQL Block -->
<gql name="users"></gql>
Examples
Basic Usage
<script setup lang="ts">
import { useQuery } from 'vql'
const { data } = useQuery()
</script>
<template>
<h1>{{ data.hello }}</h1>
</template>
<gql>
{
hello
}
</gql>
Query with Variables
<script setup lang="ts">
import { ref } from 'vue'
import { useQuery } from 'vql'
const name = ref('Evan')
const { data } = useQuery({ variables: { name } })
</script>
<template>...</template>
<gql>
query($name: String!) {
user(name: $name) {
username
}
}
</gql>
Named Query
<script setup lang="ts">
import { ref } from 'vue'
import { useQuery } from 'vql'
const name = ref('Evan')
const { data } = useQuery('users', { variables: { name } })
</script>
<template>...</template>
<gql name="users">
query($name: String!) {
user(name: $name) {
username
}
}
</gql>
Mutations
<script setup lang="ts">
import { ref } from 'vue'
import { useMutation } from 'vql'
const { executeMutation } = useMutation()
</script>
<template>...</template>
<gql mutation>
mutation($name: String!) {
createUser(name: $name) {
username
}
}
</gql>
Subscriptions
<script setup lang="ts">
import { ref } from 'vue'
import { useSubscription } from 'vql'
const isPaused = ref(false)
const handleSubscription = (messages = [], response) => {
return [response.newMessages, ...messages]
}
const { data } = useSubscription({ from: 'Eren' }, { pause: isPaused }, handleSubscription)
</script>
<template>...</template>
<gql mutation>
subscription MessageSub($from: String!) {
newMessages(from: $from) {
id
from
text
}
}
</gql>
Fragments
You can use fragments in your graphql queries, mutations, and subscriptions by specifying your .gql
files that contain your fragments in the config.
// vite.config.ts
import { defineConfig } from 'vite'
import Vue from '@vitejs/plugin-vue'
import Vql from 'vite-plugin-vue-gql'
export default defineConfig({
plugins: [
Vue(),
Vql({
fragments: './src/fragments/**/*.gql',
}),
],
})
Here is a general idea of what your fragments should look like
# src/fragments/albums.gql
fragment albumFields on Album {
id
name
image
}
Finally you can use these fragments in your Vue SFC
<script setup lang="ts">
import { ref } from 'vue'
import { useQuery } from 'vql'
const name = ref('RADWIMPS')
const { data } = useQuery({ variables: { name } })
</script>
<template>...</template>
<gql>
query($name: String!) {
queryArtists(byName: $name) {
name
image
albums {
...albumFields
}
}
}
</gql>
Type Definitions
You can automatically generate typescript type definition files from you graphql schema by providing a link to your server or a path to your graphql schema.
import { defineConfig } from 'vite'
import Vue from '@vitejs/plugin-vue'
import Vql from 'vite-plugin-vue-gql'
export default defineConfig({
plugins: [
Vue(),
Vql({
schema: 'https://my-api.dev/graphql',
dts: 'src/schema.d.ts',
}),
],
})
Whenever the application is run, vite-plugin-vue-gql will download the schema from your server or open the provided gql schema and generate a typescript type definition file for your schema via GraphQL Code Generator
Roadmap
- Add support for fragments
- Investigate automatically generating queries from SFC templates
License
MIT License © 2021-PRESENT Jacob Clevenger