Vue.js で作った Web アプリを PWA 化してみました
2019-05-23先日作った Web アプリ ココイチ注文料金簡易カリキュレータ を PWA 化した話です。
PWA・・・PWAとは、「Progressive Web Apps」の略称で、モバイル向けWebサイトをGooglePlayストアなどで見かけるスマートフォン向けアプリのように使える仕組みです。 ([PWAとは(Progressive Web Appsとは) | SEO用語集:意味/解説/SEO効果など [SEO HACKS]](https://www.seohacks.net/basic/terms/pwa/))作った経緯や使っているサービスなどについては一つ前の記事を見てください。
概要
最初から PWA 対応したアプリケーションを作る場合は、 Vue CLI でプロジェクトを作る際に Progressive Web App (PWA) Support
にチェックを入れておきます。
そうすると、プロジェクトの作成と同時に必要なファイル (manifest.json, 各サイズのアイコンなど) が作成されます。
今回は既存の Vue アプリケーションを PWA 化するので、 Progressive Web App (PWA) Support
にチェックを入れたときと入れないときとの差分を補う形で対応しました。
ちなみに PWA 化することで出来るようになること (Push 通知やオフラインキャッシュなど) はいろいろあるのですが、今回の目的はとりあえず ホーム画面に追加してネイティブアプリっぽく使えるようにする ことです。
手順
1. 必要なパッケージのインストール
package.json
に追記して、 PWA 化に必要なパッケージをインストールします。
@@ -9,6 +9,7 @@
},
"dependencies": {
"core-js": "^2.6.5",
+ "register-service-worker": "^1.6.2",
"vue": "^2.6.10",
"vue-class-component": "^7.0.2",
"vue-property-decorator": "^8.1.0"
@@ -16,6 +17,7 @@
"devDependencies": {
"@vue/cli-plugin-babel": "^3.7.0",
"@vue/cli-plugin-eslint": "^3.7.0",
+ "@vue/cli-plugin-pwa": "^3.7.0",
"@vue/cli-plugin-typescript": "^3.7.0",
"@vue/cli-service": "^3.7.0",
"@vue/eslint-config-prettier": "^4.0.1",
$ npm install
2. Service Worker を登録する処理の追加
Service Worker を使うことによって Push 通知やオフラインキャッシュなど、よりネイティブアプリに近い動作を実現することが出来ます。 (もしかしたら ホーム画面への追加だけなら必要ない?ちょっとこの辺は)
src
の直下に下記のような registerServiceWorker.ts
を作成します。
/* eslint-disable no-console */
import { register } from "register-service-worker";
if (process.env.NODE_ENV === "production") {
register(`${process.env.BASE_URL}service-worker.js`, {
ready() {
console.log(
"App is being served from cache by a service worker.\n" +
"For more details, visit https://goo.gl/AFskqB"
);
},
registered() {
console.log("Service worker has been registered.");
},
cached() {
console.log("Content has been cached for offline use.");
},
updatefound() {
console.log("New content is downloading.");
},
updated() {
console.log("New content is available; please refresh.");
},
offline() {
console.log(
"No internet connection found. App is running in offline mode."
);
},
error(error) {
console.error("Error during service worker registration:", error);
}
});
}
そして src/main.ts
内で import します。
@@ -1,5 +1,6 @@
import Vue from "vue";
import App from "./App.vue";
+ import "./registerServiceWorker";
Vue.config.productionTip = false;
3. アイコンの作成
PWA 化するとホーム画面やスプラッシュ画像に表示されるアイコン画像が必要になるので、 public/img/icons
配下に下記のアイコン画像を準備します。
public/img/icons
├── android-chrome-192x192.png
├── android-chrome-512x512.png
├── apple-touch-icon-120x120.png
├── apple-touch-icon-152x152.png
├── apple-touch-icon-180x180.png
├── apple-touch-icon-60x60.png
├── apple-touch-icon-76x76.png
├── apple-touch-icon.png
├── favicon-16x16.png
├── favicon-32x32.png
├── msapplication-icon-144x144.png
├── mstile-150x150.png
└── safari-pinned-tab.svg
apple-touch-icon.png
は 180px x 180px 、 safari-pinned-tab.svg
は 16pt x 16pt 、 その他のアイコンはファイル名の通りのサイズ (px) で作成します。
4. manifest.json の作成
今回の目的であるホーム画面へのアイコン追加を実現するためのファイルです。 public
直下に作成します。
{
"name": "ココイチ注文料金簡易カリキュレータ",
"short_name": "coco1cal",
"icons": [
{
"src": "./img/icons/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "./img/icons/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "./img/icons/apple-touch-icon-60x60.png",
"sizes": "60x60",
"type": "image/png"
},
{
"src": "./img/icons/apple-touch-icon-76x76.png",
"sizes": "76x76",
"type": "image/png"
},
{
"src": "./img/icons/apple-touch-icon-120x120.png",
"sizes": "120x120",
"type": "image/png"
},
{
"src": "./img/icons/apple-touch-icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "./img/icons/apple-touch-icon-180x180.png",
"sizes": "180x180",
"type": "image/png"
}
],
"start_url": "./index.html",
"display": "standalone",
"background_color": "#FFFFFF",
"theme_color": "#4e342e"
}
icons
で最低限必要なのは android-chrome-192x192.png
と android-chrome-512x512.png
です。ただ、 iOS でもホーム画面への追加を実現したい場合は、その他のファイルも指定する必要があります。
また、 iOS のホーム画面アイコンは透過画像が使用できません。というか、使用はできるのですが、透過部分が黒で塗りつぶされます。
なので、 Android 用アイコンには透過画像を使いたい場合、 iOS 用のアイコンには透過部分を含まない画像を用意したほうがよいです。
background_color
はスプラッシュ画像の背景色になります。
theme_color
はツールバーの色になります。
その他、 manifest.json に関する内容は The Web App Manifest | Web Fundamentals | Google Developers をご覧ください。
5. index.html への追記
4 までの手順で PWA 化は完了しているのですが、追加で対応が必要な内容がありました。
manifest.json の theme_color が反映されない
manifest.json
の theme_color
はツールバーの色になると書きましたが、ここを変更してもなぜか Vue.js デフォルトの #4DBA87
になってしまう問題がありました。 (Android 端末: Pixel 3a)
PWA化したのはいいけど、テーマカラーが変わらないのはなぜ。manifest.json の値は変わってるのに。 pic.twitter.com/6kNVRyRrf3
— よっしーCBR789RR (@michimani210) May 22, 2019
調べてみると、どうやら Vue.js で作った PWA では manifest.json
の theme_color
が反映されないため、 head
内に直接メタタグで指定する必要があるらしいです。
ということで head
内に追記したところ、無事に反映されました。
@@ -14,6 +14,7 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
+ <meta name="theme-color" content="#4e342e">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
iOS では manifest.json を読んでくれない
PWA の仕様や manifest.json
については Google が進めている内容で、 iOS Safari ではまだ未対応な部分も多々あるようです。
そのため、 manifest.json
の内容を head
内にメタタグで追記する必要があります。ただ、すべてを書くとなると面倒なので、 Google が用意ししている PWACompact を利用します。
使い方は簡単で、 GitHub の readme にある通り head
内に下記の内容を追記するだけです。ただし、 readme と違う点は、 manifest.webmanifest
ではなく manifest.json
としているところです。
@@ -5,6 +5,10 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta name="theme-color" content="#4e342e">
+ <link rel="manifest" href="manifest.json" />
+ <script async src="https://cdn.jsdelivr.net/npm/pwacompat@2.0.8/pwacompat.min.js"
+ integrity="sha384-uONtBTCBzHKF84F6XvyC8S0gL8HTkAPeCyBNvfLfsqHh+Kd6s/kaS4BdmNQ5ktp1"
+ crossorigin="anonymous"></script>
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
これによって、 iOS 用に必要なメタタグが自動で挿入されるようになります。
Lighthouse で確認
Lighthouse でスコアを確認してみます。
全体的に高いです。まあ、外部 API を使ったり複雑なデータの持ち方をしているわけではないので、スコアが高いのは当たり前かもしれません。
PWA の項目について見てみます。
全部オッケーっぽいですね。
みんなでココイチへ行こう!
Vue.js で作ったアプリケーションを PWA 化してみた話でした。
iOS/Android のネイティブアプリを作るとなると、デベロッパー登録とかストアへの申請とかハードルがいくつかありますが、 PWA の技術を使えば Web アプリケーションをネイティブアプリっぽくできるので、すごいですね。 (語彙力)
現状では iOS で対応が不完全だったりするので、今後そのあたりが統一されていけばスマホアプリ事情が変わっていくかもしれませんね。
ということで、PWA 化した ココイチ注文料金簡易カリキュレータ 、ぜひ使ってみてください。アクセスして「ホーム画面へ追加」するだけです。
ココイチ美味しいですよ🍛
comments powered by Disqus