nuxt.js + Apollo Client: How to disable cache? - graphql

I managed to get an nuxt.js + nest.js with typescript and apollo graphql running.
To test if graphql works, i used the files from this example, and added a Button to the nuxt.js-page (on:click -> load all cats via graphql).
Everything works, reading and writing.
The problem is that after doing a mutation via playground or restarting the nest.js server with other graphql-data, the nuxt.js-page is displaying the old data(on click). I have to reload the whole page in the browser, to get the Apollo-Client fetching the new data.
I've tried to add a 'no-cache'-flag and 'network-only'-flag to nuxt.config.ts without success:
apollo: {
defaultOptions: {
$query: {
loadingKey: 'loading',
fetchPolicy: 'no-cache'
}
},
clientConfigs: {
default: {
httpEndpoint: 'http://localhost:4000/graphql',
wsEndpoint: 'ws://localhost:4000/graphql'
}
}
}
The function to get the cats:
private getCats() {
this.$apollo.query({ query: GET_CATS_QUERY }).then((res:any) => {
alert(JSON.stringify(res.data, null, 0));
});
}
How can I disable the cache or is there an other solution?

I had a similar problem recently and managed to fix it by creating a Nuxt plugin which overrides default client's options:
// plugins/apollo-overrides.ts
import { Plugin } from '#nuxt/types';
const apolloOverrides: Plugin = ({ app }) => {
// disable caching on all the queries
app.apolloProvider.defaultClient.defaultOptions = {
query: {
fetchPolicy: 'no-cache',
},
};
};
export default apolloOverrides;
Don't forget to register it in Nuxt's config:
// nuxt.config.js
export default {
...
plugins: [
'~/plugins/apollo-overrides',
],
...
};

I had problem like this you can fix it easily with remove $ before query
defaultOptions: {
query: {
fetchPolicy: 'no-cache',
errorPolicy: 'all'
}
},
And Reopen your dev server
If this solution not working add fetch policy for each query
.query({
query: sample,
variables: {},
errorPolicy: "all",
fetchPolicy: "no-cache"
})

Related

Query on page not refetching once navigating back to page

In my nextjs page I have the following hook (generated by using graphql-codegen) that fetches a graphql query.
const { data, error, loading, fetchMore, refetch, variables } = useGetShortlistQuery({
notifyOnNetworkStatusChange: true, // updates loading value
defaultOptions: {
variables: {
offset: undefined,
filterBy: undefined,
sortBy: SortBy.RecentlyAdded,
sortDirection: SortDirection.Desc,
},
},
});
This is the useGetShortlistQuery hook that is generated by graphql-codegen
export function useGetShortlistQuery(
baseOptions?: Apollo.QueryHookOptions<GetShortlistQuery, GetShortlistQueryVariables>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<GetShortlistQuery, GetShortlistQueryVariables>(GetShortlistDocument, options);
}
my component is wrapped in a HOC to enable Apollo Client
export default withApollo({ ssr: true })(Index);
The withApollo HOC uses #apollo/client and the cache property of the apollo client is as follows.
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
getShortlist: {
keyArgs: [],
merge(existing: PaginatedProperties | undefined, incoming: PaginatedProperties): PaginatedProperties {
return {
...incoming,
properties: [...(existing?.properties || []), ...(incoming?.properties || [])],
};
},
},
},
},
},
}),
The problem I am having is that on this page I update the variables on the useGetShortlistQuery using refetch which, in turn, updates the data.
However, if I navigate to another page, then come back to this page using this component. It doesn't seem to retrigger the graphql query so returns the previous data.
If you are using getStaticProps (or getServerSideProps) with pre rendered pages, it is a known behavior. It is due to optimisation by Next.js not re-rendering components between page navigations, with pages like [id].js.
The trick is to have a key on components that you want to see refreshing. You have multiple ways to do so. Having a different key on components tells React that it should be re-rendering the components, and thus will trigger again the hooks.
Practical example:
export const getStaticProps: GetStaticProps = async ({ params }) => {
const data = getData() //something that fetches your data here
return {
props: {
// some other data you want to return...
// some unique value that will be on each page
key: data.key
},
}
}
const MyPage: NextPage<InferGetStaticPropsType<typeof getStaticProps>> = (props) => {
<div key={props.key} />
}

Which `apollo-server-express` Version Work Best For These Apollo Server Packages?

I’m trying to get apollo-server-lambda or apollo-server-express to work with an executable schema for v3.36.
Here are the packages we use:
apollo-server-express#3.36 or apollo-server-lambda#3+
graphql-constraint-directive#3.0.0
#graphql-tools/schema#7.1.3
I ran multiple regression test to make it work, and it does not seem to hit GraphQL.
Here’s my Apollo server config:
const apolloServer = new ApolloServer({
schema: initializeSchema(),
plugins: [
ApolloServerPluginLandingPageGraphQLPlayground(),
{
didEncounterErrors(errors) {
logger.info(`didEncounterErrors:`)
logger.info(errors)
},
async requestDidStart(requestContext) {
logger.info(`Request started! ${requestContext}`);
return {
async parsingDidStart(requestContext) {
logger.info(`Parsing started! ${requestContext}`);
},
async validationDidStart(requestContext) {
logger.info(`Validation started! ${requestContext}`);
}
}
},
}],
context: async ({ event, context, express }) => {
logger.info(`Loading event... ${JSON.stringify(event)}`)
const newContext = {
headers: event.headers,
functionName: context.functionName,
event,
context,
expressRequest: express.req,
user: {} ?? null,
}
logger.info(`context ${JSON.stringify(newContext)}`)
return newContext
},
dataSources: () => {
logger.info('!initializing datasource')
initializeDbConnection()
return {}
},
...(['staging', 'production', 'demo'].includes(process.env.stage as string)
? { introspection: false, playground: false }
: {}),
})
I was able to log the executable schema inside initializeSchema, but it does not seem to hit the GraphQL Typedef and Resolver after upgrading. It just goes straight to context. So, I'm kinda stumped how to make HTTP request hit the Typedef and Resolvers using makeExecutableSchema()
I just need some advise or a list of table that could help me which version works best with the given apollo-server-<server_version>.

