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);

  

原文地址:https://www.cnblogs.com/yiyi17/p/10975301.html

时间: 2024-08-02 07:10:48

service worker的相关文章

[PWA] 2. Service worker life cycle

Once serive worker is registered, the first time we go to the app, we cannot see the logs from servcie works. Any only refersh it second time, then we able to see the logs. Once we change service worker, it doesn't seem that we have change it. The No

认识 service worker

离线缓存可以提升用户体验,可以节省网络资源,但是,浏览器对资源缓存和自定义网络请求的控制一直不够完善,service worker 的出现就是为了解决这些问题 它可以解决目前离线应用的问题,同时也可以做更多的事. Service Worker 可以使应用先访问本地缓存资源,所以在离线状态时,在没有通过网络接收到更多的数据前,仍可以提供基本的功能(Offline First).这是原生APP 本来就支持的功能,这也是相比于 web app,原生 app 更受青睐的主要原因. 开始使用 有些浏览器版

借助Service Worker和cacheStorage缓存及离线开发 (转载)

一.缓存和离线开发 说得HTML5离线开发,我们通常第一反应是使用html5 manifest缓存技术,此技术已经出现很多年了,我以前多次了解过,也见过一些实践案例,但是却从未在博客中介绍过,因为并不看好. 为什么不看好呢?用一句话解释就是“投入产出比有些低”. 对于web应用,掉线不能使用是理所当然的,绝不会有哪个开发人员会因为网页在没网的时候打不开被测试MM提bug,或者被用户投诉,所以,我们的web页面不支持离线完全不会有什么影响.但如果我们希望支持离线,会发现,我投入的精力和成本啊还真不

[PWA] 1. Intro to Service worker

Service worker stays between our browser and noetwork requests. It can help to fetch data from cache and cache the data from Internet. To get our service worker, we need to : Register the service worker. Service worker in our code is just a javascirp

service worker 消息推送

https://developers.google.com/web/fundamentals/codelabs/push-notifications/?hl=en 首先下载源码: git clone https://github.com/GoogleChrome/push-notifications.git 设置如下选项方便开发: 开始 注册之后记录sw实例: navigator.serviceWorker.register('sw.js') .then(function(swReg) { co

Service Worker和HTTP缓存

很多人,包括我自己,初看Service Worker多一个Cache Storage的时候,就感觉跟HTTP长缓存没什么区别. 例如大家讲的最多的Service Worker能让网页离线使用,但熟悉HTTP缓存的朋友,会发现,把整站所有资源设置为长缓存(不带校验),也可以实现离线使用. 那么,Service Worker在缓存方面和HTTP缓存比较,有什么好处呢? 带着这个疑问,我翻阅了一些大神博客 JakeArchibald的<Caching best practices & max-ag

PWA之 Service worker

渐进式 Web 应用(Progressive Web Apps,也被称为 PWAs)是 Web 技术方面一项令人兴奋的创新.PWA 混合了多项技术,能够让 Web 应用的功能类似于原生移动应用.它为开发人员和用户带来的收益能够突破纯 Web 解决方案和纯原生解决方案的限制: 你只需要一个按照开放.标准 W3C Web 技术开发的应用,不需要开发单独的原生代码库: 用户在安装之前就能发现并尝试你的应用: 没有必要使用 AppStore,无需遵循复杂的规则或支付费用.应用程序会自动更新,无需用户交互

Service Worker基础知识整理

Service Worker是什么 service worker 是独立于当前页面的一段运行在浏览器后台进程里的脚本.它的特性将包括推送消息,背景后台同步, geofencing(地理围栏定位),拦截和处理网络请求. 这个 API 会让人兴奋的原因是,它可以使你的应用先访问本地缓存资源,所以在离线状态时,在没有通过网络接收到更多的数据前,仍可以提供基本的功能(一般称之为 Offline First). 在 service worker 之前,另一个叫做 APP Cache 的 api 也可以提供

使用 Service Workers 来预缓存应用外壳

Progressive Web Apps 是快速且可安装的,这意味着它能在在线.离线.断断续续或者缓慢的网络环境下使用.为了实现这个目标,我们需要使用一个 service worker 来缓存应用外壳,以保证它能始终迅速可用且可靠. 如果你对 service workers 不熟悉,你可以通过阅读 介绍 Service Workers 来了解关于它能做什么,它的生命周期是如何工作的等等知识. service workers 提供的是一种应该被理解为渐进增强的特性,这些特性仅仅作用于支持servi