はじめに
この記事では,React
アプリ開発を開始して,割と時間はたったけど「やっぱりこのアプリPWA対応したくなったな」って方に向けた記事です.
筆者の環境
WSL: Ubuntu-20.04
npm: 6.14.13
ブラウザ: Google Chrome
もくじ
前提
-
npx create-react-app app-name
でプロジェクトを始めた人 - アプリ開発を開始して少し時間たったけど,やっぱり
PWA
対応したくなった人 - PWAとは何か知っている人
最初からPWA対応を視野に入れている方は,
# Javascriptなら
npx create-react-app app-name --template cra-template-pwa
# Typescriptなら
npx create-react-app app-name --template cra-template-pwa-typescript
でPWA対応のReactアプリケーションのひな型で開発を始められます.
今回は,仮にqiita
というReact(js)アプリの開発が既に進んでいるとして,このアプリをpwa対応していきます.
現状確認
今回書き換えを行うファイルの現状を確認していきます.
※あくまで例なので,注目すべきは完成後との差分です.
ディレクトリ構成
qiita
├── README.md
├── package-lock.json
├── package.json
├── public/
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
└── src/
├── App.css
├── App.js
├── index.css
├── index.js
└── logo.svg
package.json
{
"name": "qiita",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.3",
"@testing-library/user-event": "^13.5.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "5.0.0",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
manifest.json
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
npm start
lighthouseでPWA対応していないことも確かめました.
localhost | lighthouse |
---|---|
PWA対応していく
なるべくコピペで行えるようにしたいと思います!
常にディレクトリはPWA化したいプロジェクトのルートディレクトリ(qiita/
)とします.
言語はJavaScript
を使用します!
TypeScript
の方は完全なコピペとはいかないかもしれませんが,参考程度に使ってください
PWA対応ひな型を作成する
親ディレクトリに新たにPWA用ひな型に沿ったアプリ作成して、必要なファイルを拝借するための準備を行います.
npx create-react-app ../pwa --template cra-template-pwa
# Typescriptなら
npx create-react-app ../pwa --template cra-template-pwa-typescript
必要ファイルをコピー
ひな型から,ServiceWorkerを拝借します.
cp ../pwa/src/service-worker.js ./src
cp ../pwa/src/serviceWorkerRegistration.js ./src
package.json書き換え
必要なライブラリをdependencies
に追記していきます.
{
"name": "qiita",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.3",
"@testing-library/user-event": "^13.5.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "5.0.0",
"web-vitals": "^2.1.4",
// -- ここから追加 --
"workbox-background-sync": "^5.1.4",
"workbox-broadcast-update": "^5.1.4",
"workbox-cacheable-response": "^5.1.4",
"workbox-core": "^5.1.4",
"workbox-expiration": "^5.1.4",
"workbox-google-analytics": "^5.1.4",
"workbox-navigation-preload": "^5.1.4",
"workbox-precaching": "^5.1.4",
"workbox-range-requests": "^5.1.4",
"workbox-routing": "^5.1.4",
"workbox-strategies": "^5.1.4",
"workbox-streams": "^5.1.4"
// -- ここまで --
},
// ※省略
}
}
インストールします.
npm install
index.jsの書き換え
src/index.js
をPWA対応用に書き換えます.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorkerRegistration from './serviceWorkerRegistration'; // 追加
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
serviceWorkerRegistration.register(); // 追加
manifest.jsonの書き換え
SimiCartなどのmanifest.json
とアイコン画像群を作成してくれるサービスで,簡単にPWA対応用のマニフェストを作成できます.
必要項目を入力して,「GENERATE MANIFEST」ボタンをクリックします.
アイコンには512x512の画像ファイルを入れてください.
すると,zipファイルがダウンロードされ,アイコンのセットとマニフェストが入っています.
SimiCart | zipの中身 |
---|---|
manifest.json内のicons
の配列内をコピペしてきます.
192x192にはAndroidのインストール時に使用されるマスカブルアイコンの設定として,"purpose": "maskable"
を追加しておきます.
既に使用したいアイコンファイルがあって,全サイズ独自に用意された方は,適宜ファイル名を読み替えてください.
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
// -- ここから書き換え --
{
"src": "/icon-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"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"
}
// -- ここまで --
],
"start_url": ".",
"display": "standalone",
"theme_color": "#bd10e0",
"background_color": "#4a90e2"
}
そして,既存のアイコンファイルを削除し,新たに生成されたものをコピーします.
既存の状態 | 追加しなおした状態 |
---|---|
server.jsを作成
PWAを行うためには,Reactアプリをビルドして何らかの形でホスティングします.
今回は,NodeJSではおなじみのExpressを使用していきます.
参考:Deploy ReactJs Progressive Webapp On Heroku
npm install express
touch server.js
const express = require('express');
const path = require('path');
const port = process.env.PORT || 3000;
const app = express();
app.use(express.static(__dirname));
app.use(express.static(path.join(__dirname, 'build')));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(port);
if (port === 3000) {
console.log(`Now hosting at "http://localhost:${port}/"`);
}
ホスティング設定
package.json
を再び書き換えます.
デフォルトのホットリローディングの利く方はnpm run local
という呼び出しに書き換えました.
{
// ※ 省略
"scripts": {
// -- 書き換え --
"start":"node server.js",
"local": "react-scripts start",
// -- ここまで --
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
// ※ 省略
}
}
最終的なディレクトリツリー
qiita
├── README.md
├── build/
├── package-lock.json
├── package.json
├── public/
│ ├── favicon.ico
│ ├── icon-192x192.png
│ ├── icon-256x256.png
│ ├── icon-384x384.png
│ ├── icon-512x512.png
│ ├── index.html
│ ├── manifest.json
│ └── robots.txt
├── server.js
└── src/
├── App.css
├── App.js
├── index.css
├── index.js
├── logo.svg
├── service-worker.js
└── serviceWorkerRegistration.js
PWAを動作確認
まずは,コンソールでビルドとサーバの起動を行います.
npm run build
npm start
そして,http://localhost:3000/ もしくは,ご自身で設定されているアプリのパスへアクセスしてください.
私の場合以下のようになりました.
この黄色で囲っている部分ですが,PWAに対応した場合,これらが追加されるかと思います(Google Chromeなら).
PCであればここをクリックすることで,手元のPCにローカルホスト版のPWAアプリケーションがインストールされると思います.
一応,lighthouseで確認してみましょう.
これで,PWA対応の完了です.
インストールして起動
インストールすると,デスクトップにアイコンが追加されると思います.
そちらを開くとこんな具合に,PWAのアプリケーションとして開くことができます.
画面上部に邪魔なURL欄などなく,あたかもネイティブアプリケーションかのようにふるまってくれます.
クラウドなどにデプロイしておけば,スマホに追加することもできます.
PWAアプリのアンインストール
一応アンインストール方法を紹介しておきます.
画面上部の三点リーダーをクリックすると,「{app-name}をアンインストール」という項目が出るので,それをクリックするだけです.
おわりに
皆様はうまくいきましたでしょうか?
はじめはPWA対応する予定がなく,後からというシチュエーションは割とあるかと思います.
そんな方の一助になればと思います.
それでは