GoogleChrome / workbox

📦 Workbox: JavaScript libraries for Progressive Web Apps
https://developers.google.com/web/tools/workbox/
MIT License
12.36k stars 819 forks source link

Caching firebase storage images #1712

Closed bforrester722 closed 5 years ago

bforrester722 commented 6 years ago

Trying to figure out how to cache images from firebase storage to show them if offline. Any help will be appreciated.

firebase.json

"source": "**/*.@(jpg|jpeg|gif|png|webp)",
    "headers": [
      {
        "key": "Cache-Control",
        "value": "max-age=31536000"
      }
    ]
  }

webpack build config. Tried several things put here is latest

new WorkboxPlugin.GenerateSW({
  cacheId,
  clientsClaim:              true,
  skipWaiting:               false,
  navigateFallback:          'src/view404.js',
  navigateFallbackWhitelist: [/^(?!\/__)/], 
  runtimeCaching: [{
        urlPattern: new RegExp('^https://storage\.googleapis\.com/'),
        handler: 'staleWhileRevalidate',
        options: {
           cacheableResponse: {
              statuses: [0, 200]
           }
        }
  }]
}),

service-worker.js

self.__precacheManifest = [].concat(self.__precacheManifest || []);
workbox.precaching.suppressWarnings();
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});

workbox.routing.registerNavigationRoute("src/view404.js", {
whitelist: [/^(?!\/__)/],

workbox.routing.registerRoute(/^https:\/\/storage.googleapis.com\//, 
workbox.strategies.staleWhileRevalidate({ plugins: [new 
workbox.cacheableResponse.Plugin({"statuses":[0,200]})] }), 'GET');
jeffposnick commented 6 years ago

Can you provide a few sample URLs corresponding to the images that you want cached? I'm not sure whether the RegExp you're using is correct without knowing what those URLs are.

bforrester722 commented 6 years ago

Thank you for responding. Here is 2 urls from images I am trying to cache.

https://storage.googleapis.com/asg-cms-dev.appspot.com/cms%2Fui%2Fcarousels%2Fhome%2FSnow.jpeg?GoogleAccessId=asg-cms-dev%40appspot.gserviceaccount.com&Expires=16730323200&Signature="longString"

https://storage.googleapis.com/asg-cms-dev.appspot.com/cms%2Fui%2Fcarousels%2Fhome%2Fshop2.png?GoogleAccessId=asg-cms-dev%40appspot.gserviceaccount.com&Expires=16730323200&Signature="longString"

jeffposnick commented 6 years ago

Technically, you should have a double-\\ character in your RegExp string when escaping the ., like:

new RegExp('^https://storage\\.googleapis\\.com/')

In practice, that doesn't really matter, since the . wildcard will match a literal '.' character.

So as far as I can tell, your runtime caching should match those image URLs.

Are you seeing anything saved in the runtime cache at all? What happens if you test in an Incognito window to ensure that there wasn't an earlier service worker that is still active?

If you could, test this on localhost with the JS console open, as workbox-routing will log information about each outgoing request by default, and that might offer some hints.

(That navigateFallback: 'src/view404.js', looks like it might be incorrect; navigateFallback is intended for App Shell-style routing, not for offline fallback pages.)

claymation296 commented 6 years ago

Thanks @jeffposnick ! You saved my life!!

alexeigs commented 5 years ago

@claymation296 Can you remember what exactly solved your issue? I'm facing the same: While e.g. google-stored images (using the avatar src from my google profile) works without issues, for firebase storage images service workers do not seem to work properly as the image always needs half a second to appear when page is revisited.

Not sure it is relevant but in dev mode I get Using NetworkFirst to respond to 'https://firestore.googleapis.com/google.firestore.v1.Firestore/Listen/channel?database=projects%2Fproject-name%2Fdatabases%2F(default)&gsessionid=...&VER=8&RID=rpc&SID=...&CI=0&AID=41&TYPE=xmlhttp&zx=...&t=1' in my console. Does that mean it always pulls it fresh instead of using the cached version? At least this appears roughly 50% of the time when testing by randomly navigating back and fro. The other half it works fine and also that message doesn't appear.

Using out of the box workbox config from the latest quasar cli.

longlost commented 5 years ago

@alexeigs Here is my functioning workbox config.

You can test that this works in Chrome Dev Tools by navigating to the Application tab --> Cache --> Cache Storage --> "app-images" (the cache name you provide in the config).

Also you should go offline and refresh the page. If your storage images load, this means the sw is picking them up.

The fact that it takes half a second for the images to appear is most likely due you using the 'NetworkFirst' handler, but can also be due to the file size. I recommend switching to 'staleWhileRevalidate' which serves from the cache first before attempting to hit the network. This should speed up load times dramatically.

Make sure to optimize your images, and also try to serve the appropriate image size for the situation. There is a limit to how many large images will fit in the browser cache so make sure that you aren't exceeding this.

Hope this helps!

// create a service worker new GenerateSW({ cacheId: 'my-app-cache', clientsClaim: true, importScripts: ['service-worker-app.js'], skipWaiting: false, navigateFallback: './index.html', navigateFallbackWhitelist: [/^(?!\/__)/], // allow firebase api to bypass sw runtimeCaching: [{ urlPattern: new RegExp('^https://storage\\.googleapis\\.com/'), handler: 'staleWhileRevalidate', options: { // Use a custom cache name. cacheName: 'app-images', // Only cache 50 images. expiration: { maxEntries: 50, } } }] }),