坂本研のゼミ室

ReactでSPA+PWAを作ってみた

はじめに

あけましておめでとうございます🎍

昨年末熊本で忘年会の幹事をやったのですが、県外から来る土地勘がない人に様々なお知らせをまとめておくシンプルなPWAを作りました。

作ったもの

f:id:TakaShinoda:20191226210111p:plain

  • お店のサイトへのリンク

  • お店へ、現在地からのルートのリンク

  • 最寄りホテルのサイトへのリンク

  • 最寄り駐車場へ、現在地からのルートのリンク

シンプルな機能ですが調べるのは面倒なことをワンタップでできるようにしました

github.com

使ったもの

  • React

  • react-router-dom

  • Material-UI

  • fortawesome

SPA

SPA(Single Page Application)とは、単一のページ内でコンテンツを切り替えるアーキテクチャの名称です。

(参考: SPA(Single Page Application)ってなに?)

PWA

PWA(Progressive Web Apps)とは、モバイル端末でウェブサイトを表示するときに、まるでネイティブアプリのような動作を可能にする仕組みの事です。

(参考:PWA(Progressive Web Apps)とは?メリットと実装事例について | デジ研)

環境構築

  • 以下のバージョンで動作確認しています
$ node -v
v11.10.1
"react": "^16.12.0"
  • Reactの環境構築
npx create-react-app myapp

実装

  • ファイル構成
(略)
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── manifest.json
│   ├── mogura.png
│   ├── robots.txt
│   └── top.png
├── src
│   ├── App.css
│   ├── App.test.js
│   ├── components
│   │   ├── About.jsx
│   │   ├── App.js
│   │   ├── Home.jsx
│   │   ├── Menu.jsx
│   │   └── page404.jsx
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   ├── serviceWorker.js
│   └── setupTests.js
└── yarn.lock

PWA化

こちらの記事を参考にさせていただきました (Reactで触るPWA (Progressive Web App) - Qiita)

  • index.jsの修正

オフラインでもアプリを起動できるようにindex.js下記のように修正する

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(<App />, document.getElementById('root'));
//unregister() を register()に修正する
serviceWorker.register();

アイコンを設定する

  • publicの中にアイコンにしたい画像をいれる (サイズは192×192)

画像のサイズ変更はこのサイトを使用しました => オンラインでJPGを瞬時にサイズ変更

  • publicの中のmanifest.jsonを書き換える
{
  "short_name": "hoge",
  "name": "hoge",
  "icons": [
    {
      "src": "favicon.ico",
      "sizes": "64x64 32x32 24x24 16x16",
      "type": "image/x-icon"
    },
    {
      "src": "top.png",
      "type": "image/png",
      "sizes": "192x192"
    }
  ],
  "start_url": "/",
  "display": "standalone",
  "theme_color": "#c4e4fc",
  "background_color": "#ffffff"
}

今のままだとSafariからは、アイコン画像が表示されない状態なのでpublicの中にあるindex.htmlに以下を追加することでSafariからでもアイコンが表示されるようにする (参考: 初心者がつまづいた、PWAアプリSafari版でホームボタンのアイコンが読み込まれない件 - Qiita)

<!DOCTYPE html>
<html lang="en">
  <head>
    <!--ここの一行を追加する-->
    <link rel="apple-touch-icon" href="./top.png" sizes="192x192"/>
(略)
  • できました

f:id:TakaShinoda:20191228162811p:plain

ルーティング

ルーティングに関してはこの記事を参考にさせていただきました。

react-routerに入門する - Qiita

  • react-router-domをインストールする
npm install --save react-router-dom

現在(2019/12/26)のバージョン

"react-router-dom": "^5.1.2",
  • インポートする
import {BrowserRouter as Router, Link, Route, Switch} from "react-router-dom";
  • リンクを設定する
<Router>
//リンクを<Link to='/'> </Link>で設定する
  <ul>
    <li><Link to='/'>About</Link></li>
    <li><Link to='./About'>About</Link></li>
  </ul>
</Router>
<Router>
  <ul>
    <li><Link to='/'>About</Link></li>
    <li><Link to='./About'>About</Link></li>
  </ul>
  <Switch>
  //component={ここに表示させたいコンポーネント}
    <Route path='/' exact component={Home}/>
    <Route path='/About' exact component={About}/>
    <Route exact component={page404}/>
  </Switch>
</Router>

Routeは前方一致するものがあれば全てのコンポーネントが表示されるため、一致させたくないものにはexactが必要です。

参考記事より

画像の表示

今回は存在しないパスにアクセスされた時に表示するページ(page404.jsx)にこのもぐらの画像を表示してみます。

もぐらはここから => かわいいフリー素材集 いらすとや

https://cdn-ak.f.st-hatena.com/images/fotolife/T/TakaShinoda/20191228/20191228162058.jpg

  • publicの中に表示したい画像を入れる

  • 画像の表示

//<img src="srcフォルダまでのパス" alt="" height="" width="" /> 
<img src="../mogura.png" alt="もぐらの画像" height="280px" />

現在地からのルートのリンクを作る

この機能はGoogle Maps URL を使って作ります。 こちらの記事を参考にさせていただきました => (Google Maps URL 「現在地からのルート」のリンクを作る - Qiita)

  • 座標を使う場合
<a href=https://www.google.com/maps/dir/?api=1&destination=${lat},${lng}>hoge</a>
//例えば: 宮崎駅
<a href=https://www.google.com/maps/dir/?api=1&destination=${31.915713},${131.432221}>宮崎駅</a>
  • 施設名などのキーワードを使う場合
<a href= "https://www.google.com/maps/dir/?api=1&destination=${keyword}" >hoge</a>
//例えば: 宮崎駅
<a href= "https://www.google.com/maps/dir/?api=1&destination=${宮崎駅}" >宮崎駅</a>

参考記事