APIsfor modern web apps
chris mills, mozillA
Get the slides!•Don’t worry about notes •You can get the slides from slideshare.net/
chrisdavidmills •Sit back and relax •Or fidget if you get bored… •Ask questions at @chrisdavidmills or
who am i?•I’m Chris •Mozilla, MDN writer •Twiddling around with JS/CSS/HTML •APIs •Educational material •Accessibility whiner •Heavy metal drummer
APIslike, what are we talking about?
•I really mean browser JavaScript APIs •Exposing complex functionality to JS •Making the Web more powerful and useful
api, why oh why?
•For a time, we only really had a few APIs •We had DOM stuff, and XHR •(And a bunch of horrid non-standard stuff) •But the scene exploded •WHATWG, Web Apps WG, and others
api, why oh why?
•Earlier APIs added interesting new features •E.g. Geolocation, Canvas •But this still wasn’t enough
api, why oh why?
•We want to remain competitive with native •Get everything working together more
cohesively •Deal with multimedia effectively in the
browser •Improve performance, for games, etc. •Improve internationalization
api, why oh why?
catching nativeprogressive apps
•Native platforms had better functionality •We want to catch up, and make it webby
web versus native
•The Web is a good thing •Progressive enhancement •No app stores •You can’t cache seamlessly on native, or
render text easily/fluidly
we love web
•Installable/discoverable •Offline •Re-engageable •Linkable •Responsive •Safe •and of course, Progressive
progressive apps
Installablei got you under my skin
installing apps
•The web can do this too! •Without app stores •Web App Manifest defines app features •Including icons, background, splash screen,
theme colors… •App files cached on device too (see later)
installing apps
Manifest example{ "name": "My sample app", "short_name": "MY app", "start_url": "./?utm_source=web_app_manifest", "display": "standalone", "icons": [{ "src": "images/touch/homescreen48.png", "sizes": "48x48", "type": "image/png" }, { "src": "images/touch/homescreen72.png", "sizes": "72x72", "type": "image/png" }, { "src": "images/touch/homescreen96.png", "sizes": "96x96",
•Also helps with discoverability •The web largely does this anyway •Standardised metadata mechanism is nice •Better represent apps on search results,
social media, (app stores?!) etc.
discoverability
we already do it<meta property="og:description" content="Add-ons …"> <meta name="description" content="Add-ons add …"> <meta name="twitter:description" content="Add-ons add …”>
offlinestill a problem?
No connection = no experience
•Offline data storage •Offline asset storage •Reacting to network changes
offline is hard
•Not so bad •We have storage mechanisms (e.g.
IndexedDB, Web Storage, WebSQL) •Something available in most browsers •Plus polyfills (e.g. LocalForage)
offline data
•More of a pain •We had AppCache…
offline assets
CACHE MANIFEST # v1
CACHE: css/app.css index.html js/main.js js/lib/require.js
this had promise
•It’s actually fairly useless •Too much voodoo… •Assumed a specific set of behaviours
but….
Hello service workers!
•Proxy servers that sit between app and network
•Intercepting network requests and customising responses
•Does similar things to AppCache (plus a lot more…much harder to use)
•Granular control over actions
sw are cool
if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw-test/sw.js', { scope: '/*' }).then(function(sw) { // registration worked console.log('Registration succeeded.'); }).catch(function() { // registration failed console.log('Registration failed.'); }); }
registration
this.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/bountyHunters.jpg', '/sw-test/gallery/myLittleVader.jpg', '/sw-test/gallery/snowTroopers.jpg' ]); }) ); });
installation
this.addEventListener('fetch', function(event) { var response; event.respondWith(caches.match(event.request) .catch(function() { return fetch(event.request); }).then(function(r) { response = r; caches.open('v1').then(function(cache) { cache.put(event.request, response); }); return response.clone(); }).catch(function() { return caches.match(‘/sw-test/gallery/ myLittleVader.jpg'); })); });
custom responses
•The app container should be lightweight HTML/CSS/JS
•Load fast, be cached, load on repeat visits •The content should then update dynamically •See Instant Loading Web Apps with An
Application Shell Architecture
App shell
reengagementhey, come back!!!
•You have new followers •Your friend posted a new photo •Your pokemon wants another fight •You have mail •The government wants to read your mail •etc.
hello users
•Native was always good at reengagement •Now web can do it too, even when the app
isn’t being used •Push API •Notifications API •Channel Messaging API
•etc.
People love it
•Needs an active SW controlling the app •Subscribe to push messages •Send special endpoint to your server (URL) •Send messages to this endpoint •Push server sends them to the SW
needs a sw
navigator.serviceWorker.ready.then(function(reg) { reg.pushManager.getSubscription() .then(function(subscription) { // Enable any UI for subscribing to push messages. var endpoint = subscription.endpoint; updateStatus(endpoint,'init'); }).catch(function(err) { console.log('Error during getSubscription()', err); }); });
push
self.addEventListener('push', function(event) { var obj = event.data.json(); event.waitUntil( self.registration.showNotification(title, { body: obj.name + ‘ has subscribed.’, icon: icon, tag: tag }) ); });
notifications
var channel = new MessageChannel(); channel.port1.onmessage = function(e) { alert(e.data); } mySW = reg.active; mySW.postMessage('hello', [channel.port2]);
channel msg
var port;
self.onmessage = function(e) { port = e.ports[0]; } port.postMessage(obj);
continuityspecs working together
•Creating extra work, repetition, and confusion
•E.g. CSS and SVG functionality overlap •Led to them forming the FXTF •More care taken these days •Extensible web manifesto — modular and
explainable
silos aren’t cool
•Fetch is a good example •Similar to what XHR does •Abstracts the whole request/response model
as JS objects •So it can be used with other APIs like
Service Workers
fetch / sw
•Other specs also work well with/are based on SW: •Notifications API •Push API •Channel Messaging
•They all contain partial additions for SW
sw add-ons
mediaweb audio visuals
•Media was broken for years on the Web •Audio/video delivery needed Flash for so
long •The <video> tag took long enough
fix media
•WebRTC/gUM for accessing streams •Should solve many use cases, from simple
image capture, video streaming, up to multi-person video conferencing
•What about recording? •Media Recorder API
media capture
var constraints = { audio: true, video: true };
var p = navigator.mediaDevices.getUserMedia(constraints);
p.then(function(stream) { // do something with the stream in here });
p.catch(function(err) { console.log(err.name); });
getusermedia
var mediaRecorder = new MediaRecorder(stream);
record.onclick = function() { mediaRecorder.start(); }
stop.onclick = function() { mediaRecorder.stop(); }
mediaRecorder.ondataavailable = function(e) { var video = document.createElement('video'); video.setAttribute('controls', ''); var videoURL = window.URL.createObjectURL(e.data); video.src = videoURL; }
media recorder
•Media Source Extensions •Encrypted Media Extensions •DRM on the Web?!? •A necessary evil, WRT services like
Netflix..? •Netflix involved in both the above specs
streaming/drm
•Web Audio API •Precise audio control •Add effects •Split and merge audio channels •Spatialization •Audio visualizations
audio processing
Performancefaster and faster…
•General performance much improved •Web Workers •Emscripten/asm.js (Web Assembly coming
soon-ish) •WebGL •SIMD
performance
I18ninternationalization
•The Web is international •But adapting sites for an intl. audience is a
pain •E.g. Dealing with time/date formats •And BIDI websites •But we are working on this too
i18n
var date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
console.log(new Intl.DateTimeFormat().format(date));console.log(new Intl.DateTimeFormat('en-US').format(date)); // DateTimeFormat without arguments returns the // correct value for the language/timezone.
JavaScript i18n api•The JS Internationalization API provides
features for formatting dates/times for different languages, etc.
#content { padding-left: 12px: margin-right: 20px; }
html[dir="rtl"] #content { padding-left: 0; padding-right: 12px; margin-right: 0; margin-left: 20px; }
CSS BIDI features•BIDI websites are simpler to layout with CSS
BIDI features
#content { padding-inline-start: 12px: margin-inline-end: 20px; }
CSS BIDI features
•Main image: Bokeh Dandelion, by Nicolas Raymond
credits