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

Add a method to cache the URLs of all open clients #368

Closed
philipwalton opened this issue Mar 15, 2017 · 4 comments
Closed

Add a method to cache the URLs of all open clients #368

philipwalton opened this issue Mar 15, 2017 · 4 comments

Comments

@philipwalton
Copy link
Member

Library Affected:
sw-lib

Issue or Feature Request Description:
Add a method to cache the URLs of all open clients

This allows a dev to ensure a site can run offline after the first pageload without having to wait for a subsequent pageload.

Note: we'll probably want to make sure we use the includeUncontrolled option

@jeffposnick
Copy link
Contributor

I'm going to bump down this priority, since it's new functionality that would be nice to have, but not needed for parity with our legacy offerings.

@jeffposnick
Copy link
Contributor

jeffposnick commented Sep 5, 2017

Quick hack for how this might work. It would be code that run in the context of window, and could look like:

async function populateCache(cacheName) {
  const urls = performance.getEntriesByType('resource').map(resource => resource.name);
  const cache = await caches.open(cacheName);
  return Promise.all(urls.map(async url => {
    // Explicitly check to see if the URL is present in any cache, not just in cacheName.
    // Otherwise, we'd end up double-caching URLs that are managed via precaching.
    const alreadyCached = await caches.match(url);
    if (!alreadyCached) {
      try {
        await cache.add(url);
      } catch (error) {
        // Super-hacky.
        try {
          const response = await fetch(new Request(url, {mode: 'no-cors'}));
          await cache.put(url, response);
        } catch (anotherError) {
          console.info(anotherError);
        }
      }
    }
  }));
}

Problems with this strawman approach:

  • We should provide some way of filtering what gets cached via a whitelist, blacklist, or both.
  • Running this code unconditionally on every page load is a waste, so maybe we should take care of running it inside of a navigator.serviceWorker.oncontrollerchange event listener. But then we might run into issues if our code isn't loaded until after the service worker has been installed, and the controllerchange event has already been fired.
  • I don't think we can determine from the underlying Performance API whether a cross-origin resource was loaded with CORS or is opaque, so we might be stuck trying CORS first, and then falling back to no-cors if that fails. Using no-cors unconditionally is another option, but that would end up causing issues for resources that can't be used by the page when they're opaque, and it's also riskier, since you might end up caching error responses.

@jeffposnick
Copy link
Contributor

Related discussion in the service worker specification: w3c/ServiceWorker#1282

@jeffposnick
Copy link
Contributor

This is now doable in v4 via a recipe that uses workbox-window. @philipwalton will be publishing a corresponding guide.

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

4 participants