sw.js 3.62 KB
/* eslint-env worker */
/* global FetchEvent */
self.workbox.skipWaiting();
self.workbox.clientsClaim();

const isDev = self.location.search.indexOf('dev') >= 0;
const staticDomian = isDev ? /^http:\/\/localhost:5001/i : /^https:\/\/(.*)cdn\.yoho\.cn/i;
const webDomian = isDev ? /^http:\/\/localhost:6001/i : /^https:\/\/m.yohobuy.com/;

// 定义缓存前缀
const NAME_CACHE_PREFIX = 'yoho-cache';

const precaches = [
    {
        url: '/offline.html',
        rivision: 'offline-rivision-0.0.1'
    },
    {
        url: '//cdn.yoho.cn/pwa/404.png',
        rivision: '404-rivision-0.0.1'
    }].concat(self.__precacheManifest || []);

self.workbox.precaching.precacheAndRoute(precaches);

/**
 * 需要缓存的路径
 */
const CACHED_PATH = [
    'boys',
    'girls',
    'kids',
    'lifestyle',
    'cate',
    'list',
    'search',
    'product',
    'shop',
    'guang',
    'offline.html'
];

// 自定义缓存
self.workbox.routing.registerRoute(args => {
    if (/sockjs-node\/info/.test(args.url.href)) {
        return false;
    }
    if (self.__precacheManifest.find(precahce => args.url.href.indexOf(precahce.url) >= 0)) {
        return false;
    }
    if (staticDomian.test(args.url.href)) {
        return true;
    }
    return false;
}, self.workbox.strategies.staleWhileRevalidate({
    cacheName: `${NAME_CACHE_PREFIX}-statics`,
    plugins: [
        new self.workbox.expiration.Plugin({
            maxEntries: 1000,
            maxAgeSeconds: 7 * 24 * 60 * 60 // 7 day
        })
    ]
}));

// 所有网络走 worker,异常时增加离线页面
self.workbox.routing.registerRoute(args => {
    let cached = false;
    let routeRegExp = new RegExp(`^\/(${CACHED_PATH.join('|')})`);

    if (webDomian.test(args.url.href) &&
        (routeRegExp.test(args.url.pathname) ||
        args.url.pathname === '/')) {
        cached = true;
    }

    if (args.event.request.headers.get('x-requested-with') === 'XMLHttpRequest' &&
        args.event.request.method !== 'GET') {
        cached = false;
    }

    return cached;
}, args => {
    return self.workbox.strategies.networkFirst({
        cacheName: `${NAME_CACHE_PREFIX}-runtime`,
        plugins: [
            new self.workbox.expiration.Plugin({
                maxEntries: 300,
                maxAgeSeconds: 12 * 60 * 60 // 12 小时
            })
        ]
    }).handle(args).then(res => {
        if (res || args.event.request.mode !== 'navigate') {

            // TODO report
            return res;
        }

        // navigate 请求失败后,返回网络异常页面
        return caches.match('offline.html');
    });
});

/**
 * webp 处理
 * 匹配非 webp 的 cdn 图片资源,缓存其 webp 格式
 */
self.workbox.routing.registerRoute(args => {
    let useWebp = false;
    let supportWebp = /image\/webp/i.test(args.event.request.headers.get('Accept'));

    if (!supportWebp) {
        return useWebp;
    }

    if (/^https:\/\/(.*)static\.yhbimg\.com(.*)(png|jpg|jpeg)\?(imageView|imageMogr)(.*)/.test(args.url.href) &&
    /^(?!.*format\/).*/.test(args.url.href)) {
        useWebp = true;
    }

    return useWebp;
}, args => {

    // 重新构造 fetch 请求
    args.event = new FetchEvent(args.event.type, {
        request: new Request(args.event.request.url + '/format/webp'),
        clientId: args.event.clientId,
        isReload: args.event.isReload
    });

    return self.workbox.strategies.staleWhileRevalidate({
        cacheName: `${NAME_CACHE_PREFIX}-images`,
        plugins: [
            new self.workbox.expiration.Plugin({
                maxEntries: 100,
                maxAgeSeconds: 24 * 60 * 60 // 24 小时
            })
        ]}).handle(args);
});