AMP縛りでページ作ったけど、やっぱりPWA化もしたいと思いやってみたらあまりにも簡単にできたので手順を残しておきます。
出来上がったページをLighthouseで計測した結果、PWAの点数は100点満点でした。
TL;DR
- Web App Manifest Generator使ってmanifest.jsonを生成
- amp-install-serviceworkerでAMPでもService Worker動く
- workboxでService Workerコードを簡単に生成
AMP(Accelerated Mobile Pages)とは
- モバイルページを高速化するためのもの
- 速くするというより遅くしない
- 詳しくはampproject.orgを見て下さい
PWA(Progressive Web Apps)とは
- Webとネイティブアプリの良いところを合わせてUXを良くしようとする仕組み
- オフライン、プッシュ通知、ホーム画面から起動などネイティブアプリっぽいことをWebで実現
- 詳しくはGoogleのPWAページを見て下さい
AMPの実装
最初にAMPページを用意します。
既に手元にPWA化したいAMPページがある方はここは読み飛ばしてください。
AMPページが無い方は、初めての AMP ページを作成するで作ったAMPページをもとに進めます。
AMP HTML の実装は以下の通りです。
コピペして画像のパスを変更してもらえればAMPページはすぐできます。
<!doctype html>
<html amp lang="en">
<head>
<meta charset="utf-8">
<title>Hello, AMPs</title>
<link rel="canonical" href="http://example.ampproject.org/article-metadata.html">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "NewArticle",
"headline": "Open-source framework for publishing content",
"datePublished": "2015-10-07T12:02:41Z",
"image": [
"logo.png"
]
}
</script>
<style amp-custom>
/* any custom style goes here */
body {
background-color: white;
}
amp-img {
background-color: gray;
border: 1px solid black;
}
</style>
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<script async src="https://cdn.ampproject.org/v0.js"></script>
</head>
<body>
<h1>Welcome to the mobile web</h1>
<amp-img src="welcome.png" alt="Welcome" height="400" width="800"></amp-img>
</body>
</html>
有効なAMPページかテストする
この時点でGitHub PagesやNetlifyにホスティングして、AMPテストページで有効なAMPか確認します。
有効な場合、以下のような画面が表示されます。
PWA対応する
AMPページをPWA化していきます。
やることは以下のとおりです。
- manifest.jsonを用意する
- Service Workerを導入する
manifest.jsonを用意する
ただのJSONなので手で書いても時間はかかりませんが、はじめて書く方やもっと楽したい人のためにWeb App Manifest Generatorを使います。
https://app-manifest.firebaseapp.com/ にアクセスすると以下の画面に飛びます。
各項目についてはGoogleが公開しているウェブアプリ マニフェストを見て下さい
青い「ICON」ボタンをクリックしてホーム画面に使うアイコン画像を選択します。
「GENERATE ZIP」ボタンをクリックしてapp-images.zipというzipファイルをダウンロードします。
このzipファイルにはmanifest.jsonと様々なサイズの画像が梱包されています。
zipを解凍してmanifest.jsonとアイコンの画像をプロジェクト内に置きます。
ダウンロードしたmanifest.jsonは以下のようになっていると思います。
内容を変更する場合は手動で書き直してください。
{
"name": "AMP PWA Sample App",
"short_name": "Sample",
"theme_color": "#2196f3",
"background_color": "#2196f3",
"display": "standalone",
"Scope": "/",
"start_url": "https://example.com/amp-pwa/",
"icons": [
{
"src": "images/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "images/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "images/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "images/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "images/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "images/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "images/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "images/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"splash_pages": null
}
HTMLからmanifest.jsonを読み込む
以下のようにhead
タグにmanifest.jsonを読み込む記述を追加します
<link rel="manifest" href="./manifest.json">
metaタグtheme-colorを設定する
完全なPWAにするにはmanifest.jsonで指定したtheme-colorをHTML内にmetaタグで追加する必要があります。
contentの値はmanifest.jsonで定義したtheme-colorの値に合わせてください。
<meta name="theme-color" content="#2196f3">
これでmanifest.jsonの用意は完了です。
Service Workerを導入する
Service WorkerについてはService Workerの紹介やService Workerの基本とそれを使ってできることをお読み下さい。
AMPページではJavaScriptの実行に制限がありますが、amp-install-serviceworkerを使うことでService Workerを使うことができます。
また、sw-precacheworkboxでService Workerのコードを簡単に自動生成することができるのでService Workerのための学習は特に必要なく導入が可能です。
amp-install-serviceworkerを使ってService Workerを利用可能にする
AMPページでServiceWorkerを使う場合、amp-install-serviceworkerを使うことになります。
head
の中に以下のscript
タグを追加してください。
<script async custom-element="amp-install-serviceworker"
src="https://cdn.ampproject.org/v0/amp-install-serviceworker-0.1.js"></script>
次にbody
の中に以下のamp-install-serviceworker
タグを追加してください。
src
はこの後紹介するService Workerのコードのファイルパスを設定します。
layout
は"nodisplay"を設定します。
data-iframe-src
はGoogle検索からアクセスする際にこの属性が無いとServiceWorkerは正常に動作しません。これについては後述します。
その他の設定値に関してはamp-install-serviceworkerのリファレンスにてご確認ください。
<amp-install-serviceworker
src="./sw.js"
layout="nodisplay"
data-iframe-src="https://your_site_domain/sw.html">
</amp-install-serviceworker>
data-iframe-srcについて補足します。
Google検索からのアクセスした場合、AMPページはAMP CDNから返されます。このドメインはwww.google.co.jpです。AMPページのURLを見るとわかるのですが、 https://www.google.co.jp/amp/s/your_domain/ となっているはずです。
JavaScriptファイルの取得先のドメインはデプロイした先のドメインです。例えばGitHub Pagesにデプロイしていたらusername.github.ioとなります。
ServiceWorkerの仕様としてJavaScriptファイルが違うドメインの場合、ServiceWorkerへの登録は行なえません。
そのためJavaScriptの取得先と同じドメインにHTMLを用意して、そのHTML内でServiceWorkerへの登録を行います。
data-iframe-src
はそのServiceWorkerの登録を行うHTMLのURLを指定するための属性です。
以下がdata-iframe-src
に指定するHTMLのサンプルです。
<!DOCTYPE html>
<html>
<head>
<title>installing Service Woker</title>
<script type="text/javascript">
if("serviceWorker" in navigator) {
navigator.serviceWorker.register("/sw.js")
.then(function(reg){
console.log('SW scope: ', reg.scope);
})
.catch(function(err) {
console.log('SW registration failed: ', err);
});
};
</script>
</head>
<body>
</body>
</html>
これでAMPページ内でService Workerを使う準備が整いました。
workboxを使ってService Workerのコードを生成する
workboxを使うとService Workerのコードを簡単に生成することができます。
workboxはCLI、node、webpackのいずれかで使うことができます。
今回は最も簡単そうなCLIで使います。CLIで使うにはworkbox-cliを使います。
npmで配布されているので、以下のようにインストールすることも可能ですが、
npm install -g workbox-cli
今回は一度しか使わないためnpxを使って実行します。
npxはグローバルにインストールせずにダウンロードと実行を一発で行ってくれます。
workbox-cliには4つのモードがあります。
- wizard
- generateSW
- injectManifest
- copyLibraries
今回はwizardを使います。4つのモードについて詳しくはworkbox-cliをご確認お願い致します。
npx workbox-cli wizard
実行するといくつか質問が表示されるので、答えていきます。
すべて答えるとworkbox-config.js
というファイルが自動生成されます。
自動生成されたworkbox-config.js
はローカルのファイルをキャッシュする設定はwizardで選択するだけで設定できるのですが、今回はampproject.org
のCDNから取得したJSファイルもキャッシュしなければオフライン対応ができません。
そのためworkbox-config.js
を以下のように修正します。
module.exports = {
"globDirectory": ".",
"globPatterns": [
"**/*.{png,html,json,js}"
],
"swDest": "sw.js",
// 以下を手動で追加
"runtimeCaching": [{
urlPattern: new RegExp('^https://cdn.ampproject.org'),
handler: 'staleWhileRevalidate',
options: {
cacheableResponse: {
statuses: [0, 200]
}
}
}]
};
修正したworkbox-config.js
を元にService Workerのコードを生成します。
以下のコマンドを実行してください。
npx workbox-cli generateSW workbox-config.js
コマンドを実行するとプロジェクト直下にsw.js
というファイルができているはずです。
このsw.js
がService Workerのコードです!
プロジェクト構成
ここまでで以下のようなプロジェクトになっているかと思います。
.
├── images
│ └── icons
│ ├── icon-128x128.png
│ ├── icon-144x144.png
│ ├── icon-152x152.png
│ ├── icon-192x192.png
│ ├── icon-384x384.png
│ ├── icon-512x512.png
│ ├── icon-72x72.png
│ └── icon-96x96.png
├── index.html
├── manifest.json
├── sw.js
├── welcome.png
└── workbox-config.js
Lighthouseで確認する
最後にPWA化できているのか確認してみましょう。
GitHub PagesとかNetlifyなどにホスティングしてLighthouseで確認すると満点に近い点数になってるはずです。
自分はGitHub PagesにホスティングしてChrome DevToolsのAuditsで確認し100点でした。
まとめ
- Web App Manifest Generator使えばmanifest.jsonとアイコンも生成できる
- amp-install-serviceworkerとworkbox使えばさくっとAMPページにService Worker導入できる
- AMPページは簡単にPWA化できる
参考
- ampproject.org
- Progressive Web Apps
- 初めての AMP ページを作成する
- Progressice Web AMPs
- amp-install-serviceworker
- sw-precache
- workbox
- Web App Manifest Generator
最後までお読み頂きありがとうございました。
不備や質問はコメント欄またはTwitterにてお願い致します。
2018/03/26 修正
この記事を最初に書いたときはsw-precacheを使った説明でしたが、開発が止まっているっぽく、後継にあたるworkboxを使った説明に修正しました。