🚀

PWAを実装した

2023/04/28に公開

Progressive web apps を実装しました。サイトをインストールしたり、オフラインで動かしたりできるようになりました。

<link rel="manifest" href="path/to/app.webmanifest">
<script>navigator.serviceWorker?.register("/service-worker.js").then(_onFulfilled).catch(_onRejected)</script>

Lighthouseで検証できます。

Service Worker

ネットワークリクエストやキャッシュの制御ができます。サイトのオフライン動作を助けてくれます。

// service-worker.js
self.addEventListener("install", _oninstall);
self.addEventListener("activate", _onactivate);
self.addEventListener("fetch", _onfetch);

Service Worker ファイルの更新はブラウザによって検出されるようです。

installイベント

Service Worker がインストールされるときに発行されます。

self.addEventListener("install", event => event.waitUntil(Promise.all([_addResourcesToCache(), self.skipWaiting()])));

ServiceWorkerGlobalScope.skipWaiting

更新を即座に有効にすることができます。

activateイベント

Service Worker が有効化されるときに発行されます。

self.addEventListener("activate", event => event.waitUntil(Promise.all([
    !self.registration.navigationPreload ? Promise.resolve() : self.registration.navigationPreload.enable(),
    _deleteOldCaches(),
    self.clients.claim(),
])));

ナビゲーション先読みを有効にすることができます。

Clients.claim

登録された Service Worker を、再読み込みせずに使用できるようになります。

fetchイベント

サイトのリソースが読み込まれるときに発行されます。

self.addEventListener("fetch", event => _cacheFirst());

キャッシュ

.htaccessファイルなどで制御しておくと、Service Worker がキャッシュを更新するときに、新しいリソースだけをサーバーから取得するようにできます。

<ifModule mod_headers.c>
    Header set Cache-Control "max-age=0"
</ifModule>

max-age

キャッシュの寿命が指定です。

Web app manifests

サイトがインストールできるようになります。

.webmanifest拡張子JSONファイルです。ブラウザは.json拡張子にも対応してくれるようです。

{
    "short_name": "アプリの名前",
    "name": "アプリの名前",
    "icons": [{
        "src": "path/to/icon.svg",
        "type": "image/svg+xml",
        "purpose": "monochrome",
        "sizes": "any"
    }],
    "description": "説明"
}

ウェブブラウザの開発者ツールで検証できます。

必須

short_name又はname

アプリの名前です。

icons

アイコンです。画像オブジェクトの配列で、各オブジェクトのpurposeでアイコンの用途が指定できます。monochromemaskableanyなどです。

192×192と512×512のアイコンを用意するとよいようです。一方でSVGに対応するブラウザもあります。

start_url

URLです。

"start_url": "/"

ここではトップページを指定しています。

background_color

スプラッシュ画面の背景色です。

"background_color": "black"

ページのbackground-colorと一致しているとよいようです。

display

ブラウザUIの表示です。

"display": "standalone"

ここでは単独アプリのように表示しようとしています。

対応していない場合は、ブラウザが特定の順番で代わりの方法を決定するようです。display_overrideでその順番が変更できます。

scope

ナビゲーションスコープです。

"scope": "/"

ここではトップページを指定しています。

theme_color

テーマカラーです。

"theme_color": "yellow"

HTMLの<meta name="theme-color">タグでも指定できます。media属性と合わせてシステムのテーマに対応することもできます。

<meta name="theme-color" media="(prefers-color-scheme: light)" content="yellow">
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="lightyellow">

ここでは、いわゆるライトモードのときにyellow、ダークモードのときにlightyellowをテーマカラーとするよう指定しています。

lang

言語タグです。

"lang": "ja-JP"

ここでは日本の日本語を指定しています。

orientation

画面の向きです。

"orientation": "any"

ここでは任意の向きを指定しています。

Discussion