apollo
apollo copied to clipboard
Support apollo-cache-persist
What problem does this feature solve?
Saving data locally to local storage is imperative for PWA, this is supported by apollo-cache-persist but currently it is unclear/impossible to support it due to the client config not being loaded at the client (mode: client) and thus the window and subsequently the local storage is unavailable.
What does the proposed changes look like?
Ultimately this will be supported internally to support [loading before rendeing] : https://github.com/apollographql/apollo-cache-persist#how-do-i-wait-for-the-cache-to-be-restored-before-rendering-my-app with an added config option for which store to use.
alternatively allowing to run the apollo config in the client might solve this.
I haven't try apollo-cache-persist
before. apollo-module
is simply embed of vue-cli-plugin-apollo
to create vue-apollo
client with some more options use for vue-apollo
. You can take a look of all options, on README file or here https://vue-cli-plugin-apollo.netlify.com/guide/configuration.html#createapolloclient-options
It's have a cache option so you can try, may be it's look like this:
nuxt.config.js
{
modules: ['@nuxtjs/apollo'],
apollo: {
clientConfigs: {
default: '@/apollo-config.js'
}
}
}
in apollo-config.js
import { InMemoryCache } from 'apollo-cache-inmemory'
import { persistCache } from 'apollo-cache-persist'
export default function (ctx) {
const cache = new InMemoryCache()
try {
// See above for additional options, including other storage providers.
persistCache({
cache,
storage: window.localStorage
})
} catch (error) {
console.error('Error restoring Apollo cache', error)
}
return {
httpEndpoint: YOUR_ENDPOINT,
cache
}
}
not sure if it's work. Also I found this issue, it could be relevant: https://github.com/vuejs/vue-apollo/issues/565
@kieusonlam hi, thanks for the answer, I already tried exactly your code, the issue is that when the config is being run by next the window once is not present so you can't access the local storage
Hi @gotenxds - did you ever find a solution for this?
I believe the solution is to write "node safe" code
if (typeof window === 'object') {
persistCache({
cache,
storage: window.localStorage
});
}
@gotenxds / @kieusonlam
@fresh5447 have you tried it?
I just tried this, but it unfortunately does not work. Since the window is not available the persistCache does not get initialized which causes multiple errors when the site is loaded.
Hya @kieusonlam @RubenVanEldik @fresh5447 Sorry for the long wait I did not notice you asked, I did find a "solution" for this, tell me what you think
In my config.ts file I import a file I call getCache
and use that in as the cache:
import cache from './getCache'
export default (ctx: Context) => {
const onCacheInit = (cache: InMemoryCache) => {
const data = {
...
}
cache.writeData({ data })
}
return {
cache,
...
}
}
in getCache file looks like this:
import { InMemoryCache } from 'apollo-cache-inmemory'
const cache = new InMemoryCache({
freezeResults: true,
})
export default cache
Now I also made a plugin file in /plugins/persistCache.ts
import Vue from 'vue'
import { persistCache } from 'apollo-cache-persist'
import cache from '../apollo/getCache'
export default () => {
persistCache({
cache,
// debug: true,
storage: window.localStorage as any,
maxSize: false,
}).then(() => {
Vue.prototype.$cacheReady = true
})
}
and in the config:
plugins: [
{ src: '~/plugins/persistCache', mode: 'client' },
],
Hope this helps
Hi @gotenxds,
Thank you for your time and attention!
I didn't get it to work yet, but it might be because I don't understand two parts of your code yet.
- What does this do?
a. What do you have to put in the data const?
b. Is
cache: InMemoryCache
valid syntax?
const onCacheInit = (cache: InMemoryCache) => {
const data = {
...
}
cache.writeData({ data })
}
- Is
as any
a typo? My linter throws an error and I don't know this syntax as well. 🙃
storage: window.localStorage as any,
Hi @gotenxds,
Thank you for your time and attention!
I didn't get it to work yet, but it might be because I don't understand two parts of your code yet.
- What does this do? a. What do you have to put in the data const? b. Is
cache: InMemoryCache
valid syntax?const onCacheInit = (cache: InMemoryCache) => { const data = { ... } cache.writeData({ data }) }
- Is
as any
a typo? My linter throws an error and I don't know this syntax as well. 🙃storage: window.localStorage as any,
Hi @RubenVanEldik This is just typescript syntax, if you're using plain javascript you can juse remove that, so it will look like this:
const onCacheInit = (cache) => {
const data = {
...
}
cache.writeData({ data })
}
export default () => {
persistCache({
cache,
// debug: true,
storage: window.localStorage,
maxSize: false,
}).then(() => {
Vue.prototype.$cacheReady = true
})
}
You can wrap it within process.client
like so... the Nuxt.js way.
import { persistCache } from "apollo-cache-persist";
if (process.client) {
try {
persistCache({
cache,
storage: window.localStorage,
key: "your-custom-cache-key",
})
} catch (error) {
console.error('Error restoring Apollo cache', error)
}
};
I am stuck at this too. Any plans to implement this?
Vue.prototype.$cacheReady
@gotenxds I am curious as to what you do with this Vue.prototype.$cacheReady
value, I suppose you wait for it to be true
somewhere before the first render... But where? Anywhere I try, persistCache
always finishes after client-side rendering begins and triggers issues...
For some one who may need in furure, I tested it and it okay but still has cors error
import { createHttpLink, from } from '@apollo/client/core';
import { provideApolloClient } from '@vue/apollo-composable';
import { createPersistedQueryLink } from '@apollo/client/link/persisted-queries';
import { sha256 } from 'crypto-hash';
export default defineNuxtPlugin((nuxtApp) => {
const { $apollo } = nuxtApp;
const linkChain = createPersistedQueryLink({ sha256 });
$apollo.defaultClient.setLink(from([linkChain]));
provideApolloClient($apollo.defaultClient);
});
For some one who may need in furure, I tested it and it okay but still has cors error
import { createHttpLink, from } from '@apollo/client/core'; import { provideApolloClient } from '@vue/apollo-composable'; import { createPersistedQueryLink } from '@apollo/client/link/persisted-queries'; import { sha256 } from 'crypto-hash'; export default defineNuxtPlugin((nuxtApp) => { const { $apollo } = nuxtApp; const linkChain = createPersistedQueryLink({ sha256 }); $apollo.defaultClient.setLink(from([linkChain])); provideApolloClient($apollo.defaultClient); });
I think that is a different issue, persistent queries as compared to persistcache, but maybe we can do something similar