LoginSignup
13

More than 3 years have passed since last update.

一番シンプルなPWAを作ってみよう

Last updated at Posted at 2019-10-14

一番シンプルなPWAを作ってみよう

PWAってなに?

PWAというのはProgressive Web Appの略で、ほげほげ・・・以下略。
コレを読んでる人はそこはもうええわ、って感じですよね笑。実践だけしていきます。

今回のゴール

とりあえずPWAの要件を満たす最低限のHelloWorldアプリケーションを作ります。
シンプルにPWAの条件と実装方法を理解することだけを目的とします。条件は以下の通りです。

  • ライブラリ使わない
  • フレームワークも使わない
  • 全部自前で実装

ちなみにここで作るアプリはMediumを見ながら作ったものであり、自分のアイデアではありません。
Medium記事を書いてくださった作者様には感謝しています!

実践

セットアップ

以下、フォルダ構成になります。任意の場所にこのフォルダ構成を作ります。

/HELLO-PWA    # Project root
    /css      # StyleSheets
    /images   # Image files
    /js       # JavaScripts

まずは画面を作ってみる

PWAを意識したHTMLを書く必要があります。最低限、以下の2点に留意すれば良いようです。

  1. JavaScriptが無効化されている場合でも画面が表示できるよう配慮する!これを守ることで回線状況が悪い場合や古いブラウザからアクセスされた場合も真っ白な画面を表示してしまうことだけは避ける可能性が高くなります。
  2. レスポンシブな画面としていろんなデバイスからアクセスされる可能性がある点に留意しましょう。モバイルフレンドリーであれ、ということだそうです。

最低限の対応として、いつもの viewport metaタグを利用しましょう。Project rootフォルダにindex.htmlを作ります。

index.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Hello World</title>
  <link rel="stylesheet" href="css/style.css">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
<body class="fullscreen">
  <div class="container">
    <h1 class="title">Hello World!</h1>
  </div>
</body>
</html>

CSSも格納します。

css/style.css
body {
  font-family: sans-serif;
}

/* コンテンツがブラウザのウインドウを100%使うようにしましょう */
html,
.fullscreen {
  display: flex;
  height: 100%;
  margin: 0;
  padding: 0;
  width: 100%;
}

/* コンテンツは画面の中央に来るようにね*/
.container {
  margin: auto;
  text-align: center;
}

.title {
  font-size: 3rem;
}

ここで一度、ブラウザで開いてみましょう。ちなみに私はVisual Studio Code + Go Liveの組み合わせです。
Screen Shot 2019-10-14 at 18.54.01.png
表示されましたね。ただ、これではPWAとは言えません。自信を持ってPWAと言えるようになるためには何をすれば良いのでしょう?

どのくらいPWA化出来ているかを評価しよう

Google謹製のChrome拡張「Lighthouse」を導入するとWebページのいろいろな評価ができます。これを使ってこのアプリがどの程度PWA化出来ているのか、計測していきましょう。
Screen Shot 2019-10-14 at 18.55.27.png

F12の開発者コンソールにAuditsタブが追加されているのがわかりますね。画面内に「Progressive Web App」チェックボックスがあるのが見えると思います。このチェックを入れることで、PWA化出来ているか、計測してくれます!スゴイですよね。画面下部に「Run audits」ボタンがあるので早速押して評価してみましょう。
Screen Shot 2019-10-14 at 18.56.30.png
なんとなく、全くPWAじゃねーし!って言われてる感じですね笑。下の方にスクロールすると以下のように丁寧に評価ポイントを示してくれています。これを緑にしていけば、PWA度合いが上がっていくわけですね!
Screen Shot 2019-10-14 at 18.58.46.png

PWA化しよう!

ServiceWorkerを追加しよう

PWAといえばServiceWorker笑。知らない人のために1行で説明すると、「バックグラウンドで、そのWebページを開いていないときですら、JavaScriptを自動的に実行してくれる機能」です。ServiceWorkerを実装することにより初回アクセス時にJSがダウンロードされ、次回以降は自動的にスクリプトが実行することができるようになります。早速、Project rootにsw.jsを格納します。

sw.js
var cacheName = 'hello-pwa';
var filesToCache = [
  '/',
  '/index.html',
  '/css/style.css',
  '/js/main.js'
];

/* サービスワーカー起動して、コンテンツをキャッシュする */
self.addEventListener('install', function(e) {
  e.waitUntil(
    caches.open(cacheName).then(function(cache) {
      return cache.addAll(filesToCache);
    })
  );
});

/* オフライン時はキャッシュからコンテンツを取得する */
self.addEventListener('fetch', function(e) {
  e.respondWith(
    caches.match(e.request).then(function(response) {
      return response || fetch(e.request);
    })
  );
});

cacheName、filesToCacheの2つの変数が登場しました。読んで字の如し、ですので説明は省略しますがなんとなくそういうことです。次にこのsw.jsを呼び出すためのにJavaScriptを新規作成し、HTMLを修正します。

js/main.js
window.onload = () => {
    'use strict';

    if ('serviceWorker' in navigator) {
      navigator.serviceWorker
               .register('./sw.js');
    }
  }
