Gathering detailed insights and metrics for apollo-cache-inmemory
Gathering detailed insights and metrics for apollo-cache-inmemory
Gathering detailed insights and metrics for apollo-cache-inmemory
Gathering detailed insights and metrics for apollo-cache-inmemory
apollo-enchanted-cache-inmemory
Apollo InMemoryCache wrapper for storing selected only queries and for updating linked/nested without IDs
@jtlan/apollo-cache-inmemory
君土: Core abstract of Caching layer for Apollo Client
apollo-cache-inmemory-fork
Core abstract of Caching layer for Apollo Client
apollo-cache-core-inmemory
Core abstract of Caching layer for Apollo Client
The industry-leading GraphQL client for TypeScript, JavaScript, React, Vue, Angular, and more. Apollo Client delivers powerful caching, intuitive APIs, and comprehensive developer tools to accelerate your app development.
npm install apollo-cache-inmemory
Typescript
Module System
Node Version
NPM Version
91.6
Supply Chain
97.5
Quality
80.5
Maintenance
100
Vulnerability
100
License
@apollo/client@4.0.0-rc.3
Updated on Jul 01, 2025
v3.14.0-alpha.1
Updated on Jul 01, 2025
v3.14.0-alpha.0
Updated on Jun 27, 2025
@apollo/client-codemod-migrate-3-to-4@1.0.0-rc.0
Updated on Jun 27, 2025
@apollo/client@4.0.0-rc.2
Updated on Jun 27, 2025
@apollo/client@4.0.0-rc.1
Updated on Jun 24, 2025
TypeScript (98.64%)
JavaScript (1.13%)
HTML (0.2%)
Shell (0.04%)
Total Downloads
282,092,550
Last Day
17,376
Last Week
407,405
Last Month
1,747,299
Last Year
20,692,449
MIT License
19,593 Stars
12,860 Commits
2,688 Forks
270 Watchers
363 Branches
820 Contributors
Updated on Jul 03, 2025
Minified
Minified + Gzipped
Latest Version
1.6.6
Package Id
apollo-cache-inmemory@1.6.6
Size
159.07 kB
NPM Version
lerna/3.20.2/node@v10.15.3+x64 (darwin)
Node Version
10.15.3
Published on
May 09, 2020
Cumulative downloads
Total Downloads
Last Day
1.9%
17,376
Compared to previous day
Last Week
-9.1%
407,405
Compared to previous week
Last Month
2.8%
1,747,299
Compared to previous month
Last Year
-22.9%
20,692,449
Compared to previous year
1
apollo-cache-inmemory
apollo-cache-inmemory
is the recommended cache implementation for Apollo Client 2.0. InMemoryCache
is a normalized data store that supports all of Apollo Client 1.0's features without the dependency on Redux.
In some instances, you may need to manipulate the cache directly, such as updating the store after a mutation. We'll cover some common use cases here.
npm install apollo-cache-inmemory --save
After installing the package, you'll want to initialize the cache constructor. Then, you can pass in your newly created cache to ApolloClient.
1import { InMemoryCache } from 'apollo-cache-inmemory'; 2import { HttpLink } from 'apollo-link-http'; 3import ApolloClient from 'apollo-client'; 4 5const cache = new InMemoryCache(); 6 7const client = new ApolloClient({ 8 link: new HttpLink(), 9 cache 10});
The InMemoryCache
constructor takes an optional config object with properties to customize your cache:
true
)dataIdFromObject
in the Normalization section.InMemoryCache
uses a heuristic fragment matcher. If you are using fragments on unions and interfaces, you will need to use an IntrospectionFragmentMatcher
. For more information, please read our guide to setting up fragment matching for unions & interfaces.The InMemoryCache
normalizes your data before saving it to the store by splitting the result into individual objects, creating a unique identifier for each object, and storing those objects in a flattened data structure. By default, InMemoryCache
will attempt to use the commonly found primary keys of id
and _id
for the unique identifier if they exist along with __typename
on an object.
If id
and _id
are not specified, or if __typename
is not specified, InMemoryCache
will fall back to the path to the object in the query, such as ROOT_QUERY.allPeople.0
for the first record returned on the allPeople
root query.
This "getter" behavior for unique identifiers can be configured manually via the dataIdFromObject
option passed to the InMemoryCache
constructor, so you can pick which field is used if some of your data follows unorthodox primary key conventions.
For example, if you wanted to key off of the key
field for all of your data, you could configure dataIdFromObject
like so:
1const cache = new InMemoryCache({
2 dataIdFromObject: object => object.key
3});
This also allows you to use different unique identifiers for different data types by keying off of the __typename
property attached to every object typed by GraphQL. For example:
1const cache = new InMemoryCache({ 2 dataIdFromObject: object => { 3 switch (object.__typename) { 4 case 'foo': return object.key; // use `key` as the primary key 5 case 'bar': return object.blah; // use `blah` as the priamry key 6 default: return object.id || object._id; // fall back to `id` and `_id` for all other types 7 } 8 } 9});
To interact directly with your cache, you can use the Apollo Client class methods readQuery, readFragment, writeQuery, and writeFragment. These methods are available to us via the DataProxy
interface. Accessing these methods will vary slightly based on your view layer implementation. If you are using React, you can wrap your component in the withApollo
higher order component, which will give you access to this.props.client
. From there, you can use the methods to control your data.
Any code demonstration in the following sections will assume that we have already initialized an instance of ApolloClient
and that we have imported the gql
tag from graphql-tag
.
The readQuery
method is very similar to the [query
method on ApolloClient
][] except that readQuery
will never make a request to your GraphQL server. The query
method, on the other hand, may send a request to your server if the appropriate data is not in your cache whereas readQuery
will throw an error if the data is not in your cache. readQuery
will always read from the cache. You can use readQuery
by giving it a GraphQL query like so:
1const { todo } = client.readQuery({ 2 query: gql` 3 query ReadTodo { 4 todo(id: 5) { 5 id 6 text 7 completed 8 } 9 } 10 `, 11});
If all of the data needed to fulfill this read is in Apollo Client’s normalized data cache then a data object will be returned in the shape of the query you wanted to read. If not all of the data needed to fulfill this read is in Apollo Client’s cache then an error will be thrown instead, so make sure to only read data that you know you have!
You can also pass variables into readQuery
.
1const { todo } = client.readQuery({ 2 query: gql` 3 query ReadTodo($id: Int!) { 4 todo(id: $id) { 5 id 6 text 7 completed 8 } 9 } 10 `, 11 variables: { 12 id: 5, 13 }, 14});
This method allows you great flexibility around the data in your cache. Whereas readQuery
only allowed you to read data from your root query type, readFragment
allows you to read data from any node you have queried. This is incredibly powerful. You use this method as follows:
1const todo = client.readFragment({
2 id: ..., // `id` is any id that could be returned by `dataIdFromObject`.
3 fragment: gql`
4 fragment myTodo on Todo {
5 id
6 text
7 completed
8 }
9 `,
10});
The first argument is the id of the data you want to read from the cache. That id must be a value that was returned by the dataIdFromObject
function you defined when initializing ApolloClient
. So for example if you initialized ApolloClient
like so:
1const client = new ApolloClient({
2 ...,
3 dataIdFromObject: object => object.id,
4});
…and you requested a todo before with an id of 5
, then you can read that todo out of your cache with the following:
1const todo = client.readFragment({
2 id: '5',
3 fragment: gql`
4 fragment myTodo on Todo {
5 id
6 text
7 completed
8 }
9 `,
10});
Note: Most people add a
__typename
to the id indataIdFromObject
. If you do this then don’t forget to add the__typename
when you are reading a fragment as well. So for example your id may beTodo_5
and not just5
.
If a todo with that id does not exist in the cache you will get null
back. If a todo of that id does exist in the cache, but that todo does not have the text
field then an error will be thrown.
The beauty of readFragment
is that the todo could have come from anywhere! The todo could have been selected as a singleton ({ todo(id: 5) { ... } }
), the todo could have come from a list of todos ({ todos { ... } }
), or the todo could have come from a mutation (mutation { createTodo { ... } }
). As long as at some point your GraphQL server gave you a todo with the provided id and fields id
, text
, and completed
you can read it from the cache at any part of your code.
Not only can you read arbitrary data from the Apollo Client cache, but you can also write any data that you would like to the cache. The methods you use to do this are writeQuery
and writeFragment
. They will allow you to change data in your local cache, but it is important to remember that they will not change any data on your server. If you reload your environment then changes made with writeQuery
and writeFragment
will disappear.
These methods have the same signature as their readQuery
and readFragment
counterparts except they also require an additional data
variable. So for example, if you wanted to update the completed
flag locally for your todo with id '5'
you could execute the following:
1client.writeFragment({
2 id: '5',
3 fragment: gql`
4 fragment myTodo on Todo {
5 completed
6 }
7 `,
8 data: {
9 completed: true,
10 },
11});
Any subscriber to the Apollo Client store will instantly see this update and render new UI accordingly.
Note: Again, remember that using
writeQuery
orwriteFragment
only changes data locally. If you reload your environment then changes made with these methods will no longer exist.
Or if you wanted to add a new todo to a list fetched from the server, you could use readQuery
and writeQuery
together.
1const query = gql` 2 query MyTodoAppQuery { 3 todos { 4 id 5 text 6 completed 7 } 8 } 9`; 10 11const data = client.readQuery({ query }); 12 13const myNewTodo = { 14 id: '6', 15 text: 'Start using Apollo Client.', 16 completed: false, 17}; 18 19client.writeQuery({ 20 query, 21 data: { 22 todos: [...data.todos, myNewTodo], 23 }, 24});
Here are some common situations where you would need to access the cache directly. If you're manipulating the cache in an interesting way and would like your example to be featured, please send in a pull request!
First, you will need to initialize an InMemoryCache
on the server and create an instance of ApolloClient
. In the initial serialized HTML payload from the server, you should include a script tag that extracts the data from the cache.
1`<script> 2 window.__APOLLO_STATE__=${JSON.stringify(cache.extract())} 3</script>`
On the client, you can rehydrate the cache using the initial data passed from the server:
1cache: new Cache().restore(window.__APOLLO_STATE__)
If you would like to learn more about server side rendering, please check our our more in depth guide [here].
Being able to read and write to the Apollo cache from anywhere in your application gives you a lot of power over your data. However, there is one place where we most often want to update our cached data: after a mutation. As such, Apollo Client has optimized the experience for updating your cache with the read and write methods after a mutation with the update
function. Let us say that we have the following GraphQL mutation:
1mutation TodoCreateMutation($text: String!) { 2 createTodo(text: $text) { 3 id 4 text 5 completed 6 } 7}
We may also have the following GraphQL query:
1query TodoAppQuery { 2 todos { 3 id 4 text 5 completed 6 } 7}
At the end of our mutation we want our query to include the new todo like we had sent our TodoAppQuery
a second time after the mutation finished without actually sending the query. To do this we can use the update
function provided as an option of the client.mutate
method. To update your cache with the mutation just write code that looks like:
1// We assume that the GraphQL operations `TodoCreateMutation` and 2// `TodoAppQuery` have already been defined using the `gql` tag. 3 4const text = 'Hello, world!'; 5 6client.mutate({ 7 mutation: TodoCreateMutation, 8 variables: { 9 text, 10 }, 11 update: (proxy, { data: { createTodo } }) => { 12 // Read the data from our cache for this query. 13 const data = proxy.readQuery({ query: TodoAppQuery }); 14 15 // Add our todo from the mutation to the end. 16 data.todos.push(createTodo); 17 18 // Write our data back to the cache. 19 proxy.writeQuery({ query: TodoAppQuery, data }); 20 }, 21});
The first proxy
argument is an instance of [DataProxy
][] has the same four methods that we just learned exist on the Apollo Client: readQuery
, readFragment
, writeQuery
, and writeFragment
. The reason we call them on a proxy
object here instead of on our client
instance is that we can easily apply optimistic updates (which we will demonstrate in a bit). The proxy
object also provides an isolated transaction which shields you from any other mutations going on at the same time, and the proxy
object also batches writes together until the very end.
If you provide an optimisticResponse
option to the mutation then the update
function will be run twice. Once immediately after you call client.mutate
with the data from optimisticResponse
. After the mutation successfully executes against the server the changes made in the first call to update
will be rolled back and update
will be called with the actual data returned by the mutation and not just the optimistic response.
Putting it all together:
1const text = 'Hello, world!'; 2 3client.mutate({ 4 mutation: TodoCreateMutation, 5 variables: { 6 text, 7 }, 8 optimisticResponse: { 9 id: -1, // -1 is a temporary id for the optimistic response. 10 text, 11 completed: false, 12 }, 13 update: (proxy, { data: { createTodo } }) => { 14 const data = proxy.readQuery({ query: TodoAppQuery }); 15 data.todos.push(createTodo); 16 proxy.writeQuery({ query: TodoAppQuery, data }); 17 }, 18});
As you can see the update
function on client.mutate
provides extra change management functionality specific to the use case of a mutation while still providing you the powerful data control APIs that are available on client
.
The update
function is not a good place for side-effects as it may be called multiple times. Also, you may not call any of the methods on proxy
asynchronously.
No vulnerabilities found.
Reason
23 commit(s) and 27 issue activity found in the last 90 days -- score normalized to 10
Reason
no dangerous workflow patterns detected
Reason
license file detected
Details
Reason
security policy file detected
Details
Reason
no binaries found in the repo
Reason
branch protection is not maximal on development and all release branches
Details
Reason
Found 11/21 approved changesets -- score normalized to 5
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
78 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-06-30
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More