メモログ

PWAのチェックリストを満たす

たいして更新もしない個人のブログで Service Worker とか入れる必要まったくないと思いながらも、Lighthouse の結果を見るたびに「PWA のチェックリストだけ 100 点に至らない」というなんとも言えないモヤモヤ感があった。別にそんなに大変でもないんだから入れてしまえ、ということで PWA のチェックリストを満たすべく、Service Worker と App manifest に対応しました。

Service Worker をサイトに追加するのはとても簡単で、Service Worker 用のスクリプトファイルを用意して、navigator.servceWoeker.register で読み込むだけ。HTTPS でないといけないとか、スクリプトファイルの置き場所が scope と異なる場合は Service-Worker-Allowed のヘッダーが必要とか、いろいろ考慮すべきところはあるけれど、Github pages は HTTPS だし、ファイルもどこにでも置けるので特に気にしなくても大丈夫。

<script async>
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js');
  }
</script>

service-worker.js では、今のところ最新 10 件分の HTML と featured image に使っている svg ファイルをプリキャッシュするようにした。

最新 10 件のポストデータを得るのに、まず script ディレクトリに service-worker.js を入れて、generator を登録。

hexo.extend.generator.register("service-worker", (locals) => {
  const posts = locals.posts
    .sort("-date")
    .filter((post) => post.draft !== true)
    .limit(10)
    .toArray();

  const lastUpdated = posts
    .sort((a, b) => (a.updated < b.updated ? 1 : -1))[0]
    .updated.valueOf();

  const precacheList = posts.map((post) => post.path);
  precacheList.unshift("/");

  posts.forEach((post) => {
    const featuredImage = post.featured && post.featured.image;
    if (featuredImage) {
      precacheList.push(`/assets/images/${featuredImage}/${featuredImage}.svg`);
    }
  });

  return {
    path: "service-worker.js",
    data: {
      precacheList: precacheList,
      lastUpdated: lastUpdated,
    },
    layout: "service-worker",
  };
});

そのあと theme の layout に service-worker.ejs を追加して、Service Worker のスクリプトファイルを生成。

const precacheList = [
  <% page.precacheList.forEach(function(item){ %>
  '<%- url_for(item) %>',<% }); %>
];

詳細は service-worker.jsservice-worker.ejs を参照。

App Manifest については静的なファイルを用意して、manifest へのリンクを追加しただけ。 theme-color は Light House がそう言ってくるので追加している。

<link rel="manifest" href="/manifest.json" />
<meta name="theme-color" content="white" />

詳細は manifest.json。ただ値を入れるだけではあるけど、スプラッシュスクリーンを有効にするためにいくつか要件があり、それを満たすようにアイコン画像を用意している。

そして Lighthouse の結果。100 点になりました 👍

私について

Yutaka Yamaguchi
東京在住。TypeScript, Node.js, Reactなどフロンエンドが主力。Perlも書く。SwiftやRubyも過去には使ってた。過去のTOEIC 860くらい。