カレンダーをPWA化してみた(インストール編)


はじめに

毎年年末に自宅と会社用に卓上カレンダーを購入していたのですが、前々から置く場所も取るし、お金もかかるので「PC上で確認できればなぁ…」という思いがありました。

まっさきに思い浮かんだのが Windows 10 に標準搭載されている「カレンダー」アプリ。
しかし、とっても見づらい…
フリーソフトも探してみましたがいいのが見つからず…
Google カレンダーは高機能すぎて逆に見づらい…

無いならば、自分で作ろう、カレンダー。

というわけで、カレンダーをPWA(Progressive Web Apps)化し、インストール可能にしてみました。

作成したものは以下より確認できます。

祝日付きカレンダー

Webページ化

まずはWebページとして見れるようにしましょう!
JavaScript を利用して動的に表示するようにします。

JavaScript

カレンダーの JavaScript については以下を参考にさせていただきました。
とってもわかりやすい記事ありがとうございます。

JavaScriptでカレンダーを自作したら勉強になった

祝日の実装

祝日については以下 API から取得させていただきました。

Holidays JP API

PWA(Progressive Web Apps)化してインストール可能にする

ウェブサイトをインストール可能にするには、以下のものが必要になります。

  • HTTPS で提供されているウェブサイト
  • 正しくフィールドが入力されたウェブマニフェスト
  • アイコン
  • 登録された Service Worker

ファイル構成例

必要最低限のファイル構成は以下となります。

└─ root
  ├─ index.html
  ├─ service-worker.js
  ├─ manifest.json
  ├─ icon-192.png
  └─ icon-512.png

index.html

  • <head> 内にある <link> 要素で manifest.json ファイルを読み込む
  • JavaScript で ServiceWorker である service-worker.js ファイルを登録する
  • スコープは navigator.serviceWorker.register() の第二引数(省略可能)として指定できる
index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>インストール可能なウェブサイト</title>
    <link rel="manifest" href="manifest.json">
  </head>

  <body>
    <script>
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker
        .register('service-worker.js', {scope: "/"})
        // 登録成功
        .then((registration) => {
          console.log(
            'ServiceWorker の登録に成功しました。スコープ: ',
            registration.scope,
          )
          registration.onupdatefound = () => {
            registration.update()
          }
        })
        // 登録失敗
        .catch((err) => {
          console.log('ServiceWorker の登録に失敗しました。', err)
        })
    }
    </script>
  </body>
</html>

manifest.json

アプリの情報を記述します。
以下サイトで簡単に作成できます。

Web App Manifest Generator

  • name : アプリの正式な名前
  • short_name : ホーム画面に表示するアプリの省略した名前
  • description : アプリの説明文
  • lang : nameshort_name で使用する言語を指定
  • start_url : アプリの起動時に最初に読み込まれる URL
  • scope : アプリコンテキストの範囲を定義
  • display : アプリの表示方法
    • fullscreen : 全画面表示
    • standalone : ブラウザの UI を非表示
    • minimal-ui : 最小限の UI を表示(ブラウザによって UI は異なる)
    • browser : ブラウザの UI をそのまま表示
  • orientation : 画面の縦方向、横方向の向きを定義
    • any : すべての向きに対して回転を許可
    • natural : screen.orientation.angle が 0 (正面) になる向きに固定
    • landscape : landscape-primary, landscape-secondary の省略形
    • landscape-primary : 縦長が正面の端末で縦方向に固定
    • landscape-secondary : 横長が正面の端末で縦方向に固定
    • portrait : portrait-primary, portrait-secondary の省略形
    • portrait-primary : 横長が正面の端末で横方向に固定
    • portrait-secondary : 縦長が正面の端末で横方向に固定
  • theme_color : オペレーティングシステムで使用される UI の基本色
  • icons : アイコン情報
  • background_color : アプリの既定の背景色(インストール中およびスプラッシュ画面で利用)
manifest.json
{
  "name": "アプリの正式な名前",
  "short_name": "ホーム画面に表示するアプリの省略した名前",
  "description": "アプリの説明文",
  "lang": "ja",
  "start_url": "index.html",
  "scope": "/",
  "display": "standalone",
  "theme_color": "#fff",
  "icons": [
    {
      "src": "icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "background_color": "#fff"
}

service-worker.js

Service Worker の処理を記述する JavaScript ファイル。
インストール可能にするだけであれば記述は空で大丈夫です。
ただし、 Android で Mini-infobar と呼ばれるインストールを促すバナーを表示させるためには fetch イベントを登録する必要があります。

service-worker.js
self.addEventListener('fetch', (e) => {
  // ここは空でOK
})

icon.png

manifest.json 内で指定するアイコンファイル。

いろいろなサイズのアイコン画像を設定できますが、最低限以下のサイズのアイコン画像が必要なようです。

  • 192 x 192
  • 512 x 512

インストールする(Chrome)

PWA化したページを表示すると、アドレスバーにインストールするためのアイコンが表示されます。

クリックするとインストールするか聞いてきます。

インストールするとデスクトップにショートカットアイコンが作成されます。

ブックマークバー上の「アプリ」をクリックするか、アドレスバーに chrome://apps と入力するとアプリ一覧が表示されます。
アプリが登録されているのが確認できます。

デスクトップのアイコンをクリックするとアプリが起動します。

アプリの削除はアプリ一覧画面から行うことができます。

おわりに

今まで PWA は iPhone のホーム画面に登録し、アプリっぽく表示できるものと思っていました。
PCでもアプリのように利用できるとは知らなかった…
ブラウザを起動しなくても起動できるなんてめっちゃ便利!

次はオフライン対応を実装してみようと思います。