54
47

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PWAAdvent Calendar 2018

Day 14

workbox + webpackでServiceWorkerを使いPWA化してみた

Last updated at Posted at 2018-09-26

PWAとは

Googleの記事によると、

プログレッシブ ウェブアプリはウェブとアプリの両方の利点を兼ね備えたアプリです。ブラウザのタブで表示してすぐに利用することができ、インストールの必要はありません。使い続けてユーザーとの関係性が構築されていくにつれ、より強力なアプリとなります。不安定なネットワークでも迅速に起動し、関連性の高いプッシュ通知を送信することができます。また、ホーム画面にアイコンを表示することができ、トップレベルの全画面表示で読み込むことができます。

つまり、ネイティブアプリのような機能(プッシュ通知やホーム画面にアイコンを表示など)を提供しながらも、通常のWebページ同様ブラウザでアクセスできるアプリケーション

特徴

Googleが提示するPWAの特徴

特徴 必要なもの
オフラインでの動作 ServiceWorker
プッシュ通知 ServiceWorker
ホーム画面追加 Web App Manifest

対応状況(2018/09/20)

Can I Use

ServiceWorker

スクリーンショット 2018-09-20 11.29.06.png

Web App Manifest

スクリーンショット 2018-09-20 11.29.33.png

実現したこと

  • ServiceWorkerを有効に
  • manifest.jsonを設置
  • HTTPS対応

ServiceWorkerを有効に

workbox-sw + webpackで実現

workbox

workbox.png

  • Google製ServiceWorkerのコードを生成を支援してくれるライブラリ

#####インストール

npm install --save-dev workbox-sw

# webpackでworkboxを使うためにプラグインもインストール
npm install --save-dev workbox-webpack-plugin
webpack
webpack.config.js
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
const dist = __dirname + '/dist'

// webpack config
{
  plugins: [
    // Other webpack plugins...
    new WorkboxWebpackPlugin.GenerateSW({
      globDirectory: dist,
      globPatterns: ['*.{html,js,css}', 'images/**/*.{jpg,jpeg,png,gif,webp,svg}'],
      swDest: dist + '/sw.js',
      clientsClaim: true,
      skipWaiting: true,
    }),
  ]
}
インストールしたworkbox-webpack-pluginをimportし、以下のオプションを設定
  • globDirectory: precache対象とするディレクトリ
  • globPatterns: precache対象とするファイルのパターン
  • swDest: workboxが生成するServiceWorkerのファイルのパス
  • clientsClaim: 最新のサービスワーカーに、アクティブになるとすぐにすべてのクライアントを制御するよう指示
  • skipWaiting: 待機フェーズに入ると最新のServiceWorkerにアクティベーションを指示

ここまではprecacheの設定で、静的なコンテンツを事前にキャッシュさせることができる

runtimeCachingの設定を追加

動的コンテンツはruntimeCachingを行う

GoogleAPIのURLにマッチするurlPatternのときにapiというnameで3日間100件までのデータをキャッシュする例(ステータスコード200の場合のみ)

webpack.config.js
    new WorkboxWebpackPlugin.GenerateSW({
      globDirectory: dist,
      globPatterns: ['*.{html,js,css}', 'images/**/*.{jpg,jpeg,png,gif,webp,svg}'],
      swDest: dist + '/sw.js',
      clientsClaim: true,
      skipWaiting: true,
      runtimeCaching: [
        {
          urlPattern: new RegExp('/'),
          handler: 'staleWhileRevalidate',
        },
        {
          urlPattern: new RegExp('https://www.googleapis.com/'),
          handler: 'cacheFirst',
          options: {
            cacheName: 'api',
            expiration: {
              maxEntries: 100,
              maxAgeSeconds: 72 * 60 * 60
            },
            cacheableResponse: { statuses: [0, 200] },
          }
        },
      ],
    }),
ServiceWorkerを登録
src/index.js
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('./sw.js')
  })
}

manifest.jsonを設置

  • ホーム画面などにWebアプリやサイトを表示する方法を制御し、ユーザが起動できる対象や起動時の見た目(スプラッシュ画面など)を指定できる

manifest.jsonを作成

  • manifest.jsonジェネレータ
    • 512×512の画像をUploadするだけで必要な大きさの画像ファイルをまとめてzipにしてくれるのが便利
  • 192×192のpngアイコンが登録されていないと、Chrome for Androidでホーム画面に追加バナーが表示されない
manifest.json
{
  "name": "test app",
  "short_name": "test app",
  "theme_color": "#3f51b5",
  "background_color": "#ffea00",
  "display": "standalone",
  "Scope": "/",
  "start_url": "/?utm_source=homescreen",
  "icons": [
    {
      "src": "./assets/img/icons/icon-72x72.png",
      "sizes": "72x72",
      "type": "image/png"
    },
    {
      "src": "./assets/img/icons/icon-96x96.png",
      "sizes": "96x96",
      "type": "image/png"
    },
    {
      "src": "./assets/img/icons/icon-128x128.png",
      "sizes": "128x128",
      "type": "image/png"
    },
    {
      "src": "./assets/img/icons/icon-144x144.png",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "./assets/img/icons/icon-152x152.png",
      "sizes": "152x152",
      "type": "image/png"
    },
    {
      "src": "./assets/img/icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "./assets/img/icons/icon-384x384.png",
      "sizes": "384x384",
      "type": "image/png"
    },
    {
      "src": "./assets/img/icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "splash_pages": null
}
  • name, short_nameは必須
  • "display": "standalone"でChromeからアドレスバーがなくなりネイティブっぽくなる
  • "start_url"でホーム画面から飛んだときのパラメーターなど設定できる

htmlで読み込み

<head></head>の中で読み込む

src/index.html
<link rel="manifest" href="/manifest.json">

HTTPS対応

ServiceWorkerを有効にする条件としてHTTPSに対応していなければならない

Netlifyでdeployする

Netlify
スクリーンショット 2018-09-26 14.03.57.png

  • 無料でhttpsでのdeployに対応している
  • Github, GitLab, Bitbucketなどからのdeployが可能

参考:高機能ホスティングサービスNetlifyについて調べて使ってみた

おわりに

  • workboxを使うことでServiceWorker対応を、Netlifyを使うことでhttps化を手軽に行うことができた
  • workboxはwebpushには未対応のためpush通知を利用したければ自分でロジックを書きworkboxで生成されたコードとマージしなければならない

参考
PWA(Progressive Web Apps)と戯れてみる
[ServiceWorkerを簡単に書けるworkbox-swの使い方]
(https://qiita.com/nazonohito51/items/32b61cabdac8b24769bd)

54
47
1

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
54
47

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?