The web API fetch
is superbly simple (compared to its predecessor: XMLHttpRequest
) but during development there's always a few concerns I have when making fetch requests: hitting 3rd party request limits, latency (since I want dev to be rapid) and the potential of going offline (aka: developing on trains).
Since the browser is a beautiful thing, I'm able to wrap the fetch
API with my own custom logic and circumvent those concerns, so I introduce to you: memfetch
UK EVENTAttend ffconf.org 2024
The conference for people who are passionate about the web. 8 amazing speakers with real human interaction and content you can't just read in a blog post or watch on a tiktok!
£249+VAT - reserve your place today
What it does
Memfetch will, unobtrusively, wrap the fetch API, and cache any request and response so that if you have the exact same request again, it'll be served from local browser cache.
Importantly, there's no change to my code to make use of the cached version of the requests. This aspect is an important feature to me, because I see memfetch as a development tool that I should be able to remove without having to refactor code before production.
How to use it
Again, no changes to my JavaScript fetch requests, only to include the memfetch library before my code runs:
<script src="https://unpkg.com/memfetch"></script>
Now all fetch requests will be cached, and subsequent requests will be served directly from the local browser's storage. Importantly, the requests are fingerprinted using the url and the init options passed to the fetch
. This means if there's an additional option passed to your request (such as adding mode: 'cors'
), memfetch will treat this as distinct.
Again, all fetch requests are cached, which includes POST
requests. I suspect in future I'll have some kind of include
/exclude
configuration if there's demand for it.
To clear the local cache, there's a seed
property on the fetch
method, if it's set to a value that's different to the current value (i.e. changed from undefined
to a
or from a
to b
), the local cache will be completely erased:
Under the hood
Originally this library would wrap the fetch
API and return a new Proxy
that would allow memfetch capture that the code used the .json
method, or the .blob
method - but it turned out I could simplify the code and drop the use of proxies (as cool as they are).
The original fetch
method is stored in an internal method and replaced with a wrapper.
When you code makes a request, the following are stored in IndexedDB (thanks to Jake Archibald's micro idb-keyval library):
- url
- fetch options
- response headers
- status
- statusText
- blob
Using these values, memfetch constructs a new Response
and returns that instead of the original response.
Subsequent requests check if there's a cached value, and using the captured data points (above), it resolved with another new Response
- this way the authored code can call .blob
or .json
or any other method implemented by the Response API (which meant memfetch didn't need to use a proxy object).