Vue 3 + Vuetify 3で作成したWebアプリをPWAに対応させる

これはなに Link to this heading

Vue 3 + Vuetify 3で作成したWebアプリをPWA(Progressive Web Apps)に対応させる方法のまとめ。

環境 Link to this heading

  • Vue 3.2.45
  • Vuetify 3.1.1
  • TypeScript 4.9.4
  • Vue Router 4.1.6
  • Vite 3.2.5
  • vite-plugin-pwa 0.14.1

方法 Link to this heading

パッケージをインストールする Link to this heading

vite-plugin-pwa をインストールする。

yarn add vite-plugin-pwa -D

VitePWAをプラグインとして追加する Link to this heading

vite.config.tsを編集する。

vite.config.ts
+ import { VitePWA } from 'vite-plugin-pwa'

export default defineConfig({
  plugins: [
    vue({
      template: { transformAssetUrls },
    }),
    vuetify({
      autoImport: true,
    }),
+   VitePWA({
+     registerType: 'autoUpdate'
+   })
  ]
})

Service Workerをアプリに登録する Link to this heading

main.tsでService Workerをアプリに追加する。

main.ts
import App from './App.vue';

// Composables
import { createApp } from 'vue';

// Plugins
import { registerPlugins } from '@/plugins';

+ // Register service worker
+ import { registerSW } from 'virtual:pwa-register';
+ registerSW();

const app = createApp(App);

registerPlugins(app);

app.mount('#app');

このとき、TypeScriptだと、“virtual:pwa-register"という名前のモジュールは存在しないというエラーを吐かれる。 これは"virtual:pwa-register"が型として登録されていないために起こる。 よって、tsconfig.jsonで型情報を追加する。

tsconfig.json
{
  "compilerOptions": {
+   "types": [
+     "node",
+     "vite-plugin-pwa/client"
+   ],
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
+   "node_modules/vite-plugin-pwa/client.d.ts"
  ],
}

キャッシュするファイルを指定する。 Link to this heading

PWAでキャッシュさせるデータにico, png, svgなどを含めたい場合は、workboxのglobPatternsに含める必要がある。

vite.config.ts
import { VitePWA } from 'vite-plugin-pwa'
export default defineConfig({
  plugins: [
    VitePWA({
      registerType: 'autoUpdate',
+     workbox: {
+       globPatterns: ['**/*.{js,css,html,ico,png,svg}']
+     }
    })
  ]
})

アイコン画像を用意する Link to this heading

下記に示す画像をすべて用意する。 内容はすべて同じロゴ画像で問題ない。

  • mask-icon.svg
  • favicon.ico
  • 180 × 180 pxのpng画像(apple-touch-iconとして利用する)
  • 192 × 192 pxのpng画像
  • 256 × 256 pxのpng画像
  • 384 × 384 pxのpng画像
  • 512 × 512 pxのpng画像

mask-icon.svgは元のロゴ画像そのままでよい。

260 x 260 pxの画像があれば、 Favicon Generator for perfect icons on all browsers で大体の必要なものは生成できる。

また、512 x 512 pxのpng画像があれば、 PWA Manifest Generator | SimiCart でも192 × 192 px, 256 × 256 px, 384 × 384 pxの画像を生成できる。

favicon.icoはpngファイルからConvertio — ファイルコンバーター でも生成できる。

全ての画像はpublic直下に配置する。

PWAの最低要件を満たさせる Link to this heading

head内に必要情報を追記する Link to this heading

アプリのエントリーポイントとなるファイル(大抵はindex.html)の<head>タグ内に、下記内容を含めなければならない。

  • viewportのmeta情報
  • タイトル
  • 説明
  • favicon
  • apple-touch-iconへのリンク
  • mask-iconへのリンク
  • theme-colorのmeta情報

Favicon Generator for perfect icons on all browsers を使った場合は、<head>タグ内に追記すべき内容も生成されるため、それをコピペすればよい。

最低情報だけ列挙すると下記のようになる。

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Example App</title>
  <meta name="description" content="Example description">
  <link rel="icon" href="/favicon.ico">
  <link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
  <link rel="mask-icon" href="/mask-icon.svg" color="#FFFFFF">
  <meta name="theme-color" content="#ffffff">
</head>

筆者の環境では次のようになった。

index.html
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>FF14 Collections Checker</title>
    <meta
      name="description"
      content="Final Fantasy 14 Collections Checker App"
    />
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
    <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
    <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
    <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5" />
    <meta name="msapplication-TileColor" content="#da532c" />
    <meta name="theme-color" content="#ffffff" />
  </head>

VitePWAの必要事項を設定する Link to this heading

VitePWAの必要事項であるincludeAssetsmanifestをvite.config.tsに定義する。

vite.config.ts
export default defineConfig({
  plugins: [
    VitePWA({
      includeAssets: [
        'favicon.ico',
        'apple-touch-icon.png',
        'mask-icon.svg',
        'robots.txt',
      ],
      manifest: {
        lang: 'ja',
        name: 'Web App Name',
        short_name: 'App Name',
        description: 'Example description',
        theme_color: '#ffffff',
        background_color: '#ffffff',
        display: 'standalone',
        scope: '/',
        start_url: '/',
        icons: [
          {
            src: '/icon-192x192.png',
            sizes: '192x192',
            type: 'image/png',
          },
          {
            src: '/icon-256x256.png',
            sizes: '256x256',
            type: 'image/png',
          },
          {
            src: '/icon-384x384.png',
            sizes: '384x384',
            type: 'image/png',
          },
          {
            src: '/icon-512x512.png',
            sizes: '512x512',
            type: 'image/png',
          },
          {
            src: '/icon-512x512.png',
            sizes: '512x512',
            type: 'image/png',
            purpose: 'any maskable',
          },
        ],
      },
    }),
  ],
});

robots.txtの追加 Link to this heading

検索エンジンがクロールできるようにrobots.txtを追加する。 publicファイル直下にrobots.txtを作成し、下記を記入する。

User-agent: *
Allow: /

ビルドして確認する Link to this heading

確認には、yarn build && yarn previewを実行する。 うまくいくと、リンクの横にダウンロードマークが表示される。

成功例

なお、vite-plugin-pwaによるPWA機能は、本番環境でないと動作しない。 そのため、yarn devでは動作しない。

参考文献・URL Link to this heading

Licensed under CC BY-NC-SA 4.0
最終更新 5月 21, 2023
Hugo で構築されています。
テーマ StackJimmy によって設計されています。