Dagg M.
Dagg M.

Reputation: 68

How do I prevent service worker from deleting cache, PWA

I have built PWA enabled SPA by using Vue, js, node technology. Problem is that service worker deletes my stored cache for viewing app offline whenever i switch off my PC, otherwise it works. Second problem is that it refuses to fetch data that includes google fonts, unless I enable CORS in the browser. Since PWA is based on the browser and users will not have CORS add-on installed in the browser, is there some way to enable CORS on the (Windows) server? Thanks in advance, here is my service worker code.

// service worker file. Every time when you change this file rename staticCache const in order to changes to be visible when user closes tab and reopens it.
const staticCache = 'site-static-1';  // static cache for main site files, app shell (all static files, html, css, starting images, logo etc). If you change code always rename this to new number 
const assets = [  // this is array of app shell API requests for assets. Those are keys and asset values (images etc) will be values of key/value pair in array
    '/',
    '/index.html',
    '/app.c328ef1a.js',
    '/app.c328ef1a.css',
    '/manifest.webmanifest',
    '/photo-login.04703ebf.jpg',
    '/icon_area.9bfa0c9a.png',
    '/icon_144x144.c75152b5.png',
    '/img/avatar_default.png',
    '/img/icon_pwa.png',
    'https://fonts.googleapis.com/css?family=Raleway:300,400,600,700', 
    'https://code.highcharts.com/stock/highstock.js',
    'https://code.highcharts.com/stock/modules/data.js',
    'https://code.highcharts.com/stock/modules/exporting.js',
    'https://cdn.pubnub.com/sdk/javascript/pubnub.4.21.7.min.js',
    'https://fonts.gstatic.com/s/raleway/v14/1Ptrg8zYS_SKggPNwIYqWqhPAMif.woff2',
    'https://fonts.gstatic.com/s/raleway/v14/1Ptug8zYS_SKggPNyCMIT5lu.woff2',
    'https://fonts.gstatic.com/s/raleway/v14/1Ptug8zYS_SKggPNyC0ITw.woff2',
    'https://fonts.gstatic.com/s/raleway/v14/1Ptrg8zYS_SKggPNwPIsWqhPAMif.woff2',
    'https://fonts.gstatic.com/s/raleway/v14/1Ptrg8zYS_SKggPNwPIsWqZPAA.woff2',
    'https://fonts.gstatic.com/s/raleway/v14/1Ptrg8zYS_SKggPNwJYtWqhPAMif.woff2',
    'https://fonts.gstatic.com/s/raleway/v14/1Ptrg8zYS_SKggPNwJYtWqZPAA.woff2'
];  // we hve to fetch separately fonts from links inside fonts.googleapis.com 
// In Chrome Web Tools go to Application>Cache storage and click /css?family=raleway, links are inside value of that key


// installing service worker event
self.addEventListener('install', evt => {
    console.log('Service worker has been installed');
    // programmatically skip awaiting for new changed sw file to become active, because sometimes closing Chrome and tabs is not enough
    // if we change sw.js and want to make sure change is visible ie cache is refreshed, we need to change version number of staticCache constant.
    // NOTE: If we save this file by adding asset to be fetched (image for example) it will be visible in a new cache upon clicking browser reload.
    // ..but if we delete it from the list of items to be fetched, IT WILL REMAIN  in the cache until we change staticCache version number, save  and reload browser page.
    // So it is best practice to always change version number in staticCache whenever you make and save changes.
    self.skipWaiting(); // it will be triggered only if there is a new sw version that awaits to be executed


    evt.waitUntil(  // installing awaits until this is executed first, otherwise it could stop it
        caches.open(staticCache).then(cache => {  // it opent cache, if there isn't it will create one
            cache.addAll(assets);  // add into cache all assets from the assets array []
        })
    );
});

// activating service worker event
self.addEventListener('activate', evt => {
    console.log('Service worker has been activated');
    evt.waitUntil(
        caches.keys().then(keys => {  // get array with keys (of key/value pair) from different cache versions in  Chrome Dev Tools>Application>Cache Storage
            // go thru all caches keys array and delete all values except newest cache, named in staticCache const. That way only the last cache is used by an app
            return Promise.all(keys  
                .filter(key => key !== staticCache)
                .map(key => caches.delete(key))    
            )
        })
    );
});


// fetch event
self.addEventListener('fetch', evt => {
    console.log('SW is fetching data');
    evt.respondWith(  // check if requested data is stored in the cache.
        caches.match(evt.request).then(cacheRes => {
            return cacheRes || fetch(evt.request)  // if item is in cache use it, if isn't go to the server and fetch it        
        })
    )
});

Upvotes: 1

Views: 2114

Answers (1)

Rijosh
Rijosh

Reputation: 1544

Seems like the issue is with the activate event handler in the service worker. This is mainly using for removing the old cache from the browser. Try replacing the event listener with the following code

self.addEventListener('activate', (event) => {
    event.waitUntil(
        caches.keys().then((cacheNames) => {
            return Promise.all(
                cacheNames.map((cache) => {
                    if (cache !== staticCache) {
                        return caches.delete(cache); //Deleting the old cache (cache v1)
                    }
                })
            );
        })
            .then(function () {
                console.info("Old caches are cleared!");
                return self.clients.claim();
            })
    );
});

Upvotes: 0

Related Questions