7

I have an application in Angular with PWA configured, besides caching assets/images I would also like to cache the images that are in Firebase Storage once they are loaded when I am Online.

My application makes use of the Cloud Firestore database with data persistence enabled. When I need to load the avatar of the authenticated user on the system in offline mode, it tries to load through the photoURL field, but since it is offline I can not load the image so the image is not displayed and this is not legal for the user.

In my code I load the image as follows:

<img class="avatar mr-0 mr-sm-16" src="{{ (user$ | async)?.photoURL || 'assets/images/avatars/profile.svg' }}">

I would like it when it was offline, it would search somewhere in the cache for the image that was uploaded.

It would be very annoying every time I load the images to call some method to store the cached image or something, I know it is possible but I do not know how to do that.

Is it possible to do this through the ngsw-config.json configuration file?

ngsw-config.json:

{
  "index": "/index.html",
  "assetGroups": [
    {
      "name": "app",
      "installMode": "prefetch",
      "resources": {
        "files": [
          "/favicon.ico",
          "/index.html",
          "/*.css",
          "/*.js"
        ],
        "urls": [
          "https://fonts.googleapis.com/css?family=Muli:300,400,600,700"
        ]
      }
    }, {
      "name": "assets",
      "installMode": "lazy",
      "updateMode": "prefetch",
      "resources": {
        "files": [
          "/assets/**",
          "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
        ]
      }
    }
  ]
}
Luiz Ricardo Cardoso
  • 1,554
  • 4
  • 16
  • 37

2 Answers2

3

Yes, it's possible, I tried and works for me, I have a pwa with ionic and angular 7, in my 'ngsw-config.json' I used this config:

{
  "index": "/index.html",
  "assetGroups": [{
    "name": "app",
    "installMode": "prefetch",
    "resources": {
      "files": [
        "/favicon.ico",
        "/index.html",
        "/*.css",
        "/*.js"
      ]
    }
  }, {
    "name": "assets",
    "installMode": "lazy",
    "updateMode": "prefetch",
    "resources": {
      "files": [
        "/assets/**",
        "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
      ]
    }
  }],
  "dataGroups": [{
    "name": "api-freshness",
    "urls": [
      "https://firebasestorage.googleapis.com/v0/b/mysuperrpwapp.appspot.com/"
    ],
    "cacheConfig": {
      "maxSize": 100,
      "maxAge": "180d",
      "timeout": "10s",
      "strategy": "freshness"
    }
  }]
}

In this article is well explained how works and what strategies you can use.

https://medium.com/progressive-web-apps/a-new-angular-service-worker-creating-automatic-progressive-web-apps-part-1-theory-37d7d7647cc7

It was very important in testing to have a valid https connection for the 'service_worker' starts. Once get offline, you can see that the file comes from "service_worker"

Test img _ from service_worker

Joseph M
  • 31
  • 2
  • Okay, I'll try this;) – Luiz Ricardo Cardoso Mar 16 '19 at 00:05
  • Just a question, the image is loaded through the URL saved in Firestore is the downloadURL that Firebase Storage makes available when uploading the file. Is this image going to load anyway? – Luiz Ricardo Cardoso Mar 16 '19 at 00:58
  • Are you talking about the function "getDownloadURL ()" ?, when I'm in offline mode, this function returns the same URL if at least it did it once when it was online, but I'm not sure how it works. – Joseph M Mar 16 '19 at 15:29
  • the getDownloadURL () function I only call the moment the Image upload is done, after getting the URL I saved in the Firestore, then in my application I get the value of the photoURL field that was saved in the Firestore. – Luiz Ricardo Cardoso Mar 22 '19 at 02:48
  • I think that will not work. It's important to clarify that the loaded images to firebase have a default 'cache-control' metadata, it's 'private, max-age=0', which means it can not be cacheable by de browser and need to be downloaded for each request, To fix this, you will need change this with something like this: "ref.updateMetadata({ 'cacheControl': 'private, max-age=15552000' })" Otherwise, the "serivice worker" will try to download the image from network and get a error "504 gateway Timeaout" – Joseph M Mar 22 '19 at 19:25
2

just do

storage.ref("pics/yourimage.jpg").updateMetatdata({ 'cacheControl': 'private, max-age=15552000' }).subscribe(e=>{ });

and in your ngsw-config.json

"assetGroups": [{
    "name": "app",
    "installMode": "prefetch",
    "resources": {
      "files": [
        "/favicon.ico",
        "/index.html",
        "/*.css",
        "/*.js"
      ],
      "url":[
        "https://firebasestorage.googleapis.com/v0/b/*"
      ]
    }
  }
user8462556
  • 369
  • 6
  • 13
  • The "cacheControl"-Info is worth gold. After adding it to my 'resize'-function (which basically manipulates every image in my application) everything is smooth. Thanks man! – codingbuddha Sep 22 '19 at 07:29