スマートフォン体験を一歩先へ
プログレッシブウェブアプリの作り方
Eiji Kitamura
Last update: 2016/6
Confidential and proprietary
このスライドについて
Confidential and proprietary
Eiji Kitamura
Developer Advocate @ Google
Chrome / Web / Identity
Confidential and proprietary
A day in the life...
Photo by @28964535@N08 on Flickr
Confidential and proprietary
スマートフォンの月間利用時間
1:49
Smartphone
Source: スマートフォン視聴率情報 Nielsen Mobile NetView 2015 年 9 月より
http://www.netratings.co.jp/news_release/2015/11/Newsrelease20151125.html
1:28
0:23
App
Web
Confidential and proprietary
80
は、その人のトップ3アプリ
に費やされている
Source: comScore Mobile Metrix, U.S., Age 18+, June 2015
スマートフォンユーザの
時間
%
Confidential and proprietary
https://medium.com/inside-birdly/why-you-shouldn-t-bother-creating-a-mobile-app-328af62fe0e5
Confidential and proprietary
スマートフォンユーザーの
平均月間利用アプリ数
25
Chrome for Android ユーザーの平均月間訪問サイト数
100+
Source: comScore Mobile Metrix, U.S., Age 18+, June 2015; Internal Chrome Data
Confidential and proprietary
Progressive Web Apps
Confidential and proprietary
S
L
I
C
E
Secure
Linkable
Indexable
Composable
Ephemeral
Confidential and proprietary
Progressive Web App
Legacy Browsers
Modern Browsers
Native App like Experience
Regular Web App Experience
Confidential and proprietary
Confidential and proprietary
Confidential and proprietary
Homescreen Icon
Splash Screen
Fullscreen
Offline access
Theme color
Push Notification
Confidential and proprietary
User Experience
Confidential and proprietary
アプリインストールバナー
manifest を定義
Service Worker を使用
HTTPS で提供
5 分以上の間隔で複数回アクセス
Confidential and proprietary
{
"name": "Flipkart Lite",
"short_name": "Flipkart Lite",
"icons": [
{
"src": "/images/icon.png",
"sizes": "96x96",
"type": "image/png"
}, {
"src": "/images/icon@2x.png",
"sizes": "192x192",
"type": "image/png"
}
],
"start_url": "/?homescreen=1",
"display": "standalone",
"background_color": "#F1F1F1",
"theme_color": "#F1F1F1"
}
manifest.json
Confidential and proprietary
<link rel="manifest" href="/manifest.json">
HTML
Confidential and proprietary
Service Worker
Photo by @tallkev on Flickr
Confidential and proprietary
Google for Mobile
push
Service Worker
Cache API
Push Notification
Confidential and proprietary
index.html
navigator.serviceWorker.register('/sw.js')
.then(function(registration) {
// Success!
}).catch(function(error) {
// Error...
});
Confidential and proprietary
Cache API
Photo by @taranos on Flickr
Confidential and proprietary
Google for Mobile
suumo
0.8sec
0.2sec
Confidential and proprietary
Cache API
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
sw.js
Confidential and proprietary
sw-toolbox
https://github.com/GoogleChrome/sw-toolbox
1
2
3
cacheFirst
1
2
3
networkFirst
1
2
2
fastest
Confidential and proprietary
sw-precache
https://github.com/GoogleChrome/sw-precache
index.html
/style/main.css
/scripts/main.js
...
Confidential and proprietary
https://github.com/GoogleChrome/application-shell
Confidential and proprietary
Push Notification
Photo by @johanl on Flickr
Confidential and proprietary
Google for Mobile
Confidential and proprietary
Web Push Notifications
Confidential and proprietary
Confidential and proprietary
Firebase Cloud Messaging
Confidential and proprietary
プッシュ通知の購読
navigator.serviceWorker.ready().then(function(sw) {
sw.pushManager.subscribe({userVisibleOnly: true})
.then(function(sub) {
// After permission is granted
sendSubToServer(sub); // Send subscription to the server
});
});
index.html
Confidential and proprietary
プッシュ通知の受信
self.addEventListener('push', function(event) {
event.waitUntil(
self.registration.showNotification(title, {
body: body, icon: icon, tag: tag,
actions: [{action: 'remindMe', title: 'REMIND ME'}]
}
});
});
sw.js
push
Confidential and proprietary
プッシュ通知にカスタムボタン
self.addEventListener('notificationclick', function(event) {
event.notification.close();
if (event.action === 'remindMe') {
remindMeLater();
} else {
clients.openWindow("/inbox");
}
}, false);
sw.js
Confidential and proprietary
Background Sync
Photo by @lanier67 on Flickr
Confidential and proprietary
Confidential and proprietary
One-off Sync
Confidential and proprietary
index.html
navigator.serviceWorker.register('/sw.js')
.then(function(registration) {
return registration.sync.register('mySync');
});
sw.js
self.addEventListener('sync', function(event) {
if (event.tag == 'mySync') {
event.waitUntil(doSomething());
}
});
Confidential and proprietary
Periodic Sync
Confidential and proprietary
Summary
Confidential and proprietary
Making an improvement
Photo by @28964535@N08 on Flickr
Confidential and proprietary
Confidential and proprietary
Tips
Confidential and proprietary
Confidential and proprietary
https://chromestatus.com
Confidential and proprietary
Use Chrome Canary
Confidential and proprietary
Inspect devices
Confidential and proprietary
Debug on DevTools
Confidential and proprietary
thank
you
Google for Mobile
Confidential and proprietary
FAQ
Confidential and proprietary