apollo-cache-instorage
apollo-cache-instorage copied to clipboard
Apollo Cache implementation that facilitates locally storing resources
Apollo InStorageCache
apollo-cache-instorage is an extension to apollo-cache-inmemory that allows
for granular cacheability of resources, in a storage of choice.
Purpose
The most famous implementation of a persistence layer for Apollo Client is
apollo-cache-persist. The main caveats with that project is the fastly
growing size of the cache, and the incapability of chosing what needs and
needs not to be cached. apollo-cache-instorage solves that, while reducing
the complexity on the setup and limiting interaction points between the
caching solution and the Apollo Client multiple services.
Installation
yarn add apollo-cache-instorage
Usage
InStorageCache is an extension of InMemoryCache, so initialization is not so
different than the other:
import { InStorageCache } from 'apollo-cache-instorage'
import { HttpLink } from 'apollo-link-http'
import ApolloClient from 'apollo-client'
const cache = new InStorageCache({
storage: window.localStorage,
})
const client = new ApolloClient({
link: new HttpLink(),
cache,
})
Configuration
The InStorageCache constructor takes a config object with all the options available for InMemoryCache plus the following customization properties:
| name | type | default | required |
|---|---|---|---|
| storage | Object | true | |
| shouldPersist | Function | () => true |
false |
| normalize | Function | JSON.stringify |
false |
| denormalize | Function | JSON.parse |
false |
| prefix | String | '' |
false |
storage
A Web Storage complient storage implementation.
shouldPersist
shouldPersist(
operation: String,
dataId: String,
value: ?Object
)
Callback to determine if a given data object should be cached. Takes three arguments:
operation: the ongoing storage operation. Will either beget,set, ordelete;dataId: a data object ID as resolved bydataIdFromObject;value: the persisting data object, in case the operation isset.
normalize
normalize(
value: Object
)
Normalization executed against a data object before attaching to the storage for persistence. Defaults to JSON.stringify.
denormalize
Denormalization executed against a persisted data after retrieving from the storage. Defaults to JSON.parse.
prefix
A prefix to use when persisting data to the storage. Useful for cases when the storage is shared between other application needs.
@persist directive
To facilititate persistance opt-in, this package also provides a mechanism to identify parts of a query that should be persisted using a @persist directive. To enable that, you must:
- Configure
InStorageCachewith an extra keyaddPersistFieldset totrue; - Use a provided special implementation of
shouldPersist; - Add the
PersistLinkto the chain of links.
import { ApolloLink } from 'apollo-link'
import { createHttpLink } from 'apollo-link-http'
import { InStorageCache, PersistLink } from 'apollo-cache-instorage'
const cache = new InStorageCache({
addPersistField: true,
shouldPersist: PersistLink.shouldPersist,
})
const link = ApolloLink.from([
new PersistLink(),
createHttpLink({ uri: '/graphql' }),
])
Then, you can mark query selections for persisting using the directive:
query SomeQuery {
nonPersistingSelection {
field
}
persistingSelection @persist {
field
}
deepPersistingSelection {
persistingSelection @persist {
field
}
}
}
Caveats
ROOT_QUERY
Most of the cache consumption in Apollo starts off on the ROOT_QUERY special key. Make sure that if you implement shouldPersist you always allow the storage to persist the data related to this key, such as follows:
const shouldPersist = (operation, dataId, value) => {
if (dataId === 'ROOT_QUERY') return true
// ... other logic here.
}
cache.restore()
When restoring the cache (SSR hydration, for instance), keep in mind that any value inserted via hydrating will have precedence over the persisted data.
