@graphcommerce/docs 8.1.0-canary.5 → 8.1.0-canary.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Change Log
2
2
 
3
+ ## 8.1.0-canary.6
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1984](https://github.com/graphcommerce-org/graphcommerce/pull/1984) [`e05534f`](https://github.com/graphcommerce-org/graphcommerce/commit/e05534fff4990fd584fe401b55b6d9a33934e048) - Added docs about caching
8
+ ([@paales](https://github.com/paales))
9
+
3
10
  ## 8.1.0-canary.5
4
11
 
5
12
  ## 8.0.6-canary.4
@@ -0,0 +1,205 @@
1
+ # Caching
2
+
3
+ Caching can be a complex topic especially when you have multiple layers of
4
+ caching.
5
+
6
+ - [Cache on the server](#caching-on-the-server)
7
+ - [Cache in the browser](#caching-in-the-browser)
8
+ - [Cache in the service worker](#caching-in-the-service-worker)
9
+ - [Cache invalidation limitations](#cache-invalidation-limitations)
10
+
11
+ ## Caching on the server
12
+
13
+ ### During development
14
+
15
+ - Next.js will not cache any requests
16
+ - Magento will cache GraphQL calls. This is done by Magento itself, not by
17
+ GraphCommerce.
18
+
19
+ ### How long will a page be cached (getStaticProps)?
20
+
21
+ GraphCommerce uses
22
+ [Incremental Static Regeneration (ISR)](https://nextjs.org/docs/pages/building-your-application/data-fetching/incremental-static-regeneration#on-demand-revalidation)
23
+ to cache pages with getStaticProps.
24
+
25
+ > If you set a revalidate time of 60, all visitors will see the same generated
26
+ > version of your site for one minute. The only way to invalidate the cache is
27
+ > from someone visiting that page after the minute has passed.
28
+
29
+ The length is determined by the `revalidate` property on the object that is
30
+ returned by `getStaticProps`. In GraphCommerce
31
+ [we use 60 \* 20](https://github.com/search?q=repo%3Agraphcommerce-org%2Fgraphcommerce+revalidate%3A++path%3A%2F%5Eexamples%5C%2Fmagento-graphcms%5C%2Fpages%5C%2F%2F&type=code).
32
+
33
+ This means that a cache will be regenerated when:
34
+
35
+ 1. 20 minutes has passed
36
+ 2. A new request is made to the page
37
+
38
+ Note: A page will never fall out of the cache if it is not requested. Even if
39
+ this is a very long time. In practice this can be _days_.
40
+
41
+ ## How long will a page be cached (getServerSideProps)
42
+
43
+ Not all pages use getStaticProps, a
44
+ [few pages that are not static use getServerSideProps](https://github.com/search?q=repo%3Agraphcommerce-org%2Fgraphcommerce+getServerSideProps+path%3A%2F%5Eexamples%5C%2Fmagento-graphcms%5C%2Fpages%5C%2F%2F&type=code)
45
+
46
+ The pages that do not use ISR are `/c/[...url]` and `/search/[...url]` which are
47
+ filtered pages. These pages are not cached by the server at all.
48
+
49
+ Even though the `/c/[...url]` page
50
+ [sets a Cache-Control header](https://github.com/graphcommerce-org/graphcommerce/blob/canary/examples/magento-graphcms/pages/c/%5B...url%5D.tsx#L14-L17)
51
+ it isn't cached by Cloudflare and isn't cached by the browser / service worker.
52
+
53
+ ### What happens when a backend is offline?
54
+
55
+ If a page is rendered with getStaticProps and the had been rendered before, it
56
+ will keep showing the old page. If the page hadn't been rendered before, it will
57
+ show a 500 error.
58
+
59
+ ### How does caching work with Magento GraphQL?
60
+
61
+ Magento caches GraphQL queries that are send as GET requests (which are all
62
+ queries from GraphCommerce) and have a `@cache` directive configured in the
63
+ schema.
64
+
65
+ [Magento caches certain queries in GraphQL](https://developer.adobe.com/commerce/webapi/graphql/usage/caching/#cached-and-uncached-queries),
66
+ the following are relevant for GraphCommerce: `categories`, `products`, `route`.
67
+ You can also find out what is cached by doing a
68
+ [search in the Magento codebase](https://github.com/search?q=repo%3Amagento%2Fmagento2+%40cache%28cacheIdentity+path%3A*.graphqls&type=code).
69
+
70
+ Cache invalidation is using the same system as any page that is cached in
71
+ Varnish.
72
+ [GraphQL invalidation docs](https://developer.adobe.com/commerce/webapi/graphql/usage/caching/#cache-invalidation)
73
+
74
+ ### ApolloClient InMemory cache used on the server
75
+
76
+ By default a GraphQL API call is _not_ cached, but by configuring fetchPolicy:
77
+ 'cache-first' when running the query, we can cache the response of a GraphQL API
78
+ call.
79
+
80
+ To reduce the API calls to certain backends, we use an in-memory cache on the
81
+ server. There are two queries that are cached by ApolloClient's InMemory cache:
82
+
83
+ - Layout query
84
+ [`staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' })`](https://github.com/graphcommerce-org/graphcommerce/blob/7728774cd7e9a4463508a99344b177877e3c826b/examples/magento-graphcms/pages/%5B...url%5D.tsx#L156)
85
+ - HygraphAllPages query
86
+ [`await client.query({ query: HygraphAllPagesDocument, fetchPolicy: alwaysCache })`](https://github.com/graphcommerce-org/graphcommerce/blob/7728774cd7e9a4463508a99344b177877e3c826b/packages/hygraph-ui/lib/hygraphPageContent.ts#L31)
87
+
88
+ We do this because this reduces the amount of GraphQL requests made to Hygraph
89
+ about 100x. The Layout and HygraphAllPages query would else be request on _all_
90
+ pages.
91
+
92
+ The InMemory cache is kept indefinitely, it is never flushed! There currently is
93
+ no way to flush this cache. This means that while a serverless funtion is
94
+ running or a node process is running the cache will be kept in memory:
95
+
96
+ - For serverless functions (Vercel) this isn't a problem as they are killed
97
+ after a few minutes.
98
+ - For node.js processes this means that they _need_ to be restarted every now
99
+ and then. (a few times a day is fine)
100
+
101
+ ## Caching in the browser
102
+
103
+ ### Apollo Client caching in the browser
104
+
105
+ By default all the information stored in the ApolloClient InMemory cache is also
106
+ persisted to localStorage. When the page is loaded, the cache is restored from
107
+ localStorage.
108
+
109
+ Apollo Client tries and use the cache as much as possible. This means that
110
+ multiple useQuery calls with the same query+variables will return the same
111
+ result and all use the cache (default `fetchPolicy: 'cache-first'`)
112
+
113
+ The exception is when a query is made with a different `fetchPolicy`. We
114
+ [use 'cache-and-network' on quite a few queries](https://github.com/search?q=repo%3Agraphcommerce-org%2Fgraphcommerce+fetchPolicy%3A+%27cache-and-network%27&type=code)
115
+ to make sure that the user always sees up-to-date data.
116
+
117
+ #### Improvements since GraphCommerce 6.2.0:
118
+
119
+ We've introduced the
120
+ [persistenceMapper](https://github.com/graphcommerce-org/graphcommerce/blob/canary/packages/graphql/components/GraphQLProvider/persistenceMapper.ts#L27-L36)
121
+ that makes sure not everything gets persisted to localStorage. We prune the
122
+ cache based on a list of selectors. This aims to keep the cache as small as
123
+ possible, without chaning the default behavior that 'everything is persisted to
124
+ localStorage'.
125
+
126
+ ### What is stored in the localStorage?
127
+
128
+ All queries made with useQuery are stored in the localStorage of the user and is
129
+ restored when the user visits the website
130
+
131
+ - With GraphCommerce < 6.2.0: All queries made with useQuery are stored in the
132
+ localStorage of the user and is restored when the user visits the website
133
+ - With GraphCommerce >= 6.2.0
134
+
135
+ ### Which HTTP requests are cache by the browser?
136
+
137
+ - `pages` and `_next/data` requests are not cached and are requested each time a
138
+ page is visited. The `_next/data` requests is the actual data of a page to be
139
+ able to navigate faster over the site.
140
+ - `_next/static` requests are cached by the browser. These include `images`,
141
+ `fonts` and `js` and `css`. All files are hashed and cleaned up when a new
142
+ deployment is made.
143
+ - `_next/image`requests are cached by the browser, but has a 'revalidate' header
144
+ so requests will be revalidated by the browser.
145
+
146
+ ### Which HTTP requests are cached by the service worker?
147
+
148
+ Service worker sits between the browser and the network. It can cache requests
149
+ and return them from the cache instead of the network. This can be seen as an
150
+ _additional_ caching layer which can be configured separately from the browser
151
+ cache.
152
+
153
+ The service worker caches:
154
+
155
+ - [static fonts](https://github.com/shadowwalker/next-pwa/blob/master/cache.js#L28)
156
+ - [static images](https://github.com/shadowwalker/next-pwa/blob/master/cache.js#L39)
157
+ - [\_next/image](https://github.com/shadowwalker/next-pwa/blob/master/cache.js#L50)
158
+ - [js](https://github.com/shadowwalker/next-pwa/blob/master/cache.js#L85)
159
+
160
+ Note: When a new deployment is made, the service worker is updated. This means
161
+ that all previous caches are cleared and new caches are created.
162
+
163
+ It does not cache:
164
+
165
+ - [\_next/data](https://github.com/shadowwalker/next-pwa/blob/master/cache.js#L107):
166
+ Although it looks like it does, the regex is actually wrong and it does not
167
+ cache anything.
168
+ - [pages](https://github.com/shadowwalker/next-pwa/blob/master/cache.js#L152)
169
+ Uses NetworkFirst strategy, which means it will always try to fetch the
170
+ resource from the network first, and only if that fails it will use the cache.
171
+
172
+ ## Cache invalidation limitations
173
+
174
+ ### Pages keep having old information even though Magento has updated the data
175
+
176
+ Currently there is no communcation between Magento and Next.js to revalidate a
177
+ page when a product or category is updated.
178
+
179
+ This means that a page will only be revalidated when a user visits the page
180
+ again _and_ the revalidate time has been reached.
181
+
182
+ Suggested solution: Accept the revalidate time or reduce the revalidate time of
183
+ products and categories.
184
+
185
+ #### Pages keeps having stale global information
186
+
187
+ Even when a the LayoutDocument is refreshed by restarting a node.js process the
188
+ fresh data is not automatically shown to a user.
189
+
190
+ This means that a page only gets revalidated when a user visits the page again
191
+ _and_ the revalidate time has been reached.
192
+
193
+ This results in the situation that an header change like a navigation item or a
194
+ 'global message' will see the old information for a long time.
195
+
196
+ Suggested solution: Create a fresh deployment
197
+
198
+ 1. Manually create a fresh deployment.
199
+ 2. Vercel: Integrate a
200
+ [deploy hook](https://vercel.com/docs/concepts/deployments/deploy-hooks) as a
201
+ [Hygraph webhook](https://hygraph.com/docs/api-reference/basics/webhooks)
202
+ 3. Github actions: Integrate a
203
+ [webhook_run](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run)
204
+ as a
205
+ [Hygraph webhook](https://hygraph.com/docs/api-reference/basics/webhooks)
package/package.json CHANGED
@@ -2,10 +2,10 @@
2
2
  "name": "@graphcommerce/docs",
3
3
  "homepage": "https://www.graphcommerce.org/docs",
4
4
  "repository": "github:graphcommerce-org/graphcommerce/docs",
5
- "version": "8.1.0-canary.5",
5
+ "version": "8.1.0-canary.6",
6
6
  "sideEffects": true,
7
7
  "peerDependencies": {
8
- "@graphcommerce/prettier-config-pwa": "^8.1.0-canary.5"
8
+ "@graphcommerce/prettier-config-pwa": "^8.1.0-canary.6"
9
9
  },
10
10
  "prettier": "@graphcommerce/prettier-config-pwa"
11
11
  }