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

allow service worker produced resources to be marked as "cachable" #962

Open
wanderview opened this issue Aug 25, 2016 · 19 comments
Open

allow service worker produced resources to be marked as "cachable" #962

wanderview opened this issue Aug 25, 2016 · 19 comments

Comments

@wanderview
Copy link
Member

The main cache people think about in the browser is the http cache. Service worker sits on top of the http cache and all SW invoked fetch() calls go through it. This is well and good.

There are, however, additional caches within a browser. For example, both images and stylesheets have some form of memory caching spec'd within a document. These sit above the network and service worker layers.

It might be nice to provide a way for a service worker to indicate a particular Response won't change as long as the SW is in control. For example, a pre-cached asset. This would allow the browser to keep these assets in higher level memory caches. They could then be re-used without paying the cost of firing a FetchEvent or pulling the resource out of Cache API. These assets would have to be invalidated from the memory caches if the service worker became redundant (e.g. updates, unregister, etc).

You can see how effective these caches can be in #756 (comment). The benchmark loads from image cache anywhere from 35ms to 150ms. This is in comparison to the 300+ms required using a caching service worker.

@wanderview wanderview added this to the Version 2 milestone Aug 25, 2016
@NekR
Copy link

NekR commented Aug 25, 2016

I'm also pretty sure Chromium has similar caches for JS (parsed/compiled)
which were disabled for SW. Not sure if still disabled, but I saw an issue
about it some day.

@NekR
Copy link

NekR commented Aug 25, 2016

@jakearchibald
Copy link
Contributor

@wanderview I've been thinking about this in terms of link[rel=preload], added some thoughts to whatwg/fetch#354

@marcoscaceres
Copy link
Member

I don't know if it helps... but I got bit by this once. The image cache in Gecko was serving images to a page even after that image was yanked from the cache API. I think we "fixed" this in gecko:
https://bugzilla.mozilla.org/show_bug.cgi?id=1206298

@delapuente
Copy link

Me too. I was implementing a load balancer fetching a picture identified by some URL but transparently served from different servers and I was not able to get the proper response from other browser due to the img cache.

@jakearchibald
Copy link
Contributor

@marcoscaceres @delapuente

The image cache in Gecko was serving images to a page even after that image was yanked from the cache API

Gecko's behaviour seems correct as per spec. The additional cache for images is consulted before fetch is called. So if there's a match in the image memory cache, the service worker isn't triggered.

@wanderview
Copy link
Member Author

Gecko's behaviour seems correct as per spec. The additional cache for images is consulted before fetch is called. So if there's a match in the image memory cache, the service worker isn't triggered.

This should happen within a page, but I think @marcoscaceres was running into a previous bug where we did it for new pages too. I've been told our image cache has some bugs compared to the spec, but I've been too scared to look at it further.

@wanderview
Copy link
Member Author

FWIW, it seems chrome does not consult the service worker on stylesheets in its memory cache. If you run this in chrome 54:

https://github.com/samertm/firefox-sw-perf

You can see that navigating to the same page again within the same process does not fire FetchEvent's to the service worker for style sheets. Instead the style sheets are served from a higher level memory cache.

@samertm
Copy link

samertm commented Dec 1, 2016

Using the firefox-sw-perf repo, you can verify that Chrome skips the service worker for existing tabs (but not when you create a new tab) when caching headers are set correctly by replacing the event listener in sw.js with this:

var sum = 0;
self.addEventListener("fetch", function(event) {
  console.log(sum);
  for (var i = 0; i < 10000000; i++) {
    sum++;
  }
  return;
});

For refreshes and ctrl+l, enter, only one sum is printed after loading the page. For new tabs, the sum is printed for every resource.

@wanderview
Copy link
Member Author

So I guess the question is, is this behavior ok? Should we just let upstream stuff cache per the cache-control header, etc? Or is there some expectation from devs that if a service worker is present they will get a FetchEvent since the SW can change the resource irrespective of the headers?

@jakearchibald
Copy link
Contributor

If there's a matching response found in the list of available images or whatever link[rel=preload] uses, I wouldn't expect to get a fetch event.

However, the above caches are tied to the current document. Chrome's skipping the CSS request between documents, and that does seem odd. My gut feeling is there should be a fetch event here, and whatever cache Chrome is using here should sit behind the service worker.

@wanderview
Copy link
Member Author

However, the above caches are tied to the current document. Chrome's skipping the CSS request between documents, and that does seem odd. My gut feeling is there should be a fetch event here, and whatever cache Chrome is using here should sit behind the service worker.

So we do actually re-use our image cache across documents, but we explicitly disable that when service workers are in play.

It would be nice to support these things, but perhaps the service worker shoudl explictly opt in to it? Or is the cache-control header enough?

Lets discuss at the face-to-face in april

@annevk
Copy link
Member

annevk commented Mar 3, 2017

FWIW, I think the first thing that needs to happen here is having a more concrete description of what each browser does. In particular Chrome/WebKit's cache that they also use for preloading. Then we can try to standardize something around that, then we can start thinking about exposing it.

@wanderview
Copy link
Member Author

FWIW, I think the first thing that needs to happen here is having a more concrete description of what each browser does. In particular Chrome/WebKit's cache that they also use for preloading. Then we can try to standardize something around that, then we can start thinking about exposing it.

You mean their renderer process network memory cache?

There are other caches as well, like stylesheet caches (compiled and pre-compiled).

@annevk
Copy link
Member

annevk commented Mar 3, 2017

I think that's the one I mean, yes. Others might be good to have documented too, depending on how visible they are and whether we need to expose them somehow.

And if the image cache is impacted when service workers are in play we should probably change the HTML standard somehow (it defines that cache, though somewhat badly).

@wanderview
Copy link
Member Author

Yea, I know we had to fix the firefox image cache at one point to hit the service worker in cases it would have used the cached image before.

@jakearchibald
Copy link
Contributor

I wouldn't expect the presence of a service worker to change how the image cache works (as spec'd), or are you talking about something more Firefox specific?

@wanderview
Copy link
Member Author

I wouldn't expect the presence of a service worker to change how the image cache works (as spec'd), or are you talking about something more Firefox specific?

My spec knowledge of image cache is rather weak. But we can test the following:

Compare these steps in chrome and firefox:

  1. Load https://jakearchibald.github.io/service-worker-benchmark/
  2. Navigate to http://example.com in the same tab (so process is re-used)
  3. Paste https://jakearchibald.github.io/service-worker-benchmark/ in tab URL bar again

In the no service worker installed case step (3) gets:

Chrome: 545ms
Firefox: 174ms

In the empty fetch SW case step (3) gets:

Chrome: 570ms
Firefox: 835ms

Firefox is doing some image caching within the process on navigation, but only if SW is not installed.

@jakearchibald
Copy link
Contributor

F2F:

  • General idea about an opt-in/out for using non-standard memory caches (like CSS)
  • Servers can observe these memory caches, maybe it's fine for the service worker to observe them too
  • We need to review https://bugzilla.mozilla.org/show_bug.cgi?id=1206298 and see if this "breakage" was reasonable

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

No branches or pull requests

7 participants