diff --git a/components/nav.js b/components/nav.js index b6b4f28..8590c1a 100644 --- a/components/nav.js +++ b/components/nav.js @@ -37,8 +37,8 @@ export default function Nav() {
+ The following guides contain information about bestfetch that most users + of the library do not need to know to use the library successfully. + However, for certain situations they may help you use the library more + effectively. +
+
+ Sometimes, servers experience problems that prevent them from returning
+ the data that you request. Instead, you might get a response that tells
+ you that the server is down. For RESTful APIs, an{' '}
+
+ HTTP response status code
+ {' '}
+ that's >=500
indicates that the server had an error when
+ processing the request.
+
+ For most apps, it's best to avoid caching error responses, as the + server may be up by the time the request is made again. +
++ + Note: for apps with many concurrent users, you may want to slow down + how often you make requests to a server that is having issues to avoid + worsening the situation. This library's opinion is that this limiting + requests to the server should be handled independently from the cache. + +
+
+ For this reason, bestfetch
will not cache responses that
+ have an HTTP status code >=500
. This will override{' '}
+ whatever your cachePolicy
is set as.
+
+ A response that will be added to the cache is called a{' '} + cacheable response. If the default definition of a cacheable + response does not work for your application, then you can define it + yourself. +
+
+ Use responseCache.defineCacheableResponse
to define what a
+ cacheable response is. You should only call this method one time: when
+ your app first loads.
+
+ To get started, import the responseCache
object:
+
+ responseCache.defineCacheableResponse()
accepts a single
+ argument: a function.
+
+ When you specify a cachePolicy
that allows for responses to
+ be written to the cache, then the function that you pass into{' '}
+ defineCacheableResponse
will be called once the response is
+ received. The function is passed the response
object, and
+ if it returns true
then the response
will be
+ added to the cache.
+
Here's what it looks like to define a cacheable response:
+The default cacheable response definition is:
++ If you do not wish to exclude any kinds of responses from the + cache, then you can use the following definition: +
++ Every server can have problems, though, so be mindful of how this + library will behave when you use this definition. +
+response.data
+
+ Not every API uses HTTP status codes. For instance, some enterprise APIs
+ will not return correct response status codes, and their endpoints may
+ return 200 OK
even when the server has an internal error.
+ In situations like these, you may wish to look at{' '}
+ response.data
to see what's in the body
of the
+ response.
+
+ In the following example, bestfetch won't cache responses if the value
+ of response.data.error
is the string{' '}
+ "Server error"
.
+
saveToCache
+
+ : A boolean
that determines whether or not the
+ response will be saved to the cache. Defaults to true
+ .{' '}
+
+ Learn more here
+
+ .
+ cachePolicy
: Determines how the cache will be used, if at all. Defaults to{' '}
"cache-first"
. Valid values are{' '}
- "cache-first"
, "network-only"
, and{' '}
- "cache-only"
.{' '}
+ "cache-first"
, "reload"
,{' '}
+ "cache-only"
and "no-cache"
.{' '}
Learn more here
@@ -71,7 +83,7 @@ export default function bestfetch() {
"json"
. Valid values are "json"
,{' '}
"text"
, "formData"
, "blob"
,
and "arrayBuffer"
.{' '}
-
+
Learn more here
.
diff --git a/pages/api-reference/active-requests.js b/pages/api-reference/duplicate-requests.js
similarity index 67%
rename from pages/api-reference/active-requests.js
rename to pages/api-reference/duplicate-requests.js
index e2ede83..60f0453 100644
--- a/pages/api-reference/active-requests.js
+++ b/pages/api-reference/duplicate-requests.js
@@ -4,20 +4,20 @@ export default () => {
return (
activeRequests
+ duplicateRequests
An object for managing the active requests.
+An object for managing deduplicated requests.
- activeRequests
has two methods:
+ duplicateRequests
has two methods:
clear
+ Removes tracking on all in-flight requests. Be warned: all in-flight
+ requests with dedupe: true
will never resolve if this
+ method is called.
+
- Removes tracking on all in-flight requests. In-flight requests are{' '} - not cancelled: calling this method only ensures that subsequent - identical requests are not deduped. + We strongly recommend against using this method in your app. You + have been warned!
This method does not accept any arguments.
@@ -79,7 +87,7 @@ export default () => {set
+ has
has
+ isFresh
+
+
+ set
purge
+
+
+ defineStaleness
+
+
+ useCachedResponse
+ defineCacheableResponse
get
- Retrieve the cached response for a given requestKey
.
+ Retrieve the cached response for a given requestKey
. This
+ method only returns fresh values, unless you specify the{' '}
+ includeStale
option as true
.
+
+
+ Note: calling responseCache.get()
will not increment a{' '}
+ cacheObject
's accessCount
.
+
options
+
+ : An object that configure the behavior of get
. At the
+ moment, only one option is supported: includeStale
. Pass{' '}
+ true
and this method will also return stale values from
+ the cache.
+
@@ -88,14 +126,17 @@ export default () => {
set
+ has
- Set the cached response
for a particular{' '}
- requestKey
.
+ Used to determine if a response exists in the cache for{' '}
+ requestKey
. This method only returns fresh values, unless
+ you specify the includeStale
option as true
.
requestKey
- : The request key of the request.
+ : The requestKey
to check.
response
+ options
- : The response to associate with the requestKey
.
+ : An object that configure the behavior of get
. At the
+ moment, only one option is supported: includeStale
. Pass{' '}
+ true
and this method will also return stale values from
+ the cache.
- The responseCache
object.
+ A boolean
representing whether or not a response exists in
+ the cache for requestKey
.
has
+ isFresh
- Used to determine if a response exists in the cache for{' '} + Call this to determine if a request has a fresh response in the cache. +
+requestKey
+
+ : The request key of the response to check.
+
+ A boolean
representing whether the request associated with{' '}
+ requestKey
is fresh or not. Returns true
if a
+ response exists in the cache, and it is fresh; false
is
+ returned otherwise.
+
set
+
+ Set the cached response
for a particular{' '}
requestKey
.
requestKey
- : The requestKey
to check.
+ : The request key of the request.
+
+ response
+
+ : The response to associate with the requestKey
.
- A boolean
representing whether or not a response exists in
- the cache for requestKey
.
+ The responseCache
object.
delete
@@ -176,33 +256,46 @@ export default () => {
inline={false}
value={`responseCache.delete('my-request-key');`}
/>
+ purge
+ Removes all stale values from the cache.
+This method does not accept any arguments.
+This method does not return anything.
+clear
Removes all responses from the cache.
++ Removes all responses from the cache (both fresh and stale). +
This method does not accept any arguments.
This method does not return anything.
useCachedResponse
+ defineStaleness
- Configure the invalidation strategy for your application. You should + Use this method to define when a cached response goes stale. You should only call this method one time, when your app first loads.
cacheInvalidationPolicy
+ stalenessDefinition
- : A function that defines your invalidation policy. Each time that the
- cache would be hit, this function will be called. It is passed a
- single argument: cacheObject
. Return true
to
- use the cached object, or false
to invalidate it.
+ : A function that determines whether or not a cached response is
+ stale. Each time that a response would be pulled from the cache, this
+ function will be called. It is passed a single argument:{' '}
+ cacheObject
. Return true
to mark the
+ response as stale, or false
to mark it fresh.
@@ -236,16 +329,62 @@ export default () => { // * 10 = 10 minutes const TEN_MINUTES = 1000 * 60 * 10; -responseCache.useCachedResponse(cacheObject => { +responseCache.defineStaleness((cacheObject) => { const currentTimestamp = Date.now(); - return currentTimestamp - cacheObject.createdAt <= TEN_MINUTES; + return currentTimestamp - cacheObject.createdAt > TEN_MINUTES; +});`} + /> +
+ For more on how to use this method, refer to the{' '} + + Cash Freshness + {' '} + guide. +
+ +defineCacheableResponse
+
+ Not every response goes into the cache, even if you specify a{' '}
+ "cache-policy"
that indicates that it would. A response
+ that is allowed to be cached is called "cacheable." By default, every
+ response is cacheable unless it responds with an HTTP status code that's{' '}
+ >= 500
.
+
+ Use this method to write your own definition of a cacheable response. +
+cacheableDefinition
+
+ : A function that determines whether or not a response is cacheable.
+ Each time that a response would be added to the cache, this function
+ will be called. It is passed a single argument: response
.
+ Return true
to save the cached response, or{' '}
+ false
to discard it.
+ This method does not return anything.
++ Refer to the{' '} + + Managing Server Errors + {' '} + guide to learn more about this method. +
); }; diff --git a/pages/guides/faq.js b/pages/faq.js similarity index 68% rename from pages/guides/faq.js rename to pages/faq.js index 649546e..1f481cd 100644 --- a/pages/guides/faq.js +++ b/pages/faq.js @@ -1,10 +1,12 @@ +import Link from '../components/link'; + export default function FAQ() { return (res.data
set to null
, why is that?
-
If the response cannot be parsed as the responseType
, then{' '}
res.data
will be null
.
@@ -23,14 +25,18 @@ export default function FAQ() {
- To resolve this, you can use the responseType
option to
- have greater control over the parsing of the response body from the
- server.
+ To resolve this, you can{' '}
+
+
+ use the responseType
option
+
+ {' '}
+ to have greater control over parsing the response body.
responseType
even an option?
-
This option exists because of the inner workings of the{' '}
fetch
API.
@@ -58,6 +64,21 @@ export default function FAQ() {
be thrown. To get around this problem, bestfetch reads the body for you
– one time – and passes that result to each consumer.
+ Cache freshness is a difficult problem, and each application has its own + particular needs. It would be impossible for this library to include a + default definition of staleness and expect it to work for every use case + in every app. +
++ You're able to change this behavior so that responses do go stale. Learn + more in the{' '} + + Cache Freshness + {' '} + guide. +
.json()
you're reading the response body from
the server and parsing it as JSON. When you use bestfetch, the request
body is read and parsed as JSON automatically for you (although this{' '}
-
+
can be configured
).
diff --git a/pages/guides/cache-freshness.js b/pages/guides/cache-freshness.js
new file mode 100644
index 0000000..118e241
--- /dev/null
+++ b/pages/guides/cache-freshness.js
@@ -0,0 +1,181 @@
+import Lowlight from 'react-lowlight';
+
+export default () => {
+ return (
+ + The cache will only return responses that are fresh. Out of the + box, responses that are added to the cache stay fresh indefinitely. + However, you can and often should configure this differently for your + application. +
++ For example, you may wish to specify that responses should only remain + fresh for a certain period of time, such as 10 minutes. This guide will + explain how you can configure when responses go stale for your app. +
+ +
+ Use the responseCache.defineStaleness()
method to specify
+ when responses go stale. You only need to call this method a single
+ time; typically before you start your application.
+
+ To get started, import the responseCache
object:
+
+ responseCache.defineStaleness()
accepts a single argument:
+ a function.
+
+ It works like this: each time that a request is made that has a cached
+ response, the function that you pass into defineStaleness
{' '}
+ will be called with a single argument: a cacheObject
{' '}
+ (described below). Return true
if the value is stale, or{' '}
+ false
if it is false.
+
+ To put this another way, the freshness of a response in the cache is + determined lazily. +
+Here's what it looks like to specify a definition for staleness:
+The default definition of staleness is:
++ which means that any response that is added to the cache is never{' '} + stale – they remain fresh indefinitely. +
+cacheObject
+
+ The function that you pass to defineStaleness
will be
+ passed a single argument: cacheObject
. You can use this
+ object to decide whether or not to use the cached reponse or not.
+
+ A cacheObject
has the following shape:
+
createdAt
: A timestamp (in milliseconds) when the
+ response was added to the cache.
+ lastAccessedAt
: A timecode (in milliseconds) when this
+ response was last read from the cache.
+ accessCount
: How many times the response has been read
+ from the cache.
+ res
: The cached response.
+ + The simplest example is to define a strategy that considers every + response as stale. +
++ With this definition, every response is immediately stale, so nothing + will ever be returned from the cache when making requests. This isn't + particularly useful, so let's look at more realistic examples. +
+In the following example, responses go stale after 10 minutes.
++ In the following example, responses go stale once they have been used + for 10 requests. +
++ Deleting a stale value from the cache is called eviction. When a + request is made, and its cached response is determined to be stale, that + response is immediately evicted from the cache. +
+
+ Because staleness is determined lazily, the size of your cache will grow
+ over time. You can manually evict all stale responses from the cache by
+ calling responseCache.purge()
.
+
+ Not every application needs to worry about the cache growing so large + that it causes problems. But if your application runs for a long time, + and a typical user makes a lot of different kinds of requests, then you + may need to call this method periodically. +
+The following example demonstrates purging the cache every hour:
++ You don't have to purge the cache at a set interval. For example, you + could configure your app to purge the cache if the user is idle for more + than 15 minutes. +
+
Use the cachePolicy
option when calling{' '}
- bestfetch()
to control when the cache is used. Supported
- values are:
+ bestfetch()
to configure the behavior of the cache.
+ Supported values are:
"cache-first"
: The cache is checked to see if a response
already exists for the request. If a response is found, then it will
be returned, and no network request will be made. If no response
- exists in the cache, then a network request will be made.
+ exists in the cache, then a network request will be made and the
+ response will be saved to the cache.
"network-only"
: The cache is ignored, and a network
- request is always made.
+ "reload"
: A network request is always made (even if there
+ is a response in the cache). The response is saved to the cache.
"cache-only"
: If a response exists in the cache, then it
@@ -31,17 +32,21 @@ export default function CachingResponses() {
CacheMissError
- .
+ . A network request is never made when using this option.
+ "no-cache"
: The cache is ignored completely. A network
+ request is always made, and the response is not saved to the cache.
- The following example shows how to specify the{' '}
- "network-only"
option:
+ The following example shows making a request with a{' '}
+ cachePolicy
set to "reload"
:
POST
"network-only"
+ "no-cache"
PUT
"network-only"
+ "no-cache"
PATCH
"network-only"
+ "no-cache"
DELETE
"network-only"
+ "no-cache"
The default value for less commonly used methods is:
@@ -123,15 +128,18 @@ export default function CachingResponses() { retrieving data instead ofGET
.
- - Responses that are added to the cache are never invalidated - unless you configure how you would like for them to be invalidated. For - more, refer to the guide on{' '} - - invalidating cached responses - - . + The cache only returns responses that are fresh. By default, + every request that is added to the cache remains fresh indefinitely, but + you can configure this. +
++ Refer to the{' '} + + Cache Freshness + {' '} + guide to learn how.
@@ -145,10 +153,15 @@ export default function CachingResponses() { .
-+ This system of caching is able to work because this library has an + algorithm to determine when two requests are considered identical + . For nearly all apps, this algorithm works fine, and you do not need to + understand how it works. +
- To learn more about how this algorithm works, and also how you can - change its behavior, check out the{' '} + However, if you are interested in understanding it, check out the{' '} Identical Requests {' '} diff --git a/pages/guides/index.js b/pages/guides/index.js index 5fe993a..3ebfc0a 100644 --- a/pages/guides/index.js +++ b/pages/guides/index.js @@ -19,8 +19,8 @@ export default function Guides() {
- Out of the box, bestfech will never invalidate your cached responses. - What this means is that a particular request will only ever hit the - server once, unless you configure bestfetch to behave - differently. -
-- The reason this library works this way is because cache invalidation is - a difficult problem, and each application has its own particular needs. - It would be impossible for this library to include a default - invalidation strategy and expect it to work for every use case in every - app. -
-
- You can configure an invalidation strategy that works for your
- application using the responseCache.useCachedResponse()
{' '}
- method.
-
- You only need to call this method a single time; typically before you - start your application. -
-
- To get started, import the responseCache
object:
-
- responseCache.useCachedResponse()
accepts a single
- argument: a function.
-
- It works like this: each time that a request is made that has a cached
- entry, the function that you pass will be called with a single argument:
- a cacheObject
(described below). Return true
{' '}
- from the function to use the cached response, or false
to
- immediately invalidate it.
-
cacheObject
-
- The function that you pass to useCachedResponse
will be
- passed a single argument: cacheObject
. You can use this
- object to decide whether or not to use the cached reponse or not.
-
- A cacheObject
has the following shape:
-
createdAt
: A timestamp (in milliseconds) when the
- response was added to the cache.
- lastAccessedAt
: A timecode (in milliseconds) when this
- response was last read from the cache.
- accessCount
: How many times the response has been read
- from the cache.
- res
: The cached response.
- - The simplest example is to define a strategy that rejects every{' '} - cached entry. -
-- With this invalidation strategy in place, it is as if this library - doesn't cache any responses at all. This isn't particularly useful, so - let's look at more realistic examples. -
-- In the following example, we reject cached responses that are older than - 10 minutes. -
-- In the following example, we only allow a cached response to be used up - to 10 times. -
-
You can pass a URL as the first argument, or you can pass an{' '}
- options
object and specify the URL there. URLs can be both
- absolute or relative.
+ options
object and specify the URL there. URLs can be
+ either absolute or relative, although most of the time you'll want to
+ use absolute URLs.
+ bestfetch
automatically ensures that your application never
+ makes two identical network requests at the same time. Learn more in the{' '}
+
+ Deduplicating Requests
+ {' '}
+ guide.
+
bestfetch
supports all of the same options as{' '}
@@ -198,7 +208,7 @@ bestfetch(\`/api/books?\${qs}\`)
responseType
. Use this option when making requests to
endpoints that do not return JSON. Learn more{' '}
-
+
here
.
@@ -207,12 +217,43 @@ bestfetch(\`/api/books?\${qs}\`)
requestKey
. An advanced option that is used to determine
which requests are identical. You probably won't need this. Learn more
in the{' '}
-
- deduplication guide
-
- .
+
+ Identical Requests
+ {' '}
+ guide.
+ Use{' '}
+
+ AbortController
+ {' '}
+ to cancel requests.
+
+ If you're using bestfetch in an environment without{' '}
+ AbortController
, then we recommend{' '}
+
+ this polyfill
+
+ .
+
bestfetch
returns a Promise. This Promise resolves if a
diff --git a/pages/index.js b/pages/index.js
index 81a95ca..03f9bd9 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -45,12 +45,12 @@ export default function Index() {
<3kb
gzipped) you can feel responsible adding it
- to an existing codebase.
+ bestfetch is great for your users: many people worldwide browse
+ the web on mobile phones with limited data plans. Use less of
+ their data by leveraging bestfetch.
<3kb
gzipped) you can feel responsible adding it
+ to an existing codebase.