動かざることバグの如し

近づきたいよ 君の理想に

viteで作成したWEBアプリを音速でPWA化する

環境

  • Node.js v22
  • vite 5.3

viteでビルドされるプロジェクト環境が前提となる。

やりたいこと

どっちお得くんというサイトをスマホから使う際、 ネイティブアプリっぽくさせたかったのでPWAを導入することにした。

今回はvite環境なら一発でPWA化できるということでPWA Vite Pluginを使ってみる。

Vite PWA

PWAについて

PWAってのは、Webアプリをネイティブアプリっぽく動かすための技術であり、必要なファイルは主に2つ。service workermanifest.json

service worker (dev-sw.js) は、バックグラウンドで動くスクリプトで、キャッシュやプッシュ通知を制御する。 ブラウザの裏でこっそり動いて、オフラインでも動くようにしたり、アプリっぽい挙動を可能にする。 ネットワークリクエストをインターセプトして、キャッシュからレスポンスを返したり、サーバーにリクエストをフォワードしたりする。 この制御を間違えると、キャッシュが古いままになったり、最悪動かなくなる。

manifest.jsonは、PWAアプリの設定ファイル。 アプリの名前、アイコン、テーマカラー、表示モードなどを記述する。 ブラウザがこれを読んで、PWAをホーム画面に追加するときに使う。 iconsセクションで、さまざまな解像度のアイコンを定義する。 displaystandaloneにすると、ブラウザのUIなしでアプリみたいに表示される。 theme_colorは、アプリのテーマ色だ。これらを設定しないと、PWAとしてインストールできない。

手順

インストール

npm install -D vite-plugin-pwa

vite.config.tsに以下追記

import { VitePWA } from 'vite-plugin-pwa'

export default defineConfig({
  plugins: [
    VitePWA({
      registerType: 'autoUpdate',
      devOptions: {
        enabled: true, // 開発環境でもPWA有効化
      },
    }),
  ],

開発サーバーを起動しChromeデベロッパーツールで「Application」タブ→「Service workers」を開く。

以下のようになっていれば成功。

picture 0

アイコンの準備

Webマニフェストの設定が不十分であるためPWAとしてインストールできない。 色々設定項目があるがそのなかにアイコンを用意しなくてはいけない。なんと6種類!!

面倒すぎると思ったが正方形の画像さえ用意すれば自動生成してくれるツールがあった。

ツールのインストール

npm i @vite-pwa/assets-generator -D

pwa-assets.config.tsを作成して以下 今回はpublic/icon.pngに正方形の画像を用意した。

import { defineConfig } from '@vite-pwa/assets-generator/config'

export default defineConfig({
  images: [
    'public/icon.png'
  ],
})

実行

npx pwa-assets-generator --preset minimal-2023

出力された内容をvite.config.tsに追記しつつ以下のようにする

export default defineConfig({
  plugins: [
    react(),
    vanillaExtractPlugin(),
    VitePWA({
      registerType: 'autoUpdate',
      devOptions: {
        // 開発環境でもPWA有効化
        enabled: true
      },
      manifest: {
        name: 'どっちお得くん',
        short_name: 'どっちお得くん',
        description: '物価上昇を耐え抜け',
        theme_color: '#ffffff',
        display: 'standalone',
        icons: [
          {
            src: 'pwa-64x64.png',
            sizes: '64x64',
            type: 'image/png'
          },
          {
            src: 'pwa-192x192.png',
            sizes: '192x192',
            type: 'image/png'
          },
          {
            src: 'pwa-512x512.png',
            sizes: '512x512',
            type: 'image/png'
          },
          {
            src: 'maskable-icon-512x512.png',
            sizes: '512x512',
            type: 'image/png',
            purpose: 'maskable'
          }
        ]
      }
    })
  ]
});

参考URL