index.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Hello World</title>
  <link rel="stylesheet" href="css/style.css">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body class="fullscreen">
  <div class="container">
    <h1 class="title">Hello World!</h1>
  </div>
  <script src="js/main.js"></script>
</body>
</html>

これでオフライン対応が完了しました。試しにサーバを止めてからアプリにアクセスしても画面が表示されます。試してみてください。これがServiceWorkerによるCache機能です。(Incognitoモードだとcacheされないので気をつけてくださいね。念の為)

Manifestを追加しよう

Manifestファイル(Json)に、このアプリの挙動や見た目を表現します。最低限の記載をしていきます。Project rootにmanifest.jsonを作成します。

manifest.json
{
    "name": "Hello World",
    "short_name": "Hello",
    "lang": "en-US",
    "start_url": "/index.html",
    "display": "standalone",
    "background_color": "white",
    "theme_color": "white"
}
名前 説明
name アプリの名前。インストール時のpromptに表示されます。
short_name アプリのアイコンに表示されます。
lang デフォルトの利用言語です。
start_url アプリ起動時のURLです。
display アプリのガワの見た目を選択します。nativeっぽくする場合はstandaloneを指定します。
background_color アプリ起動時のスプラッシュスクリーンの色を指定します。
theme_color ツールバー、タスクスイッチャーの色を指定します。

manifestを読み込むようにHTMLも修正しましょう。どのテーマカラーを使うのかはHTML内に改めて記載します。

index.html
<head>
...
<link rel="manifest" href="/manifest.json">
<meta name="theme-color" content="white"/>
...
</head>

アプリのアイコンを用意する

これで最後です。PWAはnativeアプリのようにアイコンをホーム画面に設置されるのが期待値ですので、アプリのアイコンを準備せねばなりません。面倒ですが、Windows, Mac/iPhone, Androidに合わせて最低でも以下の7種類のアイコンファイルを用意する必要があります。

  • 128x128 px
  • 144x133 px
  • 152x152 px
  • 192x192 px
  • 256x256 px
  • 512x512 px
  • 16x16 px (favicon)

適当なイメージを作成したら、manifest.jsonを修正しましょう。short_nameタグの後ろに追加します。

manifest.json
{
    "name": "Hello World",
    "short_name": "Hello",
    "icons": [{
      "src": "images/hello-icon-128.png",
        "sizes": "128x128",
        "type": "image/png"
      }, {
        "src": "images/hello-icon-144.png",
        "sizes": "144x144",
        "type": "image/png"
      }, {
        "src": "images/hello-icon-152.png",
        "sizes": "152x152",
        "type": "image/png"
      }, {
        "src": "images/hello-icon-192.png",
        "sizes": "192x192",
        "type": "image/png"
      }, {
        "src": "images/hello-icon-256.png",
        "sizes": "256x256",
        "type": "image/png"
      }, {
        "src": "images/hello-icon-512.png",
        "sizes": "512x512",
        "type": "image/png"
      }],
    "lang": "en-US",
    "start_url": "/index.html",
    "display": "standalone",
    "background_color": "white",
    "theme_color": "white"
}

最後にHTMLにも色々追加します。

index.html
<head>
...
<link rel="icon" href="favicon.ico" type="image/x-icon" />  
<link rel="apple-touch-icon" href="images/hello-icon-152.png">   
<meta name="theme-color" content="white"/>  
<meta name="apple-mobile-web-app-capable" content="yes">  
<meta name="apple-mobile-web-app-status-bar-style" content="black"> 
<meta name="apple-mobile-web-app-title" content="Hello World"> 
<meta name="msapplication-TileImage" content="images/hello-icon-144.png">  
<meta name="msapplication-TileColor" content="#FFFFFF">
...
</head>

よし!もう一度画面を開いて、Lighthouseで評価してみましょう。
Screen Shot 2019-10-14 at 19.58.54.png
画面上の見た目が変わりましたね!個別のメトリクスを見るとどういう評価でしょうか。
Screen Shot 2019-10-14 at 20.00.31.png
おお!だいぶ緑の評価が増えています。2箇所だけ赤いままですが、これは環境上しょうがないのであきらめましょう。(一つはHTTPSじゃない!っていうのと、もう一つはviewport指定がおかしい!っていう指摘です。viewport指定をとおすにはwindow.innerWidth === window.outerWidthにすればOKだそうです。PCかつローカル環境で動作させているため、ここは許してもらいましょう。これを除けば100点です!!)

まとめ

これで最低限のPWA対応の指針がわかりました。実際のアプリでは何をどうキャッシュするのか、がすごく大切でかつ慎重に設計しなければならないポイントになるかと思います。localStorageはその名の通りローカルにキャッシュされていくため、色々と慎重にしないと思わぬ挙動になることもあるかもしれません。

2019年現在、主要なブラウザはほぼPWA対応がされていますし、Web技術だけでプラットフォームに依存しないネイティブっぽいアプリの実現が可能です。PWA、将来性を感じますし、面白いですね!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13