Create base Pwa App#3 : Cache strategy and Implementation Cache then network

in utopian-io •  14 days ago

Repository

https://github.com/jquery/jquery

What Will I Learn?

  • Cache strategy
  • Implementation Cache then network

Requirements

  • Basic Html, CSS, javascript
  • Install Jquery and basic Jquery
  • Local server (Xampp, Wampp, or etc)

Resources

Difficulty

Basic

Tutorial Content

This tutorial is a continuation tutorial from the previous tutorial series, I suggest you follow the previous tutorial so that you can interpret this tutorial as a whole. in this tutorial we will learn the strategies in the cache, there are a lot of cache strategies, it all depends on the conditions we want and the techniques we want, so there is no strategy term what is best because all of them are based on your needs when using it. for more details, you can read about the caching strategies The offline cookbook.

Cache when installing

This strategy is the most commonly used, we have put it into practice in the previous tutorial where we have cached when the service worker was installed, as we saw in the code below.

self.addEventListener('install', function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME).then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});

cache when installing, in this code we store the value in the variable CACHE_NAME and urlsToCache as we know in the previous tutorial the value of the variable is like the following.

var CACHE_NAME = 'my-site-cache-v2';
var urlsToCache = [
  '/',
  'assets/woman.jpg',
  'assets/main.css',
  'js/main.js',
  'js/jquery.min.js'
];

ezgif.com-video-to-gif.gif

Cache when uninstalling

We can also cache when uninstalling the cache, this strategy is commonly used when for example you are playing a game and has reached a certain level, then the cache is uninstalled then the game will not return to the initial level but the level where you last played. we can see the difference in the code below.

self.addEventListener('install', function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME).then(function(cache) {
         cache.addAll(
                 urlsToCache
                 );
                 // Return the cache
                  return cache.addAll(
                 urlsToCache
                 );
      })
  );
});

Unlike in the cache when installing on uninstall we restore the cache before going from the promotion to the previous cache that will be used return cache.addAll( urlsToCache );.

Cache when activating

In the previous tutorial, we also used the activate strategy, in this section we use this event to delete cache or data.

self.addEventListener('activate', function(event) {
 event.waitUntil(
   caches.keys().then(function(cacheNames) {
     return Promise.all(
       cacheNames.filter(function(cacheNames){
         return cacheNames != CACHE_NAME
       }).map(function(cacheName) {
           return caches.delete(cacheName)
       })
     );
   })
 );
});

We will delete the previous cache if a new cache has been created return cacheNames != CACHE_NAME

return Promise.all(
        cacheNames.filter(function(cacheNames){
          return cacheNames != CACHE_NAME
        }).map(function(cacheName) {
            return caches.delete(cacheName)
        })

ezgif.com-video-to-gif (1).gif

Cache when user interaction

an event that is no less interesting is that we will only cache when the user interacts like clicking buttons or doing other interactions, so later we can choose which cache and which data, and for more details, we can see in the sample code below.

document.querySelector('.cache-article').addEventListener('click', function(event) {
  event.preventDefault();

  var id = this.dataset.articleId;
  caches.open('mysite-article-' + id).then(function(cache) {
    fetch('/get-article-urls?id=' + id).then(function(response) {
      // /get-article-urls returns a JSON-encoded array of
      // resource URLs that a given article depends on
      return response.json();
    }).then(function(urls) {
      cache.addAll(urls);
    });
  });
});

like javascript events we can usually do onclik, onchange, and other examples like document.querySelector('.cache-article').addEventListener('click', function(event) { }. then we can cache specifically based on unique IDs var id = this.dataset.articleId;

Serving suggestion

Here we will discuss serving suggestion, serving suggestion is divided into two things, cache only and network only.

  • Cache only

In the cache only section, we only want to respond to data from the cache, this is what we saw and implemented in the previous tutorial like the code.

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then(function(response) {
        // Cache hit - return response
        if (response) {
          return response;
        }
        return fetch(event.request);
      }
    )
  );
});

the code above we just want to get the response, when there is a response if (response) {return response;} but when there is no response we will retrieve the data from the cache that matches the cache name return fetch(event.request);and not request to network.

  • Network only

Network only is the opposite of cache only if in cache only we always use the available cache without getting new data from the internet. in the network only. We will only take data directly from the internet without considering the existing cache, we can see it like the code below.

self.addEventListener('fetch', function(event) {
 event.respondWith(fetch(event.request));
});

With this method we will no longer see the cache previously stored, this method is the default browser method. so we will always fetch the new data via the fetch() method.

Cache then network

We haven't used this caching strategy on the application, this strategy is quite interesting. of course we want to make sure our application uses the latest data, so with this first strategy we will do is we will use the cache in our application, but at the same time we will also connect to the internet, well after we get data from the internet , then the data in our application will also change with the data we retrieve from the internet.we will demonstrate this strategy in our application.

