利用一系列现代Web技术的组合,
以在移动设备上提供更好的交互体验。
Web App可以渐进式地模拟Native App
比如被添加到主屏幕、全屏方式运行、离线工作及推送通知消息等。
discoverable & installable
Application Shell architecture
Service Workers
<link rel="manifest" href="/manifest.json">
{
"lang": "en",
"dir": "ltr",
"name": "Super Racer 3000",
"description": "The ultimate futuristic racing game from the future!",
"short_name": "Racer3K",
"icons": [{
"src": "icon/lowres.webp",
"sizes": "64x64",
"type": "image/webp"
},{
"src": "icon/lowres.png",
"sizes": "64x64"
}, {
"src": "icon/hd_hi",
"sizes": "128x128"
}],
"scope": "/racer/",
"start_url": "/racer/start.html",
"display": "fullscreen",
"orientation": "landscape",
"theme_color": "aliceblue",
"background_color": "red",
"screenshots": [{
"src": "screenshots/in-game-1x.jpg",
"sizes": "640x480",
"type": "image/jpeg"
},{
"src": "screenshots/in-game-2x.jpg",
"sizes": "1280x920",
"type": "image/jpeg"
}]
}
typical manifest
<!-- Sets whether a web application runs in full-screen mode. -->
<meta name="apple-mobile-web-app-capable" content="yes">
<!-- Enables or disables automatic detection of possible phone numbers. -->
<meta name="format-detection" content="telephone=no">
<!-- Changing the Status Bar Appearance -->
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<!-- Hiding Safari User Interface Components -->
<meta name="apple-mobile-web-app-capable" content="yes">
<!-- Specifying a Webpage Icon for Web Clip -->
<link rel="apple-touch-icon" href="touch-icon-iphone.png">
<link rel="apple-touch-icon" sizes="76x76" href="touch-icon-ipad.png">
<link rel="apple-touch-icon" sizes="120x120" href="touch-icon-iphone-retina.png">
<link rel="apple-touch-icon" sizes="152x152" href="touch-icon-ipad-retina.png">
<!-- Specifying a Startup Image -->
<link rel="apple-touch-startup-image" href="/startup.png">
Server-side rendering ( not isomorphism)
An application shell is the minimal HTML, CSS, and JavaScript powering a user interface.
A script that your browser runs in the background, separate from a web page, opening the door to features that don't need a web page or user interaction.
Web Workers
HTML5 标准的一部分,一套API,容许一段JavaScript程序运行在主线程之外的另一个线程中。
支持的事件
Register
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/sw.js')
.then(function(registration) {
// Registration was successful
console.log(
'ServiceWorker registration successful with scope: ',
registration.scope
)
})
.catch(function(err) {
// registration failed :(
console.log(
'ServiceWorker registration failed: ',
err
)
})
}
</script>
registerServiceWorker() {
if (!('serviceWorker' in navigator)) {
// Service worker is not supported on this platform
return;
}
navigator.serviceWorker.register('/sw.js', {
scope: '/'
}).then((registration) => {
console.log('Service worker is registered.');
var isUpdate = false;
// If this fires we should check if there's a new Service Worker
// waiting to be activated. If so, ask the user to force refresh.
if (registration.active) {
isUpdate = true;
}
registration.onupdatefound = function(updateEvent) {
console.log('A new Service Worker version has been found...');
// If an update is found the spec says that there is a new Service
// Worker installing, so we should wait for that to complete then
// show a notification to the user.
registration.installing.onstatechange = function(event) {
if (this.state === 'installed') {
if (isUpdate) {
ToasterSingleton.getToaster().toast(
'App updated. Restart for the new version.');
} else {
ToasterSingleton.getToaster().toast(
'App ready for offline use.');
}
}
};
};
})
.catch((err) => {
console.log('Unable to register service worker.', err);
});
}
注意事项
Install and activate
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('v1').then(function(cache) {
return cache.addAll([
'/sw-test/',
'/sw-test/index.html',
'/sw-test/style.css',
'/sw-test/app.js',
'/sw-test/image-list.js',
'/sw-test/star-wars-logo.jpg',
'/sw-test/gallery/',
'/sw-test/gallery/bountyHunters.jpg',
'/sw-test/gallery/myLittleVader.jpg',
'/sw-test/gallery/snowTroopers.jpg'
])
})
)
})
self.addEventListener('fetch', function(event) {
console.log('The service worker is serving the asset.')
event.respondWith(fromNetwork(event.request, 400)
.catch(function() {
return fromCache(event.request)
}))
})
更多示例参考:Service Worker Cookbook