Open samkelleher opened 5 years ago
Also, normalization makes a significant CPU load on the server side. Are there any thoughts on this issue?
You can disable normalization on a type-by-type basis by returning null
from the dataIdFromObject
function
@dylanwulf Thanks! Seems like it works.
Here is my case:
client.cache.extract()
) to the frontend to make hydration.Is it ok to use new InMemoryCache({ dataIdFromObject: () => null })
only on a server? Or maybe I have to normalize that state before hydration on a frontend? Are there any helpers to do that?
Also having this issue. We're using a GQL CMS to populate the page and the TransferState object is insanely large. You can scroll down and see pages of useless metadata.
Tried disabling the normalisation as above:
new InMemoryCache({ dataIdFromObject: () => null })
But my HTML response sizes went from 2.5mb to 5.3mb. Hopefully it's fixed in Apollo Client 3 but guessing that's still months away and will require some lengthy migration
Edit: I've shoved a basic cache in my services and serialize that instead of InMemoryCache and got huge savings in my delivered index.html 2.4mb -> 1.4mb.
Basically:
import { makeStateKey } from '@angular/platform-browser';
export const CACHE_STATE_KEY = makeStateKey<any>('cache.state');
export const cache = new Map<string, any>();
with Serialization:
// SSR hydration and dehydration of the cache
if (this.transferState.hasKey(CACHE_STATE_KEY)) {
const state = this.transferState.get<any>(CACHE_STATE_KEY, {});
Object.keys(state).forEach(key => cache.set(key, state[key]));
} else {
this.transferState.onSerialize(CACHE_STATE_KEY, () => Object.fromEntries(cache.entries()));
}
And usage:
return cache.has(cacheKey)
? of(cache.get(cacheKey))
: apollo.query({ ... }).pipe(
map(({ data }) => data.getSomething),
tap(v => cache.set(cacheKey, v)),
);
I've come back to this issue because Apollo InMemory is performing magic and ruining my responses. What the client is giving me is different to what the server is giving, I assume due to it trying to normalise something. I just want to outright disable this magic, I don't want any normalisation at all
Apparently a good solution is to just use apollo-cache-hermes (but haven't tried it yet): https://github.com/convoyinc/apollo-cache-hermes
apollo-cache-inmemory performs data normalisation before placing data into the cache, it does this by splitting apart the models hieararchy, giving it ids, and storing them as flat documents. The model is then stored using these IDs as reference.
The issue is, the output is very verbose. When doing Server Side Rendering, the cache is extracted (as per Apollos own guidance) and sent in the page as a JSON object.
A simple array of 20 items, where an item might have 3 or 4 levels or children, the resulting JSON payload can easily end up being over 10MB in size.
The splitting apart of models is redundant if those child types are never referenced directly.
It is desired that the data is stored as downloaded without needing to do any normalisation. Ie, the cache would use the query as the key, but instead of reconstructing the normalised results; just return the original data.
Perhaps I'll have to use a different cache method than what this lib provides.
Feature documentation: https://github.com/apollographql/apollo-client/tree/master/packages/apollo-cache-inmemory#normalization
Similiar issue closed by author: https://github.com/apollographql/apollo-client/issues/3822