How to cache queries using Nuxt.js Apollo client?

My query fetchPolicy is set to cache-first. But Apollo doesn't cache the queries. For example, when I switch off my gql server, It returns NetworkError on client server.
Where can I see if the query is cached or not? I have Apollo dev tool Chrome extension and I can see there that my query is cached!
nuxt.config.js
export default {
modules: ['#nuxtjs/apollo'],
apollo: {
clientConfigs: {
default: '~/apollo.js',
},
},
}
apollo.js
import { InMemoryCache } from 'apollo-cache-inmemory'
export default (context) => {
return {
httpEndpoint: 'http://localhost:8000/graphql',
cache: new InMemoryCache(),
}
}
pages/index.vue
<script>
import getProducts from '~/queries/getProducts.gql'
export default {
async asyncData({ app }) {
let client = app.apolloProvider.defaultClient
const products = await client.query({
query: getProducts,
fetchPolicy: 'cache-first',
})
return { products }
},
}
</script>
It doesn't matter if the query is on server side or client side, both of them doesn't cache the queries:
mounted() {
this.$apollo
.query({
query: getProducts,
prefetch: false,
fetchPolicy: 'cache-first',
})
.then((data) => (this.products = data))
},
I also tried the Apollo specified method but was the same issue:
apollo: {
products: {
query: getProducts,
prefetch: true,
fetchPolicy: 'cache-first',
},
},
When I use cache-only, the products are empty and nothing to show.
What's the problem?

How to use 'cache-and-network' policy on ApolloClient.query()

I'm building an app using ApolloClient to query a GraphQL endpoint. I wish to utilize 'cache-and-network' fetch policy on normal queries since this particular policy only works for watchQueries. What I really want is the following:
If we can query the server, we get a response from the server.
If we can't query the server, we load the content from the cache, if it's cached
This is the code I'm using to instantiate the ApolloClient.
const defaultOptions = {
watchQuery: {
fetchPolicy: 'cache-and-network',
errorPolicy: 'ignore',
},
query: {
fetchPolicy: 'network-only',
errorPolicy: 'all',
},
mutate: {
errorPolicy: 'all'
}
}
const client = new ApolloClient({
cache: cache,
link: createUploadLink({
uri: 'http://localhost:3000/graphql',
}),
defaultOptions
});
So I think I have two options: Catch the first query response and if failed load the contents from the cache, or use watchQuery method to issue the queries.
I have no idea were how to do it so any help would be welcome!
I ended up ignoring the defaultOptions object in the constructor. I define the fetchPolicy in the query itself, depending on the network status.
function getZones() {
return ApolloService.client.query({
query: GET_ZONES_CLIENT,
fetchPolicy: navigator.onLine ? 'network-only' : 'cache-only'
})
}

How to cache using apollo-server

The apollo basic example at https://www.apollographql.com/docs/apollo-server/features/data-sources.html#Implementing-your-own-cache-backend they state that doing a redis cache is as simple as:
const { RedisCache } = require('apollo-server-cache-redis');
const server = new ApolloServer({
typeDefs,
resolvers,
cache: new RedisCache({
host: 'redis-server',
// Options are passed through to the Redis client
}),
dataSources: () => ({
moviesAPI: new MoviesAPI(),
}),
});
When I look at the examples of non-redis, it states that it's a simple { get, set } for cache. This means I should theoretically be able to do.
cache : {
get : function() {
console.log("GET!");
},
set : function() {
console.log("SET!");
}
}
No matter what I try, my cache functions are never called when I'm utilizing the graphQL explorer that apollo-server provides natively.
I have tried with cacheControl : true and with cacheControl set like it is in https://medium.com/brikl-engineering/serverless-graphql-cached-in-redis-with-apollo-server-2-0-f491695cac7f . Nothing.
Is there an example of how to implement basic caching in Apollo that does not utilize the paid Apollo Engine system?
You can look at the implementation of this package which caches the full response to implement your own cache.
import { RedisCache } from "apollo-server-redis";
import responseCachePlugin from "apollo-server-plugin-response-cache";
const server = new ApolloServer({
...
plugins: [responseCachePlugin()],
cache: new RedisCache({
connectTimeout: 5000,
reconnectOnError: function(err) {
Logger.error("Reconnect on error", err);
const targetError = "READONLY";
if (err.message.slice(0, targetError.length) === targetError) {
// Only reconnect when the error starts with "READONLY"
return true;
}
},
retryStrategy: function(times) {
Logger.error("Redis Retry", times);
if (times >= 3) {
return undefined;
}
return Math.min(times * 50, 2000);
},
socket_keepalive: false,
host: "localhost",
port: 6379,
password: "test"
}),
});
You should be able to use the NPM package 'apollo-server-caching' by implementing your own interface. See Implementing Your Own Cache which provides an example.

Resources