LoginSignup
13
9

More than 1 year has passed since last update.

[React] 途中から既存アプリをPWA対応したくなった時 [なるべくコピペで]

Last updated at Posted at 2022-03-01

はじめに

この記事では,Reactアプリ開発を開始して,割と時間はたったけど「やっぱりこのアプリPWA対応したくなったな」って方に向けた記事です.

筆者の環境

WSL: Ubuntu-20.04
npm: 6.14.13
ブラウザ: Google Chrome

もくじ

前提

  1. npx create-react-app app-nameでプロジェクトを始めた人
  2. アプリ開発を開始して少し時間たったけど,やっぱりPWA対応したくなった人
  3. 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

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

public/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

src/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
スクリーンショット 2022-03-01 154514.png スクリーンショット 2022-03-01 154447.png

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に追記していきます.

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",
// -- ここから追加 --
    "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対応用に書き換えます.

src/index.js
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の中身
スクリーンショット 2022-03-01 162748.png スクリーンショット 2022-03-01 154447.png

manifest.json内のiconsの配列内をコピペしてきます.
192x192にはAndroidのインストール時に使用されるマスカブルアイコンの設定として,"purpose": "maskable"を追加しておきます.

既に使用したいアイコンファイルがあって,全サイズ独自に用意された方は,適宜ファイル名を読み替えてください.

src/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": "/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"
}

そして,既存のアイコンファイルを削除し,新たに生成されたものをコピーします.

既存の状態 追加しなおした状態
スクリーンショット 2022-03-01 164014.png スクリーンショット 2022-03-01 164021.png

server.jsを作成

PWAを行うためには,Reactアプリをビルドして何らかの形でホスティングします.
今回は,NodeJSではおなじみのExpressを使用していきます.
参考:Deploy ReactJs Progressive Webapp On Heroku

コンソール
npm install express
touch server.js
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という呼び出しに書き換えました.

package.json
{
// ※ 省略
  "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/ もしくは,ご自身で設定されているアプリのパスへアクセスしてください.

私の場合以下のようになりました.

スクリーンショット 2022-03-01 175227.png

この黄色で囲っている部分ですが,PWAに対応した場合,これらが追加されるかと思います(Google Chromeなら).
PCであればここをクリックすることで,手元のPCにローカルホスト版のPWAアプリケーションがインストールされると思います.

一応,lighthouseで確認してみましょう.

スクリーンショット 2022-03-01 181620.png

これで,PWA対応の完了です.

インストールして起動

インストールすると,デスクトップにアイコンが追加されると思います.

そちらを開くとこんな具合に,PWAのアプリケーションとして開くことができます.

スクリーンショット 2022-03-01 184314.png

画面上部に邪魔なURL欄などなく,あたかもネイティブアプリケーションかのようにふるまってくれます.

クラウドなどにデプロイしておけば,スマホに追加することもできます.

PWAアプリのアンインストール

一応アンインストール方法を紹介しておきます.
画面上部の三点リーダーをクリックすると,「{app-name}をアンインストール」という項目が出るので,それをクリックするだけです.

スクリーンショット 2022-03-01 185204.png

おわりに

皆様はうまくいきましたでしょうか?

はじめはPWA対応する予定がなく,後からというシチュエーションは割とあるかと思います.

そんな方の一助になればと思います.

それでは:wave:

参考記事

13
9
1

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
13
9