A presentation at Fronteers @ Mirabeau in in Rotterdam, Netherlands by Niels Leenheer
THE PROGRESSION OF WEB APPS FRONTEERS @ MIRABEAU, 18TH AUGUST 2016
THE PROGRESSION OF WEB APPS
PROGRESSIVE WEB APPS
Photo by Daniel Appelquist
PROGRESSIVE
WEB APP
WEB APP
WEB APP
WEB APP
RESPONSIVE
airhorner.com
CONNECTIVITY INDEPENDENT
APP-LIKE
APP-LIKE
MENU Where is my navigation? Click on the hamburger menu to get access to all of the navigation options. APP-LIKE
FRESH
SAFE
DISCOVERABLE
Hi there! I’m a Web App!
RE-ENGAGEABLE
INSTALLABLE
airhorner.com
airhorner.com
LINKABLE
Airhorner
Airhorner no results found
https://airhorner.com
THIS IS NOT A NEW IDEA
“ The full Safari engine is inside of iPhone. And so, you can write amazing Web 2.0 and Ajax apps that look exactly and behave exactly like apps on the iPhone. And these apps can integrate perfectly with iPhone services. — Steve Jobs, 2007
“ The fundamental problem on the iPhone is not Apple’s App Store approval policies, but the iPhone developers’ arrogant disdain for Web technologies. I reviewed the apps I have on my iPhone, and most can be released as a Web app right now. — Peter Paul Koch, 2009
✓ PROGRESSIVE ✓ RESPONSIVE ✓ CONNECTIVITY INDEPENDENT ✓ APP-LIKE ✓ SAFE ✓ DISCOVERABLE ✓ INSTALLABLE ✓ LINKABLE
LOTS OF UGLY HACKS
LOTS OF BROWSER QUIRKS
NON-STANDARD API’S
NO DEVICE API’S
BUILDING NATIVE APPS USING WEB TECHNOLOGY
WHY?
WE KNOW HTML, CSS AND JAVASCRIPT
CROSS PLATFORM DEVELOPMENT
GET ACCESS TO NATIVE API’S
THE APP STORE
$ € ¥ £ € ₽ kr. ¥ دج ¥ $€ £ ₽
PACKAGED WEB APPS
}
HOSTED WEB APPS
2007
application.xml <application xmlns="http://ns.adobe.com/air/application/2.5"> <id>nl.salonhub.Salonhub</id> <filename>Salonhub</filename> <name>Salonhub</name> <versionNumber>6.0.356</versionNumber> <description>De flexibele en complete oplossing voor uw kapsalon</description> <initialWindow> <content>platform/air/app/index.html</content> <width>1024</width> <height>768</height>
adt -package -storetype pkcs12 -keystore cert.p12 -storepass ****** dist/air/Salonhub-6.0.365.air build/air/application.xml -C build/air assets external lib platform settings.js
Salonhub.air
2009
“ PhoneGap is a polyfill, and the ultimate purpose of PhoneGap is to cease to exist — Brian LeRoux
Vibration Dialogs Network Information Camera Device Motion Battery Status Splashscreen DEVICE API’S Files Statusbar Device Orientation Media Capture Geolocation File Transfers Media
PLUGINS
2012 chrome app
chromebook
chrome web store
×
2013
chromium +
launch.js const electron = require('electron'); const app = electron.app; let mainWindow; function createWindow () { mainWindow = new electron.BrowserWindow({ width: 800, height: 600 }); mainWindow.loadURL('file://' + __dirname + '/app/index.html'); mainWindow.on('closed', () => { mainWindow = null }); } app.on('ready', () => { createWindow(); }); app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); }
2014 Universal Windows Platform
npm install -g manifoldjs manifoldjs https://airhorner.com -d ~/Projects -p windows10 manifoldjs package ~/Projects/AirHorner/windows10
UNIVERSAL WINDOWS APPS HAVE ACCESS TO THE UNIVERSAL WINDOWS API
DEPLOY ON DESKTOP, MOBILE AND XBOX ONE
AND MANY MORE…
BUT…
DEPENDANT ON THIRD PARTIES
NOT PART OF THE WEB
PROGRESSIVE WEB APPS
WEB MANIFEST
index.html <!doctype> <html> <head> <title>HTML5test - How well does your browser support HTML5?</title>
index.html <!doctype> <html> <head> <title>HTML5test - How well does your browser support HTML5?</title> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black">
index.html <!doctype> <html> <head> <title>HTML5test - How well does your browser support HTML5?</title> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link <link <link <link <link <link <link <link rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png"> sizes="114x114" href="/apple-icon-114x114.png"> sizes="72x72" href="/apple-icon-72x72.png"> sizes="144x144" href="/apple-icon-144x144.png"> sizes="60x60" href="/apple-icon-60x60.png"> sizes="120x120" href="/apple-icon-120x120.png"> sizes="76x76" href="/apple-icon-76x76.png"> sizes="152x152" href="/apple-icon-152x152.png">
<!doctype> <html> <head> <title>HTML5test - How well does your browser support HTML5?</title> <meta name="apple-mobile-web-app-capable" index.htmlcontent="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link <link <link <link <link <link <link <link rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png"> sizes="114x114" href="/apple-icon-114x114.png"> sizes="72x72" href="/apple-icon-72x72.png"> sizes="144x144" href="/apple-icon-144x144.png"> sizes="60x60" href="/apple-icon-60x60.png"> sizes="120x120" href="/apple-icon-120x120.png"> sizes="76x76" href="/apple-icon-76x76.png"> sizes="152x152" href="/apple-icon-152x152.png">
<!doctype> <html> <head> <title>HTML5test - How well does your browser support HTML5?</title> <meta name="apple-mobile-web-app-capable" index.htmlcontent="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link <link <link <link <link <link <link <link rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png"> sizes="114x114" href="/apple-icon-114x114.png"> sizes="72x72" href="/apple-icon-72x72.png"> sizes="144x144" href="/apple-icon-144x144.png"> sizes="60x60" href="/apple-icon-60x60.png"> sizes="120x120" href="/apple-icon-120x120.png"> sizes="76x76" href="/apple-icon-76x76.png"> sizes="152x152" href="/apple-icon-152x152.png">
<meta name="mobile-web-app-capable" content="yes"> <meta name="theme-color" content="#0092bf"><!doctype> <html> <head> <title>HTML5test - How well does your browser support HTML5?</title> <meta name="apple-mobile-web-app-capable" index.htmlcontent="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link <link <link <link <link <link <link <link rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png"> sizes="114x114" href="/apple-icon-114x114.png"> sizes="72x72" href="/apple-icon-72x72.png"> sizes="144x144" href="/apple-icon-144x144.png"> sizes="60x60" href="/apple-icon-60x60.png"> sizes="120x120" href="/apple-icon-120x120.png"> sizes="76x76" href="/apple-icon-76x76.png"> sizes="152x152" href="/apple-icon-152x152.png">
<meta name="mobile-web-app-capable" content="yes"> <meta name="theme-color" content="#0092bf"> <link <link <link <link <link rel="icon" rel="icon" rel="icon" rel="icon" rel="icon" type="image/png" type="image/png" type="image/png" type="image/png" type="image/png" href="/icon-16x16.png" sizes="16x16"> href="/icon-32x32.png" sizes="32x32"> href="/icon-96x96.png" sizes="96x96"> href="/icon-160x160.png" sizes="160x160"> href="/icon-196x196.png" sizes="196x196">PLACE EVERYTHING IN A SEPARATE JSON FILE
manifest.json { "name": "HTML5test", "theme_color": "#0092bf", "display": "standalone", "icons": [ { "src": "/icon-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/icon-256x256.png", "sizes": "256x256", "type": "image/png" }, { "src": "/icon-512x512.png", "sizes": "512x512", "type": "image/png" }
APP NAME ICONS THEME COLORS SETTINGS
LAUNCH FULL SCREEN { "display": "standalone" }
LIMIT SCREEN ORIENTATION { "orientation": "portrait" }
START A DIFFERENT URL { "start_url": "standalone.html" }
index.html <!doctype> <html> <head> <title>HTML5test - How well does your browser support HTML5?</title> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link <link <link <link <link <link <link <link rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png"> sizes="114x114" href="/apple-icon-114x114.png"> sizes="72x72" href="/apple-icon-72x72.png"> sizes="144x144" href="/apple-icon-144x144.png"> sizes="60x60" href="/apple-icon-60x60.png"> sizes="120x120" href="/apple-icon-120x120.png"> sizes="76x76" href="/apple-icon-76x76.png"> sizes="152x152" href="/apple-icon-152x152.png">
<meta name="mobile-web-app-capable" content="yes"> <meta name="theme-color" content="#0092bf"> <link rel="icon" type="image/png" href="/icon-16x16.png" sizes="16x16">NOT POSSIBLE TO SPECIFY DIFFERENT ICON STYLES FOR DIFFERENT PLATFORMS :-(
BROWSER SUPPORT Chrome 39 Opera 32
DEVICE API’S
VIBRATION navigator.vibrate(200); navigator.vibrate([100, 200, 200, 200, 500]);
CAMERA & MICROPHONE navigator.getUserMedia( { audio: true, video: { width: 1280, height: 720 } }, function(stream) { }, function(err) { } });
BATTERY navigator.getBattery().then(function(battery) { battery.addEventListener('chargingchange', function() { console.log(battery.charging); }); battery.addEventListener('levelchange', function() { console.log(battery.level); }); });
GEOLOCATION DEVICE MOTION DEVICE ORIENTATION AMBIENT LIGHT BLUETOOTH
SERVICE WORKERS
“ Application Cache is a Douchebag! — Jake Archibald
? ×
if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js'); }
×
THE SERVICE WORKER RUNS JAVASCRIPT CODE :-)
sw.js self.addEventListener('install', function(event) { // Perform install steps });
sw.js self.addEventListener('install', function(event) { event.waitUntil( caches.open('v1').then(function(cache) { return cache.addAll([ '/index.html', '/styles/main.css', '/scripts/main.js' ]); }) ); });
return cache.addAll([ '/index.html', '/styles/main.css', '/scripts/main.js' ]); }) sw.js ); }); self.addEventListener('fetch', function(event) { // Intercept network requests });
return cache.addAll([ '/index.html', '/styles/main.css', '/scripts/main.js' ]); }) sw.js ); }); self.addEventListener('fetch', function(event) { event.respondWith( caches.match(event.request) .then(function(response) { if (response) { return response; } return fetch(event.request); } ) ); });
THE SERVICE WORKER IS INDEPENDENT OF YOUR WEBPAGE
BROWSER SUPPORT Chrome 40 Opera 27 Firefox 44 Samsung 4 Edge (behind flag)
PUSH NOTIFICATIONS
WEB PUSH API WEB PUSH PROTOCOL WEB NOTIFICATIONS SERVICE WORKERS
navigator.serviceWorker.ready.then(function(sw) { sw.pushManager.subscribe().then(function(subscription) { // Send subscription to server }) })
Send the subscription data to our server, including the URL of the push server
The webpage is closed and the service worker is sleeping
The server has new information for the user
The server sends a message to the push server using the Web Push protocol
The push server wakes up the service worker
self.addEventListener('push', function(event) { // We received a push message });
(optional)
self.registration.showNotification('Attention!', { body: 'Push message received', icon: 'icon.png' }); (optional)
The webpage is still closed and the service worker is sleeping again
BROWSER SUPPORT Chrome 42 Opera 30 Firefox 44 Samsung 4 Edge (behind flag)
WEB PAYMENTS
Start payment process by clicking a button in your app
Start payment process by clicking a button in your app var methodData = [ { supportedMethods: ["visa", "mastercard"] } ];
var details = { displayItems: [ { label: "Donation", amount: { currency: "USD", value : "55.00" } } ], total: { label: "Total", amount: { currency: "USD", value : "55.00" } } }; Start payment process by clicking a button in your app
var request = new PaymentRequest( methodData, // required payment method data details // required transaction information );
request.show().then(function(response) { // success }).catch(function(err) { // failed });
Select your payment method or use the default
Enter your CVC code or confirm with your fingerprint
Done!
BROWSER SUPPORT Chrome Edge (behind flag)
BUT WHAT ABOUT THE DESKTOP?
BROWSER DEVELOPMENT IS DRIVEN BY MOBILE
BUT…
NATIVE PWA SUPPORT IN THE WINDOWS STORE
BUT WHAT ABOUT APPLE?
THIS IS NOT A GOOGLE THING
BUT…
?
× ?
THE OLD HACKS STILL WORK
MAYBE, HOPEFULLY, POSSIBLY THIS WILL CHANGE IN THE FUTURE
OR NOT
THANK YOU! @HTML5TEST
No, this title is not a typo. This talk is about Web Apps in general. We look back to the past of Web Apps and we’re going to look how we can create native apps using web technologies. Of course we’re going to look at the future too. Progressive Web Apps – what are they? And is the web now finally able to challenge native app development?