はじめに
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の設定ができます。
それぞれの設定はこの後のManifest
、ServiceWorkerの登録
で説明します。
Manifest
では、vite.config.ts
を編集してManifestを設定します。
buildした時に、Mnifestのjsonファイルをvite.config.ts
の設定を元に作成してくれます。
また、index.htmlにも追加してくれます。
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を内部的に入っているので、こちらのプラグインで登録をしていきます。
今回は、injectRegister
をauto
で設定しデフォルトのServiceWorkerを登録します。
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>
を追加することで手動登録ができます。
<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の処理の例は以下となります。
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通知機能も作成していました。
作成したアプリは以下です。
簡単な実装説明
Push通知についてはOneSignalを利用して作成しました。
通知機能は独自実装だと難しいですが、こちらのサービスを利用すると簡単に始めれます。
また、SDKをダウンロードして、数行のコードを記載するだけでOKです。
OneSignalのパッケージも準備されています。
npm install -D react-onesignal
実装資料
※Github pagesはhttps://アカウント.github.io/プロジェクト名
で公開されます。
OneSignalはドメイン名までの登録となるので、別で準備が必要です。
私は、別途AWS S3 + CloudFrontで実装しました。
終わり
今後のPWAとしてはWebで様々なAPIが増えて行きます。現在も日々進化しています。
特にProjectFugu
という取り組みが行われており、ネイティブアプリとのギャップが徐々に埋まっていくと思われます。
現在のProjectFugu
の開発状況はFugu API Trackerで管理されています。
また、近年XR技術が話題になっています。
今年はMeta Quest3が発売され、来年にはApple Vision Proが発売されます。
XRにより、今後あらたなWeb体験が増えていく思われます。
わたし個人としてPWAがどのようにアプローチしていくのかとても楽しみです。