javascript - 如何防止 Service Worker 删除缓存、PWA
问题描述
我使用 Vue、js、节点技术构建了启用 PWA 的 SPA。问题是每当我关闭我的电脑时,服务人员都会删除我存储的缓存以便离线查看应用程序,否则它可以工作。第二个问题是它拒绝获取包含谷歌字体的数据,除非我在浏览器中启用 CORS。由于 PWA 是基于浏览器的,用户不会在浏览器中安装 CORS 插件,有没有办法在(Windows)服务器上启用 CORS?在此先感谢,这是我的服务人员代码。
// 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
})
)
});
解决方案
似乎问题出activate
在服务工作者中的事件处理程序上。这主要用于从浏览器中删除旧缓存。尝试用以下代码替换事件监听器
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();
})
);
});
推荐阅读
- javascript - AngularJS MultiSelect在初始化时崩溃的应用程序
- python - 创建基于 Pandas.DataFrame 的类,使用 pandas.read_csv() 函数进行初始化
- git - 有没有办法检查另一个分支中存在的分支中的最后一次提交?
- c++ - 如何让 mingw64 链接到 Windows 上的 OpenAL
- javascript - @Url.Action 和 JavaScript
- javascript - 你如何在php中的输入之间切换?
- python - Python tkinter 在类或帧之间传递变量
- c# - 以编程方式获取 BIOS 引导菜单键
- python - Geoviews + Datashader在投影点时很慢
- mysql - 未来预期销售查询的功能将不会运行 - MySQL