为网站开启 PWA

开启 PWA 需要三个部分:一个 JS 文件,一个 HTML 文件,一个 manifest 文件。我的网站使用 Hugo 构建。

JS 文件:

 1/**
 2  References:
 3
 4  1. https://developers.google.com/web/fundamentals/primers/service-workers
 5  2. https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook
 6  3. https://googlechrome.github.io/samples/service-worker/
 7  4. https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers
 8  5. https://serviceworke.rs/
 9  6. https://www.youtube.com/watch?v=baSiSIyTGSk
10*/
11
12const RUNTIME = "runtime";
13
14self.skipWaiting();
15
16self.addEventListener("fetch", (event) => {
17  // Do nothing if not the same origin
18  if (!event.request.url.startsWith(self.location.origin)) {
19    return;
20  }
21
22  // Network first strategy
23  event.respondWith(
24    (async () => {
25      const cache = await caches.open(RUNTIME);
26
27      try {
28        const networkResponse = await fetch(event.request);
29
30        // Save/Update cache if network response is ok
31        if (networkResponse && networkResponse.status === 200) {
32          cache.put(event.request, networkResponse.clone());
33        }
34
35        return networkResponse;
36      } catch (e) {
37        const cachedResponse = await cache.match(event.request);
38
39        return cachedResponse;
40      }
41    })()
42  );
43});

HTML 文件:

 1{{ if and .Site.Params.enableServiceWorker (eq hugo.Environment "production") }}
 2    {{- $sw := resources.Get "js/sw.js" -}}
 3    {{- $dummy := "" | resources.FromString "dummy.js" -}}
 4    {{- $url := (slice $sw $dummy | resources.Concat "sw.js").RelPermalink -}}
 5
 6    <script>
 7        if ('serviceWorker' in navigator) {
 8            window.addEventListener('load', function() {
 9                navigator.serviceWorker.register('{{ $url }}');
10            });
11        }
12    </script>
13{{ end }}

manifest 文件:

 1{
 2  "name": "一大加贝",
 3  "icons": [
 4    {
 5      "src": "/images/android-chrome-192x192.png",
 6      "type": "image/png",
 7      "sizes": "192x192",
 8      "purpose": "maskable"
 9    },
10    {
11      "src": "/images/android-chrome-512x512.png",
12      "sizes": "512x512",
13      "type": "image/png"
14    }
15  ],
16  "start_url": "/?source=pwa",
17  "theme_color": "#fff",
18  "background_color": "#fff",
19  "display": "standalone",
20  "orientation": "portrait-primary"
21}

最后把以上三个文件导入网站中即可。

ref:

  1. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta/name/theme-color
  2. 一个简单的 Service Worker
  3. service-worker.html
  4. sw.js