PWAとは、railsにPWA導入、vuejsにPWA導入

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

---

# PWAとネイティブアプリとウェブサイトの違い
## ウェブサイト
- ブラウザーでURLアクセス出来る
- HTML/CSS/WEB Frameworkで開発する
- どの端末でもブラウザーがあれば、アクセス出来る
- OSの深い機能触れません

---

##　アプリ
- OSにサポートしているSDKを使って、アプリを開発する
- OSによって、アプリが違う（Android, IOS, Mac Os, Windows）
- アプリ使えるため、アプリをダウンロードして、インストールして、開けます。　（OSのデフォルトアプリがあります、そのアプリはインストール不要です）
- OSの深い機能触れます
    - オフラインモード
    - I/Oアクセス
    - Push Notification
    - セキュリティー


---

## PWA
- ウェブサイトとアプリの真ん中
- HTML/CSS/WEB Frameworkで開発する（ウェブサイト）
- ブラウザーでURLアクセス出来る （ウェブサイト）
- アプリをインストールして、開けます。（アプリ）
- どの端末でもブラウザーがあれば、アクセス出来る（ウェブサイト）
- OSの深い機能は少しさわれます
    - オフラインモード
    - Push Notification


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318767/14536113-9a81-4a30-9540-fa692b5a704f.png)


---

# PWAとネイティブアプリとウェブサイト

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318767/1e346127-caef-fed9-dc54-fa5eba521825.png)


---

# PWAのインストール
https://qiita.com/

qiitaページはPWA入っています。

---

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318767/1cee359e-816e-8b28-4788-95f2ee1057dd.png)


# ChromeでPWA導入確認出来ます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318767/04f60a7f-bce7-6508-b636-c6e3019b33e6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318767/65c1cb8f-4bc1-b43e-86e5-69ef2d2b152a.png)


---

# ウェブサイトにPWA導入準備
- manifest.json : アプリアイコン、アプリ名など設定するファイル
- service_worker.js : JSキャッシュ、Push Notificationなど設定ファイル

---

# PWA導入例
## RAILS 
### manifest.json ファイル作成
- routers.rb　に追加

``` rb
...
resources :manifest, only: [:index]
...
```

- manifest_controller.rb　ファイル作成

``` rb
class ManifestController < ApplicationController
    protect_from_forgery except: :index
    def index
    end
end
```

- app/views/manifest/index.json.erb ファイル作成

``` json
{
  "name": "PWAテスト",
  "short_name": "PWAテスト",
  "start_url": "/",
  "icons": [
    {
      "src": "icon/android-chrome-192x192.png,
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any maskable"
    }
  ],
  "theme_color": "#000000",
  "background_color": "#FFFFFF",
  "display": "standalone",
  "orientation": "portrait"
}

```

- app/views/layouts/application.html.erb に追加

``` erb

    <%# PWA %>
    <link rel="manifest" href="/manifest.json&nocache=<%= (0...50).map { ('a'..'z').to_a[rand(26)] }.join %>" />
    <link rel="apple-touch-icon" href="icon/android-chrome-192x192.png">
    <meta name="theme-color" content="rgb(125, 212, 32)"/>
    <meta name="apple-mobile-web-app-capable" content="yes">

```

---

### serviceworker.js ファイル作成

- routers.rb　に追加

```
...
resources :serviceworker, only: [:index]
...
```

- serviceworker_controller.rb ファイル作成

``` rb
class ServiceworkerController < ApplicationController
    protect_from_forgery except: :index
    def index
    end
end

```

- app/views/serviceworker/index.js.erb ファイル追加

``` js
var CACHE_VERSION = 'v1';
var CACHE_NAME = CACHE_VERSION + ':sw-cache-';

function onInstall(event) {
  console.log('[Serviceworker]', "Installing!", event);
  event.waitUntil(
    caches.open(CACHE_NAME).then(function prefill(cache) {
      return cache.addAll([

        // make sure serviceworker.js is not required by application.js
        // if you want to reference application.js from here

        '/offline.html',

      ]);
    })
  );
}

function onActivate(event) {
  console.log('[Serviceworker]', "Activating!", event);
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.filter(function(cacheName) {
          // Return true if you want to remove this cache,
          // but remember that caches are shared across
          // the whole origin
          return cacheName.indexOf(CACHE_VERSION) !== 0;
        }).map(function(cacheName) {
          return caches.delete(cacheName);
        })
      );
    })
  );
}

// Borrowed from https://github.com/TalAter/UpUp
function onFetch(event) {
  event.respondWith(
    // try to return untouched request from network first
    fetch(event.request).catch(function() {
      // if it fails, try to return request from the cache
      return caches.match(event.request).then(function(response) {
        if (response) {
          return response;
        }
        // if not found in cache, return default offline content for navigate requests
        if (event.request.mode === 'navigate' ||
          (event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html'))) {
          console.log('[Serviceworker]', "Fetching offline content", event);
          return caches.match('/offline.html');
        }
      })
    })
  );
}

self.addEventListener('install', onInstall);
self.addEventListener('activate', onActivate);
self.addEventListener('fetch', onFetch);

```

- app/views/layouts/application.html.erb に追加

``` erb

    <script>
      if (navigator.serviceWorker) {
        navigator.serviceWorker.register('/serviceworker.js', { scope: './' })
          .then(function(reg) {
            console.log('[Companion]', 'Service worker registered!');
          });
      }
    </script>

```

---

## VUEJSに追加

- めっちゃ簡単
- https://cli.vuejs.org/core-plugins/pwa.html#example-configuration


# PWAの問題 
- Storeにアップロード出来ません
- OSの深い機能に関して、IOSとAndroidは違います。

https://medium.com/@firt/progressive-web-apps-on-ios-are-here-d00430dee3a7#:~:text=With%20iOS%2011.3%2C%20Apple%20has,Web%20Apps%20%E2%80%9D%20(PWAs).&text=This%20App%20is%20a%20PWA,app%20from%20the%20App%20Store.


---
# 以上です。