Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

(docs) - Update "Schema Awareness" with new information

+76 -34
docs/assets/partial-results.png

This is a binary file and will not be displayed.

+76 -34
docs/graphcache/schema-awareness.md
··· 5 5 6 6 # Schema Awareness 7 7 8 - As mentioned in the docs we allow for the schema to be passed 9 - to the `cacheExchange`. This allows for partial results and deterministic 10 - fragment matching. This schema argument is of type `IntrospectionQuery`, as JSON structure that 11 - describes your entire server-side `GraphQLSchema`. 8 + Previously, [on the "Normalized Caching" page](./normalized-caching.md) we've seen how Graphcache 9 + stores normalized data in its store and how it traverses GraphQL documents to do so. What we've seen 10 + is that just using the GraphQL document for traversal and the `__typename` introspection field 11 + Graphcache is able to build a normalized caching structure that keeps our application up-to-date 12 + across API results, allows it to store data by entities and keys, and provides us configuration 13 + options to write [manual cache updates](./cache-updates.md) and [local 14 + resolvers](./local-resolvers.md). 15 + 16 + While this is all possible without any information about a GraphQL API's schema, the `schema` option 17 + on `cacheExchange` allows us to pass an introspected schema to Graphcache: 18 + 19 + ```js 20 + const introspectedSchema = { 21 + __schema: { 22 + queryType: { name: 'Query', }, 23 + mutationType: { name: 'Mutation', }, 24 + subscriptionType: { name: 'Subscription', }, 25 + }, 26 + }; 27 + 28 + cacheExchange({ schema: introspectedSchema }); 29 + ``` 30 + 31 + In GraphQL, [APIs allow for the entire schema to be 32 + "introspected"](https://graphql.org/learn/introspection/), which are special GraphQL queries that 33 + give us information on what the API supports. This information can either be retrieved from a 34 + GraphQL API directly or from the GraphQL.js Schema and contains a list of all types, the types' 35 + fields, scalars, and other information. 36 + 37 + In Graphcache we can pass this schema information to enable several features that aren't enabled if 38 + we don't pass any information to this option: 39 + 40 + - Fragments will be matched deterministically: A fragment can be written to be on an interface type 41 + or multiple fragments can be spread for separate union'ed types in a selection set. In many cases, 42 + if Graphcache doesn't have any schema information then it won't know what possible types a field 43 + can return and may sometimes make a best guess and [issue a 44 + warning](./errors.md#16-heuristic-fragment-matching). If we pass Graphcache a `schema` then it'll 45 + be able to match fragments deterministically. 46 + - A schema may have non-default names for its root types; `Query`, `Mutation`, and `Subscription`. 47 + The names can be changed by passing `schema` information to `cacheExchange` which is important 48 + if the root type appears elsewhere in the schema, e.g. if the `Query` can be accessed on a 49 + `Mutation` field's result. 50 + - We may write a lot of configuration for our `cacheExchange` but if we pass a `schema` then it'll 51 + start checking whether any of the configuration options actually don't exist, maybe because we've 52 + typo'd them. This is a small detail but can make a large different in a longer configuration. 53 + - Lastly; a schema contains information on **which fields are optional or required**. When 54 + Graphcache has a schema it knows which fields can be made optional and it'll be able to generate 55 + "partial results". 56 + 57 + ### Partial Results 12 58 13 - With deterministic fragment matching if we use an interface or a union _Graphcache_ can be 100% sure 14 - what the expected types and shape of the data must be and whether the match is permitted. It also 15 - enables a feature called ["Partial Results"](#partial-results). 59 + As we navigate an app that uses Graphcache we may be in states where some of our data is already 60 + cached and some isn't. Graphcache normalizes data and stores it in tables for links and records for 61 + each entity, which means that sometimes it can maybe even execute a query against its cache that it 62 + hasn't sent to the API before. 63 + 64 + [On the "Local Resolvers" page](./local-resolvers.md#resolving-entities) we've seen how to write 65 + resolvers that resolver entities without having to have seen a link from an API result before. If 66 + Graphcache uses these resolvers and previously cached data we often run into situations where a 67 + "partial result" could already be generated, which is what Graphcache does when it has `schema` 68 + information. 69 + 70 + ![A "partial result" is an incomplete result of information that Graphcache already had cached 71 + before it sent an API result.](../assets/partial-results.png) 72 + 73 + Without a `schema` and information on which fields are optional, Graphcache will consider a "partial 74 + result" as a cache miss. If we don't have all of the information for a query then we can't execute 75 + it against the locally cached data after all. However, an API's schema contains information on which 76 + fields are required and which fields are optional, and if our apps are typed with this schema and 77 + TypeScript, can't we then use and handle these partial results before a request is sent to the API? 78 + 79 + This is the idea behind "Schema Awareness" and "Partial Results". When Graphcache has `schema` 80 + information it may give us partial results [with the `stale` flag 81 + set](../api/core.md#operationresult) while it fetches the full result from the API in the 82 + background. This allows our apps to show some information while more is loading. 16 83 17 84 ## Getting your schema 18 85 19 - But how do you get this introspected schema? The process of introspecting a schema is running an 86 + But how do you get an introspected `schema`? The process of introspecting a schema is running an 20 87 introspection query on the GraphQL API, which will give us our `IntrospectionQuery` result. So an 21 88 introspection is just another query we can run against our GraphQL APIs or schemas. 22 89 23 - As long as `introspection` as turned on and permitted, we can download an introspection schema by 90 + As long as `introspection` is turned on and permitted, we can download an introspection schema by 24 91 running a normal GraphQL query against the API and save the result in a JSON file. 25 92 26 93 ```js ··· 125 192 It may be worth checking what your bundler or framework does when you import a JSON file. Typically 126 193 you can reduce the parsing time by making sure it's turned into a string and parsed using 127 194 `JSON.parse` 128 - 129 - **What do we get from adding the schema to _Graphcache_?** 130 - 131 - ### Partial Results 132 - 133 - Once _Schema Awareness_ is activated in _Graphcache_, it can use the schema to check which fields 134 - and lists are marked as optional fields. This is then used to delivery partial results when 135 - possible, which means that different queries may give you partial data where some uncached fields 136 - have been replaced with `null`, while loading more data in the background, instead of our apps 137 - having to wait for all data to be available. 138 - 139 - Let's approach this with the example from ["Computed Queries"](./local-resolvers.md#resolve): We 140 - have our `TodosQuery` result which loads a list, and our app may want to get a specific `Todo` when 141 - the app transitions to a details page. We may have already written a resolver that tells 142 - _Graphcache_ what `Query.todo` does, but it may be missing some optional field to actuall give us 143 - the full detailed `Todo`. 144 - 145 - Without a schema _Graphcache_ would assume that because some fields are uncached and missing, it 146 - can't serve this query's data. But if it has a schema, it may see that the uncached fields are 147 - optional anyway and it can return a partial result for the `Todo` while it's fetching the full query 148 - in the background, which in the `OperationResult` also causes `stale` to be set to `true`. 149 - 150 - This means that _Schema Awareness_ can enable us to create apps that can display already cached data 151 - on page transitions, while the page's full data loads in the background, which can often feel much 152 - faster to the user.