Clean up your Vue SFC Scripts by moving your graphql queries to their own block
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 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"
]
}
}
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>
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>
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>
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
- Add support for fragments
- Investigate automatically generating queries from SFC templates
MIT License © 2021-PRESENT Jacob Clevenger