PWA作成手順

JavaScriptで動きをもたせたWebページは、 PWA(Progressive Web Apps)の形式を整えることで、 スマートフォン上でオフラインでも動作するアプリとして登録できる。

手順のまとめ

以下の手順で作成する。

  1. アイコンファイルを作成する
  2. 表示と実行必要なファイルをすべて一覧化する
  3. ServiceWorker となるjsファイルを作成する
  4. ServiceWorker をロードする記述を主要jsファイルに追加する
  5. manifestファイルを作成する

アイコンファイルの作成

アプリ起動時のためのアイコンを作成する。通常複数のサイズで作成するが、 最低限192x192の物を用意する。この例では ./img/appicon-192.png のファイル名で配置するものとする。

ブラウザのアドレスバー等に表示されるiconファイルも作成しておくとよい。

convert -resize 32x32 img/appicon-192.png img/favicon.ico

ファイルの一覧化

主要なHTMLファイルと、そこから呼び出しているCSSファイル、 JavaScriptソースファイル、画像ファイルをもれなく列挙し、 以下で作成する serviceworker.js 内の配列変数に代入する。

serviceworker.jsの作成

以下のようなほぼ決まった内容で serviceworker.js を作成する。 最初の2つの変数には

  1. スマートフォンがオフラインのときにキャッシュするときの 目印となるバージョン識別文字列を入れる。アプリ名に 日付やバージョンを含むものにすると便利である。
  2. スマートフォンのストレージにキャッシュすべきファイル名一覧を 相対パスで列挙する。少なくとも、入口となる index.html, 主体となるJavaScriptプログラムファイル、アプリのアイコンファイルは 必要で、その他CSSや利用しているデータファイル画像ファイルなどがあれ ば記述する。

serviceworker.js

var cacheName = 'AnyStringToIdentify-NandemoKandemo';
var filesToCache = [
    './',
    './index.html',
    './main.js',
    './main.css',
    './img/appicon-192.png',
    './img/favicon.ico'
];
self.addEventListener('install', function(event) {
    console.log('ServiceWorker installing');
    event.waitUntil(
	caches.open(cacheName).then(function(cache) {
	    console.log('Service Worker caching app shell');
	    return cache.addAll(filesToCache);
	})
    );
});
self.addEventListener('activate', function(event) {
    console.log('Service Worker activating');
    event.waitUntil(
	caches.keys().then(function(keyList) {
	    return Promise.all(keyList.map(function(key) {
		if (key !== cacheName) {
		    console.log('Service Worker removing old cache', key);
		    return caches.delete(key);
		}
	    }));
	})
    );
    return self.clients.claim();
});
self.addEventListener('fetch', function(event) {
    console.log('Service Worker fetching', event.request.url);
    event.respondWith(
	caches.match(event.request).then(function(response) {
	    return response || fetch(event.request);
	})
    );
});

実行部はほぼ定形なので、先頭部分のキャッシュ識別名と、 キャシュすべきファイル一覧を間違わずに記述する。 作成ファイルを追加したときにこの部分の更新を忘れると悩むことになる。

serviceworker.jsのロード

上の例でメインとなるJavaScriptファイルが main.js だとすると、そこから serviceworker.js をロードする記述を埋め込む。仮に index.html から main.js

<script type="text/javascript" src="main.js"></script>

と読み込んでいるのだとすると、main.js には以下のような記載が必要になる。

document.addEventListener("DOMContentLoaded", ()=>{
  //
  // main.js でやろうとしている処理がここに書いてあるものとする。
  //
  if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('./serviceworker.js')
  	.then(()=> {
  	    console.log('service worker registered'); //なくてもよい
  	});
  }
}, false);

manifest.jsonファイルの作成

アプリケーション登録に必要な情報をJSON形式でファイルに書き込み、 それを主要HTMLファイルのlink要素から取り込む。

  1. manifestファイルの作成

    ファイル名は何でもよいが、一般的には manifest.json として アプリ登録に必要な項目を埋めて作成する。

    manifest.json

    {
        "name": "PWA Sample",
        "short_name": "PWAs",
        "icons": [{
    	"src": "./img/appicon-192.png",
    	"sizes": "192x192",
    	"type": "image/png"
        }],
        "theme_color": "#c0c0c0",
        "background_color": "#ddf",
        "display": "standalone",
        "start_url": "./index.html"
    }
    
    
  2. 主要HTMLからのlink

    上で作成したJSONファイルを呼び出し側のHTML からリンクする。以下のものをhead要素内に追加する。

    <link rel="manifest" href="manifest.json">
    

実例

これまでの手順をまとめ、以下のファイル群をPWA化した例を示す。

ファイル名役割
pwa-sample.html 開始ページ(start_url)
pwa-sample.js 本体jsファイル
pwa-sample.css CSS定義ファイル
pwa-svw.js ServiceWorker定義jsファイル
pwa-manifest.json manifestファイル
img/pwa-sample-192.png アイコンファイル
img/pwa-sample.ico icoファイル
img/A.png データファイルその1
img/B.png データファイルその2

pwa-sample

キャッシュ残存問題

PWAに限らず、スマートフォンのブラウザで見るときには CSSやjsファイルを更新後に単にリロードしても更新前のものが本体に キャッシュされて修正を確認できない。PC用ブラウザの場合はSHIFTを 押しながらリロード(スーパーリロード)することで解決できることがあるが、 それでも効かないときは、ブラウザの履歴消去機能でキャッシュを消さねばならない。

PC用ブラウザやAndroidのChromeでは、ブラウザメニューの履歴から 進むと一定時間のキャッシュをサイトごとに消去できるのでこれを利用する。 iPhoneのSafariではかなり複雑なので 「ios safari キャッシュ 消えない js」 などのキーワードで検索して調べる。

アイコンの作成などのTips

本来アイコンは複数のサイズで使うが、別デザインで作るのが大変なときは、 大きめのサイズ(例えば512x512)で作って、小さい方にリサイズする。 たとえば myicon512x512.png だけ作ったのなら、

convert -reisze 192x192 myicon192x192.png myicon512x512.png
convert -reisze 180x180 myicon180x180.png myicon512x512.png

などのようにconvertでリサイズ変換する。

また、icoファイルはGIMPでエクスポートするときに拡張子を .ico で書き出すと作成できる。