16
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ReactAdvent Calendar 2023

Day 22

React + vite によるPWAアプリ

Last updated at Posted at 2023-12-21

はじめに

12月に社内で技術交流会が開催されました。
私も参加し、15分程度発表をさせて頂きました。
しかし、準備した発表資料は半分ほどしか発表できず、日の目を浴びることがなかった部分が出てしまいました。



というのも、、、
当初、本記事のタイトルの通りReact + vite によるPWAアプリについて発表しようと思っていました。
せっせとサンプルアプリ構築を済ませ、発表資料を作成していたのですが、、、
若手であったり、PWAを知らない人もいるだろうな思い。
PWAとは何なのかを説明する資料を準備しました。
結構まじめにPWAについて資料を準備したせいで、発表はPWAについての説明までしか出来ませんでした。
サンプルアプリについての説明は当日は触り程度しか実施しませんでした。



ですので、日の目を浴びることが出来なかった本記事のタイトルとなっているReact + vite によるPWAアプリについて記載しようと思います。
また、npx create-react-app my-appで作成するReact環境とは違いデフォルトでマニュフェストファイルが作成されず、pwa-vite-pluginパッケージを利用する必要があった為、備忘録としても記載したいと思います。

ちなみに、ちょうどアドベントカレンダー期間だったのもあり、、、
急遽探して、参加させていただいました!!
本記事は React Advent Calendar 2023の22日目となります!!

本題

というわけで、本題のReact + viteによるPWAアプリを作成していきます。

作成したアプリ

10秒間で何回タップできるか?というアプリです。
アプリ自体は以下のGithubサンプル(PWA Nightコミュニティーで紹介されていました)を真似して作成しました。
参考にさせて頂いたサンプル(Github)です。
こちらをReact+viteで置き換えました。

環境

開発エディター: Visual Studio Code
node: LTS(※18+、20+以上のバージョンが必要です。)
npm: LTS
PWAアプリ構築に必要なnodemodule: vite-plugin-pwa
公開用Webpage: Github pagesを利用

React+vite の環境作成

環境作成については以下を参考にしました。
viteでReact×TypeScript環境を爆速で作る最小版
今回はPWAのサンプルアプリ作成が趣旨なので、ESLint, Prettier導入 CSSライブラリ導入はしていません。
また、viteの公式ドキュメントはこちら

初回に作成したReact+vite環境で、不要なファイルについては以下の対応を実施
・index.cssは不要なので読み込まれないように設定
・初期のApp.tsxのコードは作り替えます
・初回で作成した環境でpublicディレクトに存在していた不要な画像、svgファイル削除

10秒間のサンプルアプリを実装

App.tsxに実装し、該当のデザインはApp.cssに作成。
ここは、PWAの趣旨とは違うので以下のGithubを確認ください。
ソースコード

PWAの実装

アイコンの作成

私はmac端末でしたのでKeyNoteで適当にアイコンの元画像を作成しました。
作成した画像を、PWA Manifest Generator等のサービスを利用してアイコンを作成していきます。
※その他サービスではpwabuilderがあります。
アイコンは以下のサイズを準備します。

  • 180×180 // ファイル名の例:apple-touch-icon.png
  • 192×192 // ファイル名の例:pwa-192×192.png
  • 256×256 // ファイル名の例:pwa-256×256.png
  • 384×384 // ファイル名の例:pwa-384×384.png
  • 512×512 // ファイル名の例:pwa-512×512.png
  • favicon.ico

apple-touch-icon.png は作成済のロゴのsvgファイルからInkscapeにて180×180サイズで作ります。
基本デバイスごとで上記のサイズを準備する必要がありますが、今回私は「apple-touch-icon.png」「pwa-192×192.png」「pwa-512×512.png」のみ準備しました。
作成したアイコンについてはpublicディレクトに配置します。

vite-plugin-pwaのインストール

vite にはManifestの設定やServiceWorkerの登録するためのプラグインが準備されています。
以下でパッケージをインストールをします。

npm install vite-plugin-pwa -D

また、インストールが終わったら、vite.config.tsを編集します。
vite.config.tsの編集でManifestの設定や、デフォルトのServiceWorkerの設定ができます。
それぞれの設定はこの後のManifestServiceWorkerの登録で説明します。

Manifest

では、vite.config.tsを編集してManifestを設定します。
buildした時に、Mnifestのjsonファイルをvite.config.tsの設定を元に作成してくれます。
また、index.htmlにも追加してくれます。

vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import {  VitePWA } from 'vite-plugin-pwa' // 追加

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    // ★★★以下を追加★★★
    VitePWA({
      registerType: 'autoUpdate',
      includeAssets: ['favicon.ico', 'apple-touch-icon.png'],
      manifest: {
        name: 'PWA Sample Apps',
        short_name: 'PWAApps', 
        description: 'PWAサンプルアプリ',
        theme_color: '#ffffff',
        icons: [
          {
            src: 'pwa-192x192.png',
            sizes: '192x192',
            type: 'image/png'
          },
          {
            src: 'pwa-512x512.png',
            sizes: '512x512',
            type: 'image/png'
          },
          {
            src: 'pwa-512x512.png',
            sizes: '512x512',
            type: 'image/png',
            purpose: 'any'
          },
          {
            src: 'pwa-512x512.png',
            sizes: '512x512',
            type: 'image/png',
            purpose: 'maskable'
          }
        ]
      }
    })
    // ★★★ここまで!!★★★
  ],
})

ServiceWorkerの登録

ServiceWorkerは直接スクリプトを書くと大変です。
ですので、基本はWorkboxを利用します。
インストールしたvite-plugin-pwaにはWorkboxを内部的に入っているので、こちらのプラグインで登録をしていきます。
今回は、injectRegisterautoで設定しデフォルトのServiceWorkerを登録します。
vite.config.tsに以下を追加します。

vite.config.ts
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    VitePWA({ 
      registerType: 'autoUpdate',
      includeAssets: ['favicon.ico', 'apple-touch-icon.png'],
      injectRegister: 'auto', // 追加
      manifest: {
       ...省略
      }
    })
  ],
})

autoの設定をすると、自動でServiceWorkerのjsファイルがbuildをした段階で作成されます。
また、手動で設定したい場合は、injectRegisterにinline等を設定することで可能です。
他にはscript等の設定があります。
詳しくはServiceWorkerの登録を参照。
そして、以下のindex.htmlに<script>を追加することで手動登録ができます。

index.html
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
    <!-- PWA -->
    <script>
      if ('serviceWorker' in navigator) {
        window.addEventListener('load', () => {
          navigator.serviceWorker
            .register('./serviceWorker.js')
            .then((reg) => console.log('サービスワーカーの登録成功', reg.scope))
            .catch((err) => console.log('サービスワーカーの登録失敗', err));
        });
      }
    </script>
  </body>

そして、ここでindex.htmlで設定している'./serviceWorker.js'をpubulicディレクトに作成をします。
作成するServiceWorkerの処理の例は以下となります。

serviceWorker.js
const CACHE_NAME = 'version-1';
const urlsToCache = ['index.html', 'offline.html'];

// Install SW
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => {
      console.log('Opened cache');
      return cache.addAll(urlsToCache);
    })
  );
});

// Listen for requests
self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request).then(() => {
      return fetch(event.request).catch(() => caches.match('offline.html'));
    })
  );
});

// Activate the SW
self.addEventListener('activate', (event) => {
  const casheWhitelist = [];
  casheWhitelist.push(CACHE_NAME);

  event.waitUntil(
    caches.keys().then((casheNames) =>
      Promise.all(
        casheNames.map((casheName) => {
          if (!casheWhitelist.includes(casheName)) {
            return cashes.delete(casheName);
          }
        })
      )
    )
  );
});

ただ今回はinjectRegisterはautoで設定とします。injectRegister: 'auto'の追加だけOKです。
また、vite-plugin-pwaによるプリキャッシュの設定も可能みたいです。
プリキャッシュの設定
以上でPWAアプリの作成は完了となります。

余談

今回はPush通知機能も作成していました。
作成したアプリは以下です。

image.png

簡単な実装説明

Push通知についてはOneSignalを利用して作成しました。
通知機能は独自実装だと難しいですが、こちらのサービスを利用すると簡単に始めれます。
また、SDKをダウンロードして、数行のコードを記載するだけでOKです。

OneSignalのパッケージも準備されています。

 npm install -D react-onesignal

実装資料

※Github pagesはhttps://アカウント.github.io/プロジェクト名で公開されます。
OneSignalはドメイン名までの登録となるので、別で準備が必要です。
私は、別途AWS S3 + CloudFrontで実装しました。
image.png

image.png

終わり

今後のPWAとしてはWebで様々なAPIが増えて行きます。現在も日々進化しています。
特にProjectFuguという取り組みが行われており、ネイティブアプリとのギャップが徐々に埋まっていくと思われます。
現在のProjectFuguの開発状況はFugu API Trackerで管理されています。
また、近年XR技術が話題になっています。
今年はMeta Quest3が発売され、来年にはApple Vision Proが発売されます。
XRにより、今後あらたなWeb体験が増えていく思われます。
わたし個人としてPWAがどのようにアプローチしていくのかとても楽しみです。

16
7
0

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
16
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?