Skip to content

Instantly share code, notes, and snippets.

@ashleymichal
Last active October 4, 2019 21:47
Show Gist options
  • Save ashleymichal/f636aa770cee184f8a87f36b194ae6d6 to your computer and use it in GitHub Desktop.
Save ashleymichal/f636aa770cee184f8a87f36b194ae6d6 to your computer and use it in GitHub Desktop.
how i would explain sites caching to the me of three months ago

Explaining Workers Sites Caching to a General Audience

0. Preface

This builds from most familiar to least familiar, most general to most specific. Section one will be review for most people. Section two will be review for some. etc.

1. what happens when you visit a website

When I point my browser at ashleymichal.github.io, the server returns an HTML file. As my browser parses it, it encounters references to other resources: stylesheets, scripts, images, etc. It makes new requests for each resource, and integrates the responses until the page is rendered.

[Show simple example of an html page with a stylesheet, script reference, and image; show the multiple requests to the server, perhaps in a devtools image.]

So, for this simple example, the browser makes five separate requests to the server: an initial request for the html document, then subsequent requests for its stylesheet, javascript, and an image. How long each request takes depends on the physical distance between my browser and the origin server, and the strength of my connection.

2. How browser caching reduces load time

To reduce calls to the origin, the server can tell the client to store, or cache, the response for a certain amount of time. The server can’t notify all the clients that have downloaded an asset that it has changed, so it relies on these instructions to tell the browser what to cache and for how long. Think of the relative difficulty of distributing a software patch for a native application vs. fixing a bug in a web app. This tension, between the desire to always provide up to date resources, and to reduce calls to the origin, is why caching is often referred to as “the hardest problem in computer science”. We are going to focus on one solution employed by the framework create-react-app (and others, probably).

3. How static site generators optimize for this

During the build step, create react app renames as many assets as possible with a “fingerprinted” version of the filename:

[illustrate this using the file tree vs. the asset manifest image from the blog post].

It then generates an asset manifest: a key value mapping between the asset referenced in the app, and the actual file stored on the server with the fingerprinted filename. Now, when the browser requests mycoolreactapp.com, it downloads the react app and the asset manifest. The app uses the manifest to request resources using the fingerprinted url, and the browser can cache those assets under those unique keys indefinitely, because when a resource changes, the change is reflected in the asset manifest, and so when the app goes looking for it, it’s a cache miss, and it makes a request to the server for the new asset.

[show another network devtool screenshot with cache hits/misses and the fingerprint]

This is called “cache busting”, and works brilliantly on most, but not all file types.

4. The limitations of this approach

Remember the first request the browser makes is just to mycoolreactapp.com; it is only by convention that the server knows to return the asset at index.html. Logistically, this address cannot change. It would be like moving house every time you changed your curtains: guests, the mailman, etc, could never find you, all because of one silly state change. Similarly, it’s not super smart to cache the asset manifest used by create react app, since it acts as the source of truth for the most up to date version of the app.

5. The Edge

Cloudflare’s network is a distributed system of servers that sit between our customers’ origin servers, and the clients that want to visit them. When a browser makes a request to an origin behind Cloudflare, it is routed first through a data center closer to the user. This is handy for lots of things: DOS protection, bot mitigation, etc., but a basic use for a network like this is a CDN, or a content distribution network. CDNs work as intermediary caches; rather than every browser reaching all the way back to the origin for an asset, the first request to an edge data center “warms” the cache; that is, the data center server makes a request, caches the response, and serves it to the client. Subsequent requests can then be served from this cache, allowing many browsers to benefit from caching. This mitigates latency on most requests, but still suffers the same issue as the browser cache: an edge POP knows nothing of the state of the server it sits in front of, and therefore can’t tell any better than the browser when, say, the root html for your site has updated, so cache control headers stay generally the same in this case, and by default these caches do not cache html documents.

[use the classic diagram of the eyeball, edge network, and origin for this section]

6. Workers Sites

With a Worker, however, we have more options. With Workers, we can manipulate the cache on the edge ourselves. We can also build our own version of an asset manifest

[show a second example, this time with every file hashed]

This is not served to the browser, but instead generated when you run publish, and deployed alongside the Worker we use to serve your assets out of KV. This allows us to actually map an expected path (the way it looks on your local machine) to a key fingerprinted by Wrangler at deploy time. This is edge cache-busting, and it’s super exciting, because everything that you cannot cache indefinitely in the browser can instead be cached indefinitely on the edge, reducing the number of requests to the origin even further, especially during periods of high load. And since your “origin” is actually KV, this acts as a completely serverless implementation of static site hosting. ✨

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment