Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalidation strategy #1

Open
ChrisBAshton opened this issue May 28, 2019 · 3 comments
Open

Invalidation strategy #1

ChrisBAshton opened this issue May 28, 2019 · 3 comments

Comments

@ChrisBAshton
Copy link
Owner

We need a way for the server to tell what has been cached on the client, and not just whether something is cached.

Currently, if you update the CSS for your site, there's no easy way to make sure your visitors' InlineCacher localStorage is cleared. We need to know when to call InlineCacher.reset() and send the latest inline styles.

There are a few approaches we could take:

  1. Setting the cookie value as an expiration date on the cache (e.g. inline-cacher="1559076458")and invalidating if too old.
  2. Setting the cookie value as a hash of the cached CSS (e.g. inline-cacher="abc123def456") and invalidating if different to what's on the server.
  3. Setting a data attribute on the style tag (<style data-version="v1.2.3>) and setting the cookie value to this (e.g. inline-cacher="v1.2.3"), invalidating if too old.

I'm keen to get this right from the beginning to avoid setting up any technical debt.

@ChrisBAshton
Copy link
Owner Author

Thinking about it, I can leave the implementation up to the developer. It should simply be a parameter when calling InlineCacher, e.g.

new InlineCacher({
  cachebust: "foo", 
});

On the server:

if (cookie['inline-cacher'] === 'foo') {
  // whatever
  // maybe 'foo' is a hash and we can compare the hash of our latest styles.
  // maybe 'foo' is an expiration date and we can check the time.
}

It's up to the developer to use the value of cachebust however they wish.

This does, however, assume only one block of inline css. It provides a hook for the server to clear the inline-cache if needed, but it doesn't answer the following two scenarios:

  1. different inline CSS blocks in one page
  2. different inline CSS blocks across multiple pages

Ideally these should all be both independently cacheable and independently cache-bustable.

@ChrisBAshton
Copy link
Owner Author

Think the inline-cacher cookie should store an array of identifiers - again, the actual implementation of the identifier would be up to the developer. For example, it might be a hash of the CSS contents, or it might be based on the URL slug or something.

Each identifier could be associated with the time it was set. We would serialise this as JSON. That way the identifier doesn't have to be a hash, it can be an id, and we would look at the time it was set to figure out if we should invalidate the CSS and send a new block down.

Every request the browser sends would contain the serialised cookie, which would look something like inline-cacher="{ abc123: 1574166358, def456: 1574166358, ghi789: 1574166358 }". Then you would JSON parse the cookie and decide whether the CSS should be pushed down from the server or not. Again, the actual implementation would be left up to the developer.

Example implementation

HTML:

<script src="inline-cacher.min.js"></script>
<style data-inline-cacher="abc123">
  foo { ... }
  bar { ... }
</style>

Server requests:

// pseudocode
$inlineCacher = JSON.parse($_COOKIE["inline-cacher"]) || {};
if ($inlineCacher['abc123'] && $inlineCacher['abc123'] < (new Date() - 1000)) {
  echo '<style data-inline-cacher="abc123" data-serve-from-cache="true"></style>';
}
else {
  echo '<style data-inline-cacher="abc123" >' + $inlineStylesGoHere + '</style>';
}

Note that the inline-cacher.js script would need to be loaded ASAP in case it needs to serve any cached CSS, otherwise the perceived performance would be awful. But the script will be doing so little in reality, it should be small. Ironically we'll need to think about caching vs inlining the script itself.

@ChrisBAshton
Copy link
Owner Author

Had a further think about this today. Think of it as "inline by default". If the server detects a cookie which suggests it is cached already, then switch to the external approach (<link rel="stylesheet" data-inline-cache="abc123" href="..." />).

Ideally we should have some service worker which intercepts any external requests to that href and lifts it from cache/localStorage instead.

This approach:

  1. retains the ordering (as someone could have another stylesheet that isn't inline-cacheable, and the cascade could cause issues with specificity if we're arbitrarily injecting all cached styles in the <head>, say.
  2. could work with JS too, as a result
  3. is a progressive enhancement (if the cookie, or localStorage, get deleted, it will fall back to a HTTP request)

So biggest challenge atm is a) how to create that web worker to do all that in a timely fashion and b) how to initialise all that (probably have to inline the inline-cacher script in the HEAD)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant