Service worker

Service worker

Dev

In general, you need to serve both your page and your service worker script via HTTPS in order to use service workers. The rationale is described at Prefer Secure Origins For Powerful New Features.

There's an exception to the HTTPS requirement in place to facilitate local development: if you access your page and service worker script via http://localhost[:port], or via http://127.x.y.z[:port], then service workers should be enabled without any further actions.

In recent versions of Chrome, you can work around this requirement duriing local development via chrome://flags/#unsafely-treat-insecure-origin-as-secure .

Firefox offers similar functionality, via the devtools.serviceWorkers.testing.enabled setting in about:config page.

静态资源离线缓存

一个最简的使用 vanilla service worker 的 PWA 网页静态资源缓存

const version = "1";
const cache_name = "cache-" + version;
const assets = [
  "./",
  "./index.html",
  "./app.css",
  "./manifest.json",
  "./app.js",
];

async function cleanResponse(response) {
  const cloned_response = response.clone();
  if (cloned_response.redirected == 0) {
    return cloned_response;
  }
  let response;
  if (cloned_response.body) {
    response = Promise.resolve(cloned_response.body);
  } else {
    response = cloned_response.blob();
  }
  let body = await response;
  return new Response(body, {
    headers: cloned_response.headers,
    status: cloned_response.status,
    statusText: cloned_response.statusText,
  });
}
async function cacheAsset(request) {
  console.log(
    "[Service Worker] Searching for resource: " + (request.url || request)
  );
  let req = (await caches.match(request)) || (await fetch(request));
  let cache = await caches.open(cache_name);
  console.log(
    "[Service Worker] Caching new resource: " + (request.url || request)
  );
  let cloned_response = await cleanResponse(req);
  await cache.put(request, cloned_response);
  return req;
}
self.addEventListener("install", (e) => {
  console.log("[Service Worker] Install"), e.waitUntil(self.skipWaiting());
});
self.addEventListener("fetch", (e) => {
  e.respondWith(cacheAsset(e.request));
});
self.addEventListener("activate", async (e) => {
  console.log("[Service Worker] Activate");
  await caches.open(cache_name);
  for (const asset of assets) {
    try {
      await cacheAsset(asset);
    } catch (e) {
      console.log("[Service Worker] Failed to download " + asset);
    }
  }
});

Workbox

Workbox 能够极大简化 Service worker 编码,是目前 service worker 事实上通用的标准工具库。

importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js');

workbox.precaching.precacheAndRoute([
  {
    "url": "css/index.css",
    "revision": "835ba5c3"
  },
  {
    "url": "images/xxx.png",
    "revision": "b1537bfs"
  },
  {
    "url": "index.html",
    "revision": "b331f695"
  },
  {
    "url": "js/index.js",
    "revision": "4d562866"
  }
]);

workbox.routing.registerRoute(
  new RegExp(''.*\.html'),
  workbox.strategies.networkFirst()
);

workbox.routing.registerRoute(
  new RegExp('.*\.(?:js|css)'),
  workbox.strategies.cacheFirst()
);

workbox.routing.registerRoute(
  new RegExp('https://your\.cdn\.com/'),
  workbox.strategies.staleWhileRevalidate()
);

workbox.routing.registerRoute(
  new RegExp('https://your\.img\.cdn\.com/'),
  workbox.strategies.cacheFirst({
    cacheName: 'example:img'
  })
);

Last update: 2022-11-16 05:57:38 UTC