这是配置的sw.js
已测试,是OK的.
'use strict'; const version = 'v2'; const __DEVELOPMENT__ = false; const __DEBUG__ = true; const offlineResources = [ './tt.html', './images/1.png', // '/imgerror.jpg', // '/favicon.ico' ]; const ignoreCache = [ /https?://hm.baidu.com//, /https?://www.google-analytics.com//, /http?://resource.haorooms.com//, /https?://www.haorooms.com/admin/, /https?://github.com//, // /https?://z4.cnzz.com//, ]; // 慎重使用全局可变变量,因为 serviceWork 不可控的停止和重启,会导致它们的取值在后续读取时无法预测 let port; /** * common function */ function developmentMode() { return __DEVELOPMENT__ || __DEBUG__; } function cacheKey() { return [version, ...arguments].join(':'); } function log() { if (developmentMode()) { console.log("SW:", ...arguments); } } // 不需要缓存的请求 function shouldAlwaysFetch(request) { return __DEVELOPMENT__ || request.method !== 'GET' || ignoreCache.some(regex => request.url.match(regex)); } // 缓存 html 页面 function shouldFetchAndCache(request) { return (/text/html/i).test(request.headers.get('Accept')); } // 发送 Notification 通知 function sendNotify(title, options, event) { if (Notification.permission !== 'granted') { log('Not granted Notification permission.'); // 无授权时,向来源页面申请授权 if (port && port.postMessage) { port.postMessage({ type: 'applyNotify', info: { title, options } }); } return; } const notificationPromise = self.registration.showNotification(title || 'Hi:', Object.assign({ body: '这是一个通知示例', icon: './images/1.png', requireInteraction: true, // tag: 'push' }, options)); return event && event.waitUntil(notificationPromise); } /** * onClickNotify */ function onClickNotify(event) { event.notification.close(); const url = "https://www.baidu.com"; event.waitUntil( self.clients.matchAll({ type: "window" }) .then(() => { if (self.clients.openWindow) { return self.clients.openWindow(url); } }) ); } /** * Install 安装 */ function onInstall(event) { log('install event in progress.'); event.waitUntil( caches.open(cacheKey('offline')) .then(cache => cache.addAll(offlineResources)) .then(() => log('installation complete! version: ' + version)) .then(() => self.skipWaiting()) ); } /** * Fetch */ // 当网络离线或请求发生了错误,使用离线资源替代 request 请求 function offlineResponse(request) { log('(offline)', request.method, request.url); if (request.url.match(/.(jpg|png|gif|svg|jpeg)(?.*)?$/)) { return caches.match('./imgerror.jpg'); } else { return caches.match('./offline.html'); } } // 从缓存读取或使用离线资源替代 function cachedOrOffline(request) { return caches .match(request) .then((response) => response || offlineResponse(request)); } // 从网络请求,并将请求成功的资源缓存 function networkedAndCache(request) { return fetch(request) .then(response => { const copy = response.clone(); caches.open(cacheKey('resources')) .then(cache => { cache.put(request, copy); }); log("(network: cache write)", request.method, request.url); return response; }); } // 优先从 cache 读取,读取失败则从网络请求并缓存。网络请求也失败,则使用离线资源替代 function cachedOrNetworked(request) { return caches.match(request) .then((response) => { log(response ? '(cached)' : '(network: cache miss)', request.method, request.url); return response || networkedAndCache(request) .catch(() => offlineResponse(request)); }); } // 优先从网络请求,失败则使用离线资源替代 function networkedOrOffline(request) { return fetch(request) .then(response => { log('(network)', request.method, request.url); return response; }) .catch(() => offlineResponse(request)); } function onFetch(event) { const request = event.request; // 应当永远从网络请求的资源 // 如果请求失败,则使用离线资源替代 if (shouldAlwaysFetch(request)) { log('AlwaysFetch request: ', event.request.url); event.respondWith(networkedOrOffline(request)); return; } // 应当从网络请求并缓存的资源 // 如果请求失败,则尝试从缓存读取,读取失败则使用离线资源替代 if (shouldFetchAndCache(request)) { event.respondWith( networkedAndCache(request).catch(() => cachedOrOffline(request)) ); return; } event.respondWith(cachedOrNetworked(request)); } /** * Activate */ function removeOldCache() { return caches .keys() .then(keys => Promise.all( // 等待所有旧的资源都清理完成 keys .filter(key => !key.startsWith(version)) // 过滤不需要删除的资源 .map(key => caches.delete(key)) // 删除旧版本资源,返回为 Promise 对象 ) ) .then(() => { log('removeOldCache completed.'); }); } function onActivate(event) { log('activate event in progress.'); event.waitUntil(Promise.all([ // 更新客户端 self.clients.claim(), removeOldCache() ])) } /** * onPush */ function onPush(event) { log('onPush ', event); sendNotify('Hi:', { body: `发生了一次 Push 同步事件 ~` }, event); } /** * onSync */ function onSync(event) { log('onSync', event); sendNotify('Hi:', { body: `发生了一次 Sync 同步事件 ~` }, event); } /** * onMessage */ function onMessage(event) { log('onMessage', event); if (event.ports) { port = event.ports[0]; } if (!event.data) { return; } // 如果是要求一条通知,则发送 if (event.data.type === 'notify') { const { title, options } = event.data.info || {}; sendNotify(title, options, event); } } log("Hello from ServiceWorker land!", version); self.addEventListener('install', onInstall); self.addEventListener('fetch', onFetch); self.addEventListener("activate", onActivate); self.addEventListener("push", onPush); self.addEventListener("sync", onSync); self.addEventListener('message', onMessage); self.addEventListener("notificationclick", onClickNotify);