Cache then network implementation

we will demonstrate this strategy in our application, in this application we use the API, because of this we will also cache our application but we will not cache in the sw.js section, but we will separate the separate API cache.

  • How does it work ?

In this method, what we will do first is if we have a cache, we will first display the data from the cache, but if the cache does not exist we will fetch data from the API and later if the data in the API is updated, then we will also change the data what is shown as the latest data is not the data from the cache, for that we will overhaul the little code that we made before.

  • Separate Internal cache

What we will do next is to separate the cache from the API and cache that we have made previously that come from internal. the following is an example.

self.addEventListener('fetch', function(event) {
  var request = event.request;
  var url     = new URL(request.url);
  //Separate response if cache from internal 
  if(url.origin === location.origin){
      event.respondWith(
        caches.match(request).then(function(response){
          return response || fetch(request)
        })
      );  
  }
});
  • Define variable: We will make several variables to store some data to make it more simple, We need to save the URL that we are accessing we can get it on event.request. then we can also create an URL object with the new URL (), that is javascript method so that we can see the source of our URL.

  • Check Source URL: After we get the value from the URL and the source we will check whether the source and url urls that we are accessing are the same, if the same means we are not accessing the API, we can do like this if(url.origin === location.origin){}. We do the check process like this because it happens that our application uses the API.

  • Cache response: Same as before we will match cache with requests that we get caches.match(request).then(function(response){ });, then we will return the data in response when there is a cache but if there is no chace we will fetch to retrieve data from the internet return response || fetch(request)

  • Separate API cache

We have checked the URL that we access then we will make else {} to cache the API we use, because we cache the API we use we need to make it dynamic. for more details, you can see the code below.

self.addEventListener('fetch', function(event) {
  var request = event.request;
  var url     = new URL(request.url);
  //Separate response if cache from internal 
  if(url.origin === location.origin){
      event.respondWith(
        caches.match(request).then(function(response){
          return response || fetch(request)
        })
      );  
  }else{// API cache
      event.respondWith(
        caches.open("Api-cache").then(function(cache){
          return fetch(request).then(function(apiRespone){
            cache.put(request, apiRespone.clone())
            return apiRespone
          })
        })
      );
  }
});
  • Make new Cache: We will do a response by creating a new cache named "Api-cache". and then we will immediately retrieve data from the internet using the fetch () method.

  • Create promise in fetch(): When fetching data from live with the fetch () method we will also make a promise fetch(request).then(function(apiRespone) { });, so that we not only return the values we retrieve from the internet, but we will also save the data that we have fetched in the cache cache.put(request, apiRespone.clone()). request the request is the URL that we will cache. apiRespone.clone() What we will save is data on apiRespone, but we will do the clone() method first so we can return in the next code return apiRespone.

  • Handle Error

Because we use promises a lot we also have to handle if an error occurs we will handle an error like the code below.

self.addEventListener('fetch', function(event) {
  var request = event.request;
  var url     = new URL(request.url);
  //Separate response if cache from internal 
  if(url.origin === location.origin){
      event.respondWith(
        caches.match(request).then(function(response){
          return response || fetch(request)
        })
      );  
  }else{// API cache
      event.respondWith(
        caches.open("Api-cache").then(function(cache){
          return fetch(request).then(function(apiRespone){
            cache.put(request, apiRespone.clone())
            return apiRespone
          })
        }).catch(function(){
          return caches.match(request).then(function(){
            if(response) return response
              return caches.match('/error.json')
          })
        })
      );
  }
});
  • in the handle error section, we will see whether the cache already exists or not, We will also make a fallback. If it turns out the cache already exists, then we will make a return response if(response) return response
    . but if it's not there we will call the cache that is error.json return caches.match('/error.json'), We have not made error.json in this tutorial, we can add it in the variable urlsToCache like this.
var urlsToCache = [
  '/',
    'error.json',
  'assets/woman.jpg',
  'assets/main.css',
  'js/main.js',
  'js/jquery.min.js'
];

You are free to do anything when handling errors, we have managed to handle errors and also implement starategy cache then network on our application, in the next tutorial we will demonstrate to our application, there is much we can still do with this cache strategy, hopefully You can explore it even further, I suggest there is to see and study my tutorial before, you can see the bottom link. I hope this tutorial can help you thanks.

Curricullum

Create base pwa app #1Introduction service worker and Web manifest

Create base pwa app #2 Service worker installation, Activate service worker, and fetch cache

Proof of workdone

https://github.com/milleaduski/Pwa

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  
Loading...

Upvoted.

Hi @duski.harahap!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server

Hey, @duski.harahap!

Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!