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
PWAとネイティブアプリとウェブサイト
PWAのインストール
qiitaページはPWA入っています。
ChromeでPWA導入確認出来ます
ウェブサイトにPWA導入準備
- manifest.json : アプリアイコン、アプリ名など設定するファイル
- service_worker.js : JSキャッシュ、Push Notificationなど設定ファイル
PWA導入例
RAILS
manifest.json ファイル作成
- routers.rb に追加
...
resources :manifest, only: [:index]
...
- manifest_controller.rb ファイル作成
class ManifestController < ApplicationController
protect_from_forgery except: :index
def index
end
end
- app/views/manifest/index.json.erb ファイル作成
{
"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 に追加
<%# 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 ファイル作成
class ServiceworkerController < ApplicationController
protect_from_forgery except: :index
def index
end
end
- app/views/serviceworker/index.js.erb ファイル追加
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 に追加
<script>
if (navigator.serviceWorker) {
navigator.serviceWorker.register('/serviceworker.js', { scope: './' })
.then(function(reg) {
console.log('[Companion]', 'Service worker registered!');
});
}
</script>
VUEJSに追加
PWAの問題
- Storeにアップロード出来ません
- OSの深い機能に関して、IOSとAndroidは違います。