Skip to content

Instantly share code, notes, and snippets.

@luksak
Last active March 26, 2024 07:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save luksak/def035c8ed37892d967a05186efa180a to your computer and use it in GitHub Desktop.
Save luksak/def035c8ed37892d967a05186efa180a to your computer and use it in GitHub Desktop.
Integration of nuxt-graphql-middleware with nuxt-multi-cache with full cache tag propagation
export default defineNuxtPlugin((NuxtApp) => {
const state = useGraphqlState()
const event = useRequestEvent()
if (!state) {
return
}
state.fetchOptions = {
onResponse ({ request, response, options }) {
if (response._data.__cacheTags) {
const cacheTags = response._data.__cacheTags
useCDNHeaders((helper) => {
helper
.public()
.setNumeric('maxAge', 3600)
.set('staleIfError', 86400)
.set('staleWhileRevalidate', 86400)
.set('sharedMaxAge', 2592000)
.addTags(cacheTags)
}, event)
}
}
}
})
import { H3Event } from 'h3'
import { defineGraphqlServerOptions } from 'nuxt-graphql-middleware/dist/runtime/serverOptions'
import { GraphqlMiddlewareOperation } from 'nuxt-graphql-middleware/dist/runtime/settings'
import type { GraphqlMiddlewareRuntimeConfig } from 'nuxt-graphql-middleware/dist/runtime/types'
// @todo: Mocking the missing functions from nuxt-graphql-middleware
import { getFetchOptions, onServerError, onServerResponse, getEndpoint } from '../utils/middlewareFunctions'
import serverOptions from '#graphql-middleware-server-options-build'
import { useDataCache, useCDNHeaders } from '#nuxt-multi-cache/composables'
import useAddCDNHeaders from '~/composables/useAddCDNHeaders'
export default defineGraphqlServerOptions({
/**
* Alter response from GraphQL server.
*/
onServerResponse (event, graphqlResponse) {
const surrogateKey = graphqlResponse.headers.get('Surrogate-Key')
const cacheTags = surrogateKey.split(' ')
return { ...graphqlResponse._data, __cacheTags: cacheTags }
},
/**
* Cache requests in nuxt-multi-cache
*/
async doGraphqlRequest ({
event,
operationName,
operationDocument,
variables
}) {
// The operation (either "query" or "mutation").
const operation = event.context?.params
?.operation as GraphqlMiddlewareOperation
// Determine the endpoint of the GraphQL server.
// Get the fetch options for this request.
const fetchOptions = await getFetchOptions(
serverOptions,
event,
operation,
operationName
)
// Get the runtime config.
const runtimeConfig = useRuntimeConfig()
.graphqlMiddleware as GraphqlMiddlewareRuntimeConfig
// Determine the endpoint of the GraphQL server.
const endpoint = await getEndpoint(
runtimeConfig,
serverOptions,
event,
operation,
operationName
)
const cacheKey = `${operationName}|${JSON.stringify(variables)}`
const { value: cachedValue, addToCache } = await useDataCache(cacheKey, event)
// If the data is already in cache, return it
if (cachedValue) {
useAddCDNHeaders(event, cachedValue.__cacheTags)
return cachedValue
}
// The data isn't available in cache. We have to fetch it.
const response = await $fetch
.raw(endpoint, {
// @todo: Remove any once https://github.com/unjs/nitro/pull/883 is released.
method: 'POST' as any,
body: {
query: operationDocument,
variables,
operationName
},
...fetchOptions
})
.then((response) => {
return onServerResponse(
serverOptions,
event,
response,
operation,
operationName
)
})
.catch((error) => {
return onServerError(
serverOptions,
event,
error,
operation,
operationName
)
})
useAddCDNHeaders(event, response.__cacheTags)
// Save data to the cache and return it.
addToCache(response)
return response
}
})
import { H3Event } from 'h3'
import { useCDNHeaders } from '#nuxt-multi-cache/composables'
export default function (event: H3Event, cacheTags: string[]) {
useCDNHeaders((helper) => {
helper
.public()
.setNumeric('maxAge', 3600)
.set('staleIfError', 86400)
.set('staleWhileRevalidate', 86400)
.set('sharedMaxAge', 2592000)
.addTags(cacheTags)
}, event)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment