この記事では、以前個人で作ったJavaScriptで動くページにPWAを導入する手順について説明します。 対象サイトは1ページだけで構成されていて、HTML+CSS+JavaScriptのみで作られているページをPWA化してみます。
PWA (Progressive Web Apps) はWebページをネイティブアプリとしてインストール&実行する仕組みのことです。 PWAを使うことにより、オフラインでもページを閲覧することができるようになります。
必要な作業
既存ページをPWA化するために必要な作業は大まかに以下の通りです。
- マニフェストファイル (manifest.json) を作成する
- アイコン用に 192x192 と 512x512 の2つ画像ファイルを用意する
- HTMLのheaderにマニフェストファイルへの参照を追加する
- ServiceWorkerの処理を書いたJavaScriptファイル (sw.js) を作成する
- HTMLで sw.js をServiceWorkerに登録する処理を追加する
- ブラウザで動作確認
今回は2017年ごろに作った「色の名は。」(https://github.com/tex2e/color-name) という一発ネタ用のサイトをPWA化してみます。 ちなみに最終的には以下のようになります。
1. Manifestファイルを作成する
アプリの設定などを記述するManifestファイルはJSONで書かれています。 以下の内容を「manifest.json」というファイル名で保存します。 Manifestファイルの作り方は https://web.dev/add-manifest/ に書かれています。 特に重要な項目は「name」「icons」「start_url」「display」の4つです。
{
"name": "色の名は。",
"icons": [
{
"src": "./img/color-name-icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "./img/color-name-icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "./index.html",
"display": "standalone",
"background_color": "#FFFFFF",
"theme_color": "#4e342e"
}
- name : アプリの名前。name はインストール時に表示するアプリ名で、short_name はユーザのホーム画面や起動画面などで表示されるアプリ名です。
- icons : ホーム画面や起動画面などで表示するアイコン。
- start_url : 対象画面のURL
- display : インストールしたアプリの表示形式(fullscreen, standalone, minimal-ui など)
2. アイコン用の画像ファイル作成
縦横サイズ 192×192 と 512×512 のアイコン用の画像を用意します。 GIMPで画像サイズ指定で作るのがおすすめです。 作成したら、manifest.json の icons で指定したパスに配置します。
ブラウザのインストールアイコンの出現条件によると、アイコンの画像は192と512pxの両方が必要なので、必ず両方とも用意しておく必要があります。
3. HTMLのheaderにmanifest.jsonへのlink追加
HTML側でlinkタグを使ってmanifest.jsonファイルの場所を書きます。 これを書くことによって、ブラウザはマニフェストファイルの内容を読みにいくようになります。
<link rel="manifest" href="manifest.json">
4. ServiceWorker用JavaScriptファイル作成
ServiceWorkerとは、あらかじめキャッシュされたリソースを簡単に使用できるようにする仕組みで、ページをオフラインで表示させるために使用します。
以下の内容を sw.js というファイル名でindex.htmlと同じフォルダに配置します。 (同じ階層に配置しないと、開発者ツールのApplicationタブで No matching service worker detected. と警告されてインストールボタンが表示されないので注意が必要です。)
配列 urlsToCache にキャッシュすべきファイルの一覧を書いていきます。 複数ページにまたがる場合はその全てをパスを記述しないといけなくなるので、SPAのようなシングルページアプリケーションとは相性がよさそうだと感じました。
var CACHE_NAME = 'color-name';
var urlsToCache = [
'/color-name/js/main.js',
'/color-name/css/normalize.css',
'/color-name/css/common.css'
];
// インストール処理
self.addEventListener('install', function(event) {
event.waitUntil(
caches
.open(CACHE_NAME)
.then(function(cache) {
return cache.addAll(urlsToCache);
})
);
});
// リソースフェッチ時のキャッシュロード処理
self.addEventListener('fetch', function(event) {
event.respondWith(
caches
.match(event.request)
.then(function(response) {
return response || fetch(event.request);
})
);
});
5. ServiceWorkerに登録
上記で作成したJavaScriptファイルをServiceWorkerに登録するためのスクリプトを追加します。 対象画面のHTMLのbodyの一番下に追加するのが手っ取り早いです。
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/color-name/sw.js').then(function(registration) {
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
console.log('ServiceWorker registration failed: ', err);
});
});
}
</script>
6. 動作確認
PWAのインストールボタン表示条件には以下の条件があります。
- Webアプリが未インストール
- HTTPS通信であること(localhostは例外)
- Webアプリのmanifestファイルに以下が含まれていること
-
name
またはshort_name
-
icons
: 192px と 512px のアイコン画像 start_url
-
display
: fullscreen, standalone, minimal-ui のどれか -
prefer_related_applications
が存在しない、または false が設定されている
-
- ServiceWorker用のJavaScriptで「fetch」ハンドラを使っていること
以上を満たしているときにページを開くと、Chromeの場合はアドレスバーの右側にインストールボタンが現れます。 クリックするとインストールするかのダイアログが表示されます。
インストールするとネイティブアプリとして動作します。 Windows10の場合は Win+S の検索から、インストールしたアプリが表示・起動できるようになります。 不要になった場合のアンインストールは、上部の設定ボタンからアンインストールができます。
全てのソースコードはGitHubに置いてあるので、よければ参考にしてください。
その他開発者向けの内容
設定をしてもPWAのインストールボタンが表示されないときがあります。 その際は、Chromeで開発者ツールを起動して、ApplicationタブのManifestを選択すると、manifest.jsonが読み込めているか、内容に問題はないかを確認することができます。 以下のように Installability の部分に黄色三角の警告アイコンがある場合は、その問題を解消するまではPWAのインストールボタンが表示されません。
また、EdgeではPWAに対応していないサイトでもPWAとしてインストールすることができます。 PWA化する前にデスクトップアプリとしてどんな感じになるのか確認したいときはEdgeの設定から アプリ>このサイトをアプリとしてインストール することで簡単なお試しができます。