service worker

Posted yiyi17

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了service worker相关的知识,希望对你有一定的参考价值。

这是配置的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.xueersi.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);

  

以上是关于service worker的主要内容,如果未能解决你的问题,请参考以下文章

来用Service worker吧

注销/删除 Service Worker

Javascript Service Worker onload 显示通知

Service Worker 配置 - 网络然后缓存

PWA之 Service worker

Selenium 和 Service Worker 离线模式