File tree 3 files changed +31
-3
lines changed
3 files changed +31
-3
lines changed Original file line number Diff line number Diff line change @@ -5,7 +5,18 @@ import { deriveError } from "@/utils/error";
5
5
import { Options , buildRequest , buildResult } from "./common" ;
6
6
7
7
export const fetcher = async < T > ( opts : Options ) : Promise < T > => {
8
- const response = await fetch ( buildRequest ( opts ) ) ;
8
+ const request = buildRequest ( {
9
+ ...opts ,
10
+ // We use the browser default cache behaviour for the client side requests.
11
+ // There's no revalidation set on the client as we're already using SWR for
12
+ // that. The default cache behaviour will however make use of browser HTTP
13
+ // Conditional Requests and ETag headers which some endpoints in Storyden
14
+ // provide. This results in a mostly fast experience but it's slowed down a
15
+ // bit by the server side behaviour (see server.ts comment for more info.)
16
+ cache : "default" ,
17
+ } ) ;
18
+
19
+ const response = await fetch ( request ) ;
9
20
10
21
return buildResult < T > ( response ) ;
11
22
} ;
Original file line number Diff line number Diff line change @@ -11,6 +11,7 @@ export type Options = {
11
11
responseType ?: string ;
12
12
cookie ?: string ;
13
13
revalidate ?: number ;
14
+ cache ?: RequestCache ;
14
15
} ;
15
16
16
17
export class RequestError extends Error {
@@ -29,6 +30,7 @@ export function buildRequest({
29
30
params,
30
31
data,
31
32
revalidate,
33
+ cache,
32
34
} : Options ) : Request {
33
35
const apiAddress = getAPIAddress ( ) ;
34
36
const address = `${ apiAddress } /api${ url } ${ cleanQuery ( params ) } ` ;
@@ -42,7 +44,7 @@ export function buildRequest({
42
44
credentials : "include" ,
43
45
headers,
44
46
body : buildPayload ( data ) ,
45
- cache : "default" ,
47
+ cache,
46
48
next : {
47
49
tags,
48
50
revalidate,
Original file line number Diff line number Diff line change @@ -22,7 +22,22 @@ export const fetcher = async <T>(url: string, opts: Options): Promise<T> => {
22
22
headers,
23
23
method : opts . method as any ,
24
24
data : opts . body ,
25
- revalidate : 5 ,
25
+ // Server side requests are cached a little more aggressively than client
26
+ // side hydration requests. The downside of this is a user may see a flash
27
+ // of stale data as the server render loads which will be replaced by the
28
+ // client side hydration by SWR. However, the second call will most likely
29
+ // be a 304 if it has been loaded before by the same user already. So, in a
30
+ // best case, we get a single database read, worst case we get two. The
31
+ // revalidation period is set to one minute in order to cut down on the
32
+ // flashes of stale data. However, in reality this doesn't really gain much
33
+ // as a user landing for the first time will still trigger two DB reads,
34
+ // and a user returning is quite likely someone who has interacted with a
35
+ // piece of content and thus will result in a new read at least once. So,
36
+ // it's not the most efficient approach (ignoring server-side data cache)
37
+ // but it's the best of a not-so-great situation. This should improve a lot
38
+ // if Next.js adds support for HTTP Conditional Requests and ETag headers.
39
+ revalidate : 60 ,
40
+ cache : "force-cache" ,
26
41
} ) ;
27
42
28
43
req . headers . set ( "Cookie" , await getCookieHeader ( ) ) ;
You can’t perform that action at this time.
0 commit comments