Last active
March 26, 2024 07:04
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} | |
} | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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