为网站开启 PWA

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

JS 文件:

    /**
      References:

      1. https://developers.google.com/web/fundamentals/primers/service-workers
      2. https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook
      3. https://googlechrome.github.io/samples/service-worker/
      4. https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers
      5. https://serviceworke.rs/
      6. https://www.youtube.com/watch?v=baSiSIyTGSk
    */

    const RUNTIME = "runtime";

    self.skipWaiting();

    self.addEventListener("fetch", (event) => {
      // Do nothing if not the same origin
      if (!event.request.url.startsWith(self.location.origin)) {
        return;
      }

      // Network first strategy
      event.respondWith(
        (async () => {
          const cache = await caches.open(RUNTIME);

          try {
            const networkResponse = await fetch(event.request);

            // Save/Update cache if network response is ok
            if (networkResponse && networkResponse.status === 200) {
              cache.put(event.request, networkResponse.clone());
            }

            return networkResponse;
          } catch (e) {
            const cachedResponse = await cache.match(event.request);

            return cachedResponse;
          }
        })()
      );
    });

HTML 文件:

    {{ if and .Site.Params.enableServiceWorker (eq hugo.Environment "production") }}
        {{- $sw := resources.Get "js/sw.js" -}}
        {{- $dummy := "" | resources.FromString "dummy.js" -}}
        {{- $url := (slice $sw $dummy | resources.Concat "sw.js").RelPermalink -}}

        <script>
            if ('serviceWorker' in navigator) {
                window.addEventListener('load', function() {
                    navigator.serviceWorker.register('{{ $url }}');
                });
            }
        </script>
    {{ end }}

manifest 文件:

    {
      "name": "一大加贝",
      "icons": [
        {
          "src": "/android-chrome-192x192.png",
          "type": "image/png",
          "sizes": "192x192",
          "purpose": "maskable"
        },
        {
          "src": "/android-chrome-512x512.png",
          "sizes": "512x512",
          "type": "image/png"
        }
      ],
      "start_url": "/?source=pwa",
      "theme_color": "#fff",
      "background_color": "#fff",
      "display": "standalone",
      "orientation": "portrait-primary"
    }

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

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
欢迎通过「邮件」或者点击「这里」告诉我你的想法
Welcome to tell me your thoughts via "email" or click "here"