たいして更新もしない個人のブログで 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.js と service-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 点になりました 👍