SlideShare ist ein Scribd-Unternehmen logo
1 von 166
Progressive Web Apps
@PatrickKettner
Progressive What Apps?
@PatrickKettner
calm a baby
2G Ruined My Day45M Ruined My Day
When you don’t have a better
idea, buy a novelty domain
https://HushLittleBa.by
Baby soothing goodness in <6k
ServiceWorker
let CURRENT_CACHE = {
prefetch: 'prefetch-cache-v1'
};
self.addEventListener('install', event => {
let prefetch = ['/T0t411y-R4D-Sans']
event.waitUntil(caches.open(CURRENT_CACHE['prefetch'])
.then(cache =>
cache.addAll(prefetch.map((url) =>
new Request(url, { 'mode': 'no-cors' })
))
)
)
})
let CURRENT_CACHE = {
prefetch: 'prefetch-cache-v1'
};
self.addEventListener('install', event => {
let prefetch = ['/T0t411y-R4D-Sans']
event.waitUntil(caches.open(CURRENT_CACHE['prefetch'])
.then(cache =>
cache.addAll(prefetch.map((url) =>
new Request(url, { 'mode': 'no-cors' })
))
)
)
})
let CURRENT_CACHE = {
prefetch: 'prefetch-cache-v1'
};
self.addEventListener('install', event => {
let prefetch = ['/T0t411y-R4D-Sans']
event.waitUntil(caches.open(CURRENT_CACHE['prefetch'])
.then(cache =>
cache.addAll(prefetch.map((url) =>
new Request(url, { 'mode': 'no-cors' })
))
)
)
})
let CURRENT_CACHE = {
prefetch: 'prefetch-cache-v1'
};
self.addEventListener('install', event => {
let prefetch = ['/T0t411y-R4D-Sans']
event.waitUntil(caches.open(CURRENT_CACHE['prefetch'])
.then(cache =>
cache.addAll(prefetch.map((url) =>
new Request(url, { 'mode': 'no-cors' })
))
)
)
})
let CURRENT_CACHE = {
prefetch: 'prefetch-cache-v1'
};
self.addEventListener('install', event => {
let prefetch = ['/T0t411y-R4D-Sans']
event.waitUntil(caches.open(CURRENT_CACHE['prefetch'])
.then(cache =>
cache.addAll(prefetch.map((url) =>
new Request(url, { 'mode': 'no-cors' })
))
)
)
})
let CURRENT_CACHE = {
prefetch: 'prefetch-cache-v1'
};
self.addEventListener('install', event => {
let prefetch = ['/T0t411y-R4D-Sans']
event.waitUntil(caches.open(CURRENT_CACHE['prefetch'])
.then(cache =>
cache.addAll(prefetch.map((url) =>
new Request(url, { 'mode': 'no-cors' })
))
)
)
})
self.addEventListener('fetch', event => {
event.respondWith(caches.match(event.request)
.then((response) => {
if (response) {
return response;
}
return fetch(event.request)
.then(response => response);
}));
});
self.addEventListener('fetch', event => {
event.respondWith(caches.match(event.request)
.then((response) => {
if (response) {
return response;
}
return fetch(event.request)
.then(response => response);
}));
});
self.addEventListener('fetch', event => {
event.respondWith(caches.match(event.request)
.then((response) => {
if (response) {
return response;
}
return fetch(event.request)
.then(response => response);
}));
});
:(
AppCache
@JaffaTheCake
ServiceWorker > AppCache
...but it covers our use case
if('serviceWorker' in navigator) {
navigator.serviceWorker.register('/serviceworker.js')
} else if ('applicationCache' in window) {
// add AppCache
}
<html lang="en" manifest="/offline.appcache">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
...
<html lang="en" manifest="/offline.appcache">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
...
if('serviceWorker' in navigator) {
navigator.serviceWorker.register('/serviceworker.js')
} else if ('applicationCache' in window) {
// add AppCache
}
let iframe = document.createElement('iframe')
iframe.style.display = 'none'
iframe.src = '/load-appcache.html'
document.body.appendChild(iframe)
let iframe = document.createElement('iframe')
iframe.style.display = 'none'
iframe.src = '/load-appcache.html'
document.body.appendChild(iframe)
let iframe = document.createElement('iframe')
iframe.style.display = 'none'
iframe.src = '/load-appcache.html'
document.body.appendChild(iframe)
let iframe = document.createElement('iframe')
iframe.style.display = 'none'
iframe.src = '/load-appcache.html'
document.body.appendChild(iframe)
<html manifest="/offline.appcache">
<head>
<title>loading douchebags</title>
</head>
<body></body>
</html>
CACHE MANIFEST
/
/download
/css/main.css
/img/logo.svg
/js/build.js
NETWORK:
*
CACHE MANIFEST
/
/download
/css/main.css
/img/logo.svg
/js/build.js
NETWORK:
*
CACHE MANIFEST
/
/download
/css/main.css
/img/logo.svg
/js/build.js
NETWORK:
*
CACHE MANIFEST
/
/download
/css/main.css
/img/logo.svg
/js/build.js
NETWORK:
*
20.7 seconds
190 milliseconds
@JaffaTheCake
radical new way to
create web sites
radical new way to
update web sites
WebWorkers
commit 90b52e847359ae902d3f7ce7bc511cadfbc29ea8
Author: Alexey Proskuryakov <ap@webkit.org>
Date: Thu Nov 6 07:04:47 +0000
Implement Worker global object
2008!
WebWorkers?
single threaded
by default
everything is fighting
for CPU time
lots of number crunchin’
===
hardcore jank
Offload tasks to
background thread
super expensive fns
become pretty cheap
@PatrickKettner
@PatrickKettner
@PatrickKettner
https://github.com/nolan
lawson/pokedex.org
Web App Manifest
{
"lang": "en",
"dir": "ltr",
"name": "Super Racer 2000",
"description": "The ultimate futuristic racing game from the future!",
"short_name": "Racer2K",
"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"
}
{
"lang": "en",
"dir": "ltr",
"name": "Super Racer 2000",
"description": "The ultimate futuristic racing game from the future!",
"short_name": "Racer2K",
"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"
}
{
"lang": "en",
"dir": "ltr",
"name": "Super Racer 2000",
"description": "The ultimate futuristic racing game from the future!",
"short_name": "Racer2K",
"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"
}
{
"lang": "en",
"dir": "ltr",
"name": "Super Racer 2000",
"description": "The ultimate futuristic racing game from the future!",
"short_name": "Racer2K",
"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"
}
{
"lang": "en",
"dir": "ltr",
"name": "Super Racer 2000",
"description": "The ultimate futuristic racing game from the future!",
"short_name": "Racer2K",
"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"
}
{
"lang": "en",
"dir": "ltr",
"name": "Super Racer 2000",
"description": "The ultimate futuristic racing game from the future!",
"short_name": "Racer2K",
"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"
}
{
"lang": "en",
"dir": "ltr",
"name": "Super Racer 2000",
"description": "The ultimate futuristic racing game from the future!",
"short_name": "Racer2K",
"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"
}
{
"lang": "en",
"dir": "ltr",
"name": "Super Racer 2000",
"description": "The ultimate futuristic racing game from the future!",
"short_name": "Racer2K",
"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"
}
{
"lang": "en",
"dir": "ltr",
"name": "Super Racer 2000",
"description": "The ultimate futuristic racing game from the future!",
"short_name": "Racer2K",
"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"
}
"related_applications": [{
”platform": ”play",
”url": "https://play.google.com/store/apps/details?id=com.example.app1",
”id": "com.example.app1"
},{
"platform": ”itunes",
”url": "https://itunes.apple.com/app/example-app1/id123456789"
}, {
”platform": ”windows",
”url": "ms-windows-store://pdp?PFN=Example.App_pfhei292v8qza"
}],
"prefer_related_applications": false,
"related_applications": [{
”platform": ”play",
”url": "https://play.google.com/store/apps/details?id=com.example.app1",
”id": "com.example.app1"
},{
"platform": ”itunes",
”url": "https://itunes.apple.com/app/example-app1/id123456789"
}, {
”platform": ”windows",
”url": "ms-windows-store://pdp?PFN=Example.App_pfhei292v8qza"
}],
"prefer_related_applications": false,
<html lang=en dir=ltr>
<head>
<title>Racer2K</title>
<meta name=application-name content="Super Racer 2000”>
<meta name=description content="The ultimate futuristic game"/>
<meta name=apple-mobile-web-app-capable content=yes>
<link rel=manifest href="manifest.webmanifest">
<meta name=screen-orientation content=landscape>
<meta name=theme-color content=aliceblue>
<link rel=favicon href="icon/lowres.png">
<meta name="msApplication-PackageFamilyName" content="Example

<link rel=alternate href="ios-app://id123456789/racer/begin">
<link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png">
<link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png">
<link rel=start href="/racer/start.html">
<html lang=en dir=ltr>
<head>
<title>Racer2K</title>
<meta name=application-name content="Super Racer 2000”>
<meta name=description content="The ultimate futuristic game”>
<meta name=apple-mobile-web-app-capable content=yes>
<link rel=manifest href="manifest.webmanifest">
<meta name=screen-orientation content=landscape>
<meta name=theme-color content=aliceblue>
<link rel=favicon href="icon/lowres.png">
<meta name="msApplication-PackageFamilyName" content="Example

<link rel=alternate href="ios-app://id123456789/racer/begin">
<link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png">
<link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png">
<link rel=start href="/racer/start.html">
{
"lang": "en",
"dir": "ltr",
"name": "Super Racer 2000",
"description": "The ultimate futuristic racing game from the future!",
"short_name": "Racer2K",
"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"
}
<html lang=en dir=ltr>
<head>
<title>Racer2K</title>
<meta name=application-name content="Super Racer 2000”>
<meta name=description content="The ultimate futuristic game”>
<meta name=apple-mobile-web-app-capable content=yes>
<link rel=manifest href="manifest.webmanifest">
<meta name=screen-orientation content=landscape>
<meta name=theme-color content=aliceblue>
<link rel=favicon href="icon/lowres.png">
<meta name="msApplication-PackageFamilyName" content="Example

<link rel=alternate href="ios-app://id123456789/racer/begin">
<link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png">
<link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png">
<link rel=start href="/racer/start.html">
<html lang=en dir=ltr>
<head>
<title>Racer2K</title>
<meta name=application-name content="Super Racer 2000”>
<meta name=description content="The ultimate futuristic game”>
<meta name=apple-mobile-web-app-capable content=yes>
<link rel=manifest href="manifest.webmanifest">
<meta name=screen-orientation content=landscape>
<meta name=theme-color content=aliceblue>
<link rel=favicon href="icon/lowres.png">
<meta name="msApplication-PackageFamilyName" content="Example

<link rel=alternate href="ios-app://id123456789/racer/begin">
<link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png">
<link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png">
<link rel=start href="/racer/start.html">
let cheerio = require(’cheerio')
let cld = require('cld')
let getLang = (html, callback) => {
let $ = cheerio.load(html)
let lang = $('html[lang]').attr(‘lang')
if (!lang) {
lang = $('html[xml:lang]').attr(‘xml:lang’)
}
if (!lang) {
lang = $(’meta[name:”dc.language”]').attr(‘content’)
}
...
let cheerio = require(’cheerio')
let cld = require('cld')
let getLang = (html, callback) => {
let $ = cheerio.load(html)
let lang = $('html[lang]').attr(‘lang')
if (!lang) {
lang = $('html[xml:lang]').attr(‘xml:lang’)
}
if (!lang) {
lang = $(’meta[name:”dc.language”]').attr(‘content’)
}
...
let cheerio = require(’cheerio')
let cld = require('cld')
let getLang = (html, callback) => {
let $ = cheerio.load(html)
let lang = $('html[lang]').attr(‘lang')
if (!lang) {
lang = $('html[xml:lang]').attr(‘xml:lang’)
}
if (!lang) {
lang = $(’meta[name:”dc.language”]').attr(‘content’)
}
...
let cheerio = require(’cheerio')
let cld = require('cld')
let getLang = (html, callback) => {
let $ = cheerio.load(html)
let lang = $('html[lang]').attr(‘lang')
if (!lang) {
lang = $('html[xml:lang]').attr(‘xml:lang’)
}
if (!lang) {
lang = $(’meta[name:”dc.language”]').attr(‘content’)
}
...
let cheerio = require(’cheerio')
let cld = require('cld')
let getLang = (html, callback) => {
let $ = cheerio.load(html)
let lang = $('html[lang]').attr(‘lang')
if (!lang) {
lang = $('html[xml:lang]').attr(‘xml:lang’)
}
if (!lang) {
lang = $(’meta[name:”dc.language”]').attr(‘content’)
}
...
let cheerio = require(’cheerio')
let cld = require('cld')
let getLang = (html, callback) => {
let $ = cheerio.load(html)
let lang = $('html[lang]').attr(‘lang')
if (!lang) {
lang = $('html[xml:lang]').attr(‘xml:lang’)
}
if (!lang) {
lang = $(’meta[name:”dc.language”]').attr(‘content’)
}
...
cld.detect(html,{isHTML: true},(err, result) => {
if (!err && result.reliable) {
lang = result.language.code
}
callback(err, lang)
}
let url = require(’url')
let async = require(’async’)
let icojs = require(’icojs')
let cheerio = require(’cheerio')
let request= require(’request')
let imgsize = require(’image-size')
let imgtype = require(’image-type')
let mime = require(’./mime-types’).lookup
let FilteType = require(’file-type')
let flatten = require(’lodash/flattenDeep')
let filter = require(’lodash/filter')
let icons = (obj, callback) => {
let $ = cheerio.load(html)
let favicon = $(’rel[“shortcut icon”]').attr(‘href')
<link rel=favicon href="icon.ico">
<link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png">
<link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png”><meta
name="msApplication-TileImage" content=”icon/tile.png”>
<meta name="msApplication-config" content=”tileConfig.xml”>
<link rel=favicon href="icon.ico">
<link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png">
<link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png">
<meta name="msApplication-TileImage" content=”icon/tile.png”>
<meta name="msApplication-config" content=”tileConfig.xml”>
<link rel=favicon href="icon.ico">
<link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png">
<link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png">
<meta name="msApplication-TileImage" content=”icon/tile.png”>
<meta name="msApplication-config" content=”tileConfig.xml”>
<link rel=favicon href="icon.ico">
<link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png">
<link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png">
<meta name="msApplication-TileImage" content=”icon/tile.png”>
<meta name="msApplication-config" content=”tileConfig.xml”>
https://WebManife.st
<html lang=en dir=ltr>
<head>
<title>Racer2K</title>
<meta name=application-name content="Super Racer 2000”>
<meta name=description content="The ultimate futuristic game"/>
<meta name=apple-mobile-web-app-capable content=yes>
<link rel=manifest href="manifest.webmanifest">
<meta name=screen-orientation content=landscape>
<meta name=theme-color content=aliceblue>
<link rel=favicon href="icon/lowres.png">
<meta name="msApplication-PackageFamilyName" content="Example

<link rel=alternate href="ios-app://id123456789/racer/begin">
<link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png">
<link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png">
<link rel=start href="/racer/start.html">
https://WebManife.st/validator
https://WebManife.st/spec
<html lang=en dir=ltr>
<head>
<title>Racer2K</title>
<meta name=application-name content="Super Racer 2000”>
<meta name=description content="The ultimate futuristic game"/>
<meta name=apple-mobile-web-app-capable content=yes>
<link rel=manifest href="manifest.webmanifest">
<meta name=screen-orientation content=landscape>
<meta name=theme-color content=aliceblue>
<link rel=favicon href="icon/lowres.png">
<meta name="msApplication-PackageFamilyName" content="Example

<link rel=alternate href="ios-app://id123456789/racer/begin">
<link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png">
<link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png">
<link rel=start href="/racer/start.html">
let methodData = [{
supportedMethods: [’basic-card'],
data: {
supportedNetworks: [’visa', ’mastercard', ’amex'],
supportedTypes: [’credit']
}
}];
let details = {
total: {
label: ’Total Due',
amount: { currency: ’USD', value : ’109.00' }
}};
var options = {
requestShipping: true
};
let methodData = [{
supportedMethods: [’basic-card'],
data: {
supportedNetworks: [’visa', ’mastercard', ’amex'],
supportedTypes: [’credit']
}
}];
let details = {
total: {
label: ’Total Due',
amount: { currency: ’USD', value : ’109.00' }
}};
var options = {
requestShipping: true
};
let methodData = [{
supportedMethods: [’basic-card'],
data: {
supportedNetworks: [’visa', ’mastercard', ’amex'],
supportedTypes: [’credit']
}
}];
let details = {
total: {
label: ’Total Due',
amount: { currency: ’USD', value : ’109.00' }
}};
var options = {
requestShipping: true
};
if (’PaymentRequest’ in window) {
let payment = new PaymentRequest(methodData, details, options)
}
if (’PaymentRequest’ in window) {
let payment = new PaymentRequest(methodData, details, options)
} else {
window.location.href = ‘/old-checkout’
}
if (’Windows’ in window) {
...
}
bluetooth
Windows​.Devices​.Bluetooth
media keys
Windows.​Media.​Dial​Protocol
ocr
Windows.​Media.​Ocr
cortana
Windows​.ApplicationModel​.VoiceCommands
IndexedDB
commit 4334db65c2718d304d4792fbeb46f96e9d798b76
Author: Ben Turner <bent@mozilla.com>
Date: Wed Jun 23 19:46:00 2010 +0000
Implement Asynchronous parts of the Indexed Database
API
localStorage.setItem(’foo', ’bar');
localStorage.getItem(’foo’) //bar
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
if (!window.indexedDB) {
alert("Sorry!Your browser doesn't support IndexedDB");
}
var database;
var request = window.indexedDB.open("foobar",1);
request.onerror = function(event) {
console.log(event.target.errorCode);
};
request.onsuccess = function(event) {
database=request.result;
};
request.onupgradeneeded = function(event) {
var db = event.target.result;
var objectStore = db.createObjectStore("notes", { keyPath: "id",autoIncrement:true});
};
var note={title:"foo", body:"bar", date:”06/21/2016”};
var transaction = database.transaction(["hello"], "readwrite");
var objectStore = transaction.objectStore("world");
var request=objectStore.put(note);
request.onsuccess = function(event) {
//do something here
};
var objectStore = database.transaction("hello").objectStore("world");
objectStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
alert("Note id: "+cursor.key+", Title: "+cursor.value.title);
cursor.continue();
}
};
window.name
document.cookie
Flash Cache
IndexedDB
localStorage
AppCache
Cache API
WebSQL
window.name
document.cookie
Flash Cache
IndexedDB
localStorage
AppCache
Cache API
WebSQL
window.name
document.cookie
Flash Cache
IndexedDB
localStorage
AppCache
Cache API
WebSQL
window.name
document.cookie
Flash Cache
IndexedDB
localStorage
AppCache
Cache API
WebSQL
var db = new Dexie('MyDatabase');
db.friends
.where(‘age’)
.above(75)
.each((friend) => {
console.log(friend.name);
});
localForage.setItem(’foo', ’bar');
localForage.getItem(’foo’, (err, val) => {
console.log(val)
}
))
with a G
demo.agektmr.com/storage
don’t wait for a rearch
use the new shiny.
make awesome stuff.
github.com/PatrickKettner
twitter.com/PatrickKettner
facebook.com/PatrickKettner
PatKet@microsoft.com
Thanks!

Weitere Àhnliche Inhalte

Was ist angesagt?

Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesLindsay Holmwood
 
And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...Codemotion
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your AppLuca Mearelli
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Eric Palakovich Carr
 
Javascript is your (Auto)mate
Javascript is your (Auto)mateJavascript is your (Auto)mate
Javascript is your (Auto)mateCodemotion
 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010ikailan
 
Beyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the codeBeyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the codeWim Godden
 
JavaScript APIs - The Web is the Platform - MDN Hack Day, Sao Paulo
JavaScript APIs - The Web is the Platform - MDN Hack Day, Sao PauloJavaScript APIs - The Web is the Platform - MDN Hack Day, Sao Paulo
JavaScript APIs - The Web is the Platform - MDN Hack Day, Sao PauloRobert Nyman
 
Web Crawling with NodeJS
Web Crawling with NodeJSWeb Crawling with NodeJS
Web Crawling with NodeJSSylvain Zimmer
 
Leave No One Behind with HTML5 - FFWD.PRO, Croatia
Leave No One Behind with HTML5 - FFWD.PRO, CroatiaLeave No One Behind with HTML5 - FFWD.PRO, Croatia
Leave No One Behind with HTML5 - FFWD.PRO, CroatiaRobert Nyman
 
CodeIgniter 3.0
CodeIgniter 3.0CodeIgniter 3.0
CodeIgniter 3.0Phil Sturgeon
 
Into the ZF2 Service Manager
Into the ZF2 Service ManagerInto the ZF2 Service Manager
Into the ZF2 Service ManagerChris Tankersley
 
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)Brian Sam-Bodden
 
Controlling The Cloud With Python
Controlling The Cloud With PythonControlling The Cloud With Python
Controlling The Cloud With PythonLuca Mearelli
 
ES6, 잘 ì“°êł  êł„ì‹œìŁ ?
ES6, 잘 ì“°êł  êł„ì‹œìŁ ?ES6, 잘 ì“°êł  êł„ì‹œìŁ ?
ES6, 잘 ì“°êł  êł„ì‹œìŁ ?임현 한
 
AJAX Transport Layer
AJAX Transport LayerAJAX Transport Layer
AJAX Transport LayerSiarhei Barysiuk
 
To Batch Or Not To Batch
To Batch Or Not To BatchTo Batch Or Not To Batch
To Batch Or Not To BatchLuca Mearelli
 
Puppet Camp Seattle 2014: Puppet: Cloud Infrastructure as Code
Puppet Camp Seattle 2014: Puppet: Cloud Infrastructure as CodePuppet Camp Seattle 2014: Puppet: Cloud Infrastructure as Code
Puppet Camp Seattle 2014: Puppet: Cloud Infrastructure as CodePuppet
 

Was ist angesagt? (20)

Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websites
 
And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your App
 
Makezine
MakezineMakezine
Makezine
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!
 
Javascript is your (Auto)mate
Javascript is your (Auto)mateJavascript is your (Auto)mate
Javascript is your (Auto)mate
 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010
 
Beyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the codeBeyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the code
 
QA for PHP projects
QA for PHP projectsQA for PHP projects
QA for PHP projects
 
JavaScript APIs - The Web is the Platform - MDN Hack Day, Sao Paulo
JavaScript APIs - The Web is the Platform - MDN Hack Day, Sao PauloJavaScript APIs - The Web is the Platform - MDN Hack Day, Sao Paulo
JavaScript APIs - The Web is the Platform - MDN Hack Day, Sao Paulo
 
Web Crawling with NodeJS
Web Crawling with NodeJSWeb Crawling with NodeJS
Web Crawling with NodeJS
 
Leave No One Behind with HTML5 - FFWD.PRO, Croatia
Leave No One Behind with HTML5 - FFWD.PRO, CroatiaLeave No One Behind with HTML5 - FFWD.PRO, Croatia
Leave No One Behind with HTML5 - FFWD.PRO, Croatia
 
CodeIgniter 3.0
CodeIgniter 3.0CodeIgniter 3.0
CodeIgniter 3.0
 
Into the ZF2 Service Manager
Into the ZF2 Service ManagerInto the ZF2 Service Manager
Into the ZF2 Service Manager
 
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
 
Controlling The Cloud With Python
Controlling The Cloud With PythonControlling The Cloud With Python
Controlling The Cloud With Python
 
ES6, 잘 ì“°êł  êł„ì‹œìŁ ?
ES6, 잘 ì“°êł  êł„ì‹œìŁ ?ES6, 잘 ì“°êł  êł„ì‹œìŁ ?
ES6, 잘 ì“°êł  êł„ì‹œìŁ ?
 
AJAX Transport Layer
AJAX Transport LayerAJAX Transport Layer
AJAX Transport Layer
 
To Batch Or Not To Batch
To Batch Or Not To BatchTo Batch Or Not To Batch
To Batch Or Not To Batch
 
Puppet Camp Seattle 2014: Puppet: Cloud Infrastructure as Code
Puppet Camp Seattle 2014: Puppet: Cloud Infrastructure as CodePuppet Camp Seattle 2014: Puppet: Cloud Infrastructure as Code
Puppet Camp Seattle 2014: Puppet: Cloud Infrastructure as Code
 

Ähnlich wie Progressive What Apps?

The Future of CSS with Web components
The Future of CSS with Web componentsThe Future of CSS with Web components
The Future of CSS with Web componentsdevObjective
 
The Future of CSS with Web Components
The Future of CSS with Web ComponentsThe Future of CSS with Web Components
The Future of CSS with Web ComponentsColdFusionConference
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)Igor Bronovskyy
 
HTML5: huh, what is it good for?
HTML5: huh, what is it good for?HTML5: huh, what is it good for?
HTML5: huh, what is it good for?Remy Sharp
 
How to replace rails asset pipeline with webpack?
How to replace rails asset pipeline with webpack?How to replace rails asset pipeline with webpack?
How to replace rails asset pipeline with webpack?Tomasz Bak
 
Service Worker - Reliability bits
Service Worker - Reliability bitsService Worker - Reliability bits
Service Worker - Reliability bitsjungkees
 
Building Progressive Web Apps for Windows devices
Building Progressive Web Apps for Windows devicesBuilding Progressive Web Apps for Windows devices
Building Progressive Web Apps for Windows devicesWindows Developer
 
Cloud Endpoints _Polymer_ Material design by Martin Görner
Cloud Endpoints_Polymer_Material design by Martin GörnerCloud Endpoints_Polymer_Material design by Martin Görner
Cloud Endpoints _Polymer_ Material design by Martin GörnerEuropean Innovation Academy
 
Micro app-framework - NodeLive Boston
Micro app-framework - NodeLive BostonMicro app-framework - NodeLive Boston
Micro app-framework - NodeLive BostonMichael Dawson
 
Micro app-framework
Micro app-frameworkMicro app-framework
Micro app-frameworkMichael Dawson
 
Private slideshow
Private slideshowPrivate slideshow
Private slideshowsblackman
 
Mozilla Web Apps - Super-VanJS
Mozilla Web Apps - Super-VanJSMozilla Web Apps - Super-VanJS
Mozilla Web Apps - Super-VanJSRobert Nyman
 
JavaScript APIs - The Web is the Platform
JavaScript APIs - The Web is the PlatformJavaScript APIs - The Web is the Platform
JavaScript APIs - The Web is the PlatformRobert Nyman
 
20160905 - BrisJS - nightwatch testing
20160905 - BrisJS - nightwatch testing20160905 - BrisJS - nightwatch testing
20160905 - BrisJS - nightwatch testingVladimir Roudakov
 
HTML5: friend or foe (to Flash)?
HTML5: friend or foe (to Flash)?HTML5: friend or foe (to Flash)?
HTML5: friend or foe (to Flash)?Remy Sharp
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackIgnacio MartĂ­n
 
Running Vue Storefront in production (PWA Magento webshop)
Running Vue Storefront in production (PWA Magento webshop)Running Vue Storefront in production (PWA Magento webshop)
Running Vue Storefront in production (PWA Magento webshop)Vendic Magento, PWA & Marketing
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Chris Alfano
 
Html5 For Jjugccc2009fall
Html5 For Jjugccc2009fallHtml5 For Jjugccc2009fall
Html5 For Jjugccc2009fallShumpei Shiraishi
 

Ähnlich wie Progressive What Apps? (20)

The Future of CSS with Web components
The Future of CSS with Web componentsThe Future of CSS with Web components
The Future of CSS with Web components
 
The Future of CSS with Web Components
The Future of CSS with Web ComponentsThe Future of CSS with Web Components
The Future of CSS with Web Components
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
 
HTML5: huh, what is it good for?
HTML5: huh, what is it good for?HTML5: huh, what is it good for?
HTML5: huh, what is it good for?
 
How to replace rails asset pipeline with webpack?
How to replace rails asset pipeline with webpack?How to replace rails asset pipeline with webpack?
How to replace rails asset pipeline with webpack?
 
Service Worker - Reliability bits
Service Worker - Reliability bitsService Worker - Reliability bits
Service Worker - Reliability bits
 
Building Progressive Web Apps for Windows devices
Building Progressive Web Apps for Windows devicesBuilding Progressive Web Apps for Windows devices
Building Progressive Web Apps for Windows devices
 
Intro to HTML5
Intro to HTML5Intro to HTML5
Intro to HTML5
 
Cloud Endpoints _Polymer_ Material design by Martin Görner
Cloud Endpoints_Polymer_Material design by Martin GörnerCloud Endpoints_Polymer_Material design by Martin Görner
Cloud Endpoints _Polymer_ Material design by Martin Görner
 
Micro app-framework - NodeLive Boston
Micro app-framework - NodeLive BostonMicro app-framework - NodeLive Boston
Micro app-framework - NodeLive Boston
 
Micro app-framework
Micro app-frameworkMicro app-framework
Micro app-framework
 
Private slideshow
Private slideshowPrivate slideshow
Private slideshow
 
Mozilla Web Apps - Super-VanJS
Mozilla Web Apps - Super-VanJSMozilla Web Apps - Super-VanJS
Mozilla Web Apps - Super-VanJS
 
JavaScript APIs - The Web is the Platform
JavaScript APIs - The Web is the PlatformJavaScript APIs - The Web is the Platform
JavaScript APIs - The Web is the Platform
 
20160905 - BrisJS - nightwatch testing
20160905 - BrisJS - nightwatch testing20160905 - BrisJS - nightwatch testing
20160905 - BrisJS - nightwatch testing
 
HTML5: friend or foe (to Flash)?
HTML5: friend or foe (to Flash)?HTML5: friend or foe (to Flash)?
HTML5: friend or foe (to Flash)?
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
 
Running Vue Storefront in production (PWA Magento webshop)
Running Vue Storefront in production (PWA Magento webshop)Running Vue Storefront in production (PWA Magento webshop)
Running Vue Storefront in production (PWA Magento webshop)
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011
 
Html5 For Jjugccc2009fall
Html5 For Jjugccc2009fallHtml5 For Jjugccc2009fall
Html5 For Jjugccc2009fall
 

KĂŒrzlich hochgeladen

How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍾 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍾 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍾 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍾 8923113531 🎰 Avail...gurkirankumar98700
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 

KĂŒrzlich hochgeladen (20)

How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍾 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍾 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍾 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍾 8923113531 🎰 Avail...
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 

Progressive What Apps?

  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18. 2G Ruined My Day45M Ruined My Day
  • 19.
  • 20.
  • 21. When you don’t have a better idea, buy a novelty domain
  • 24. let CURRENT_CACHE = { prefetch: 'prefetch-cache-v1' }; self.addEventListener('install', event => { let prefetch = ['/T0t411y-R4D-Sans'] event.waitUntil(caches.open(CURRENT_CACHE['prefetch']) .then(cache => cache.addAll(prefetch.map((url) => new Request(url, { 'mode': 'no-cors' }) )) ) ) })
  • 25. let CURRENT_CACHE = { prefetch: 'prefetch-cache-v1' }; self.addEventListener('install', event => { let prefetch = ['/T0t411y-R4D-Sans'] event.waitUntil(caches.open(CURRENT_CACHE['prefetch']) .then(cache => cache.addAll(prefetch.map((url) => new Request(url, { 'mode': 'no-cors' }) )) ) ) })
  • 26. let CURRENT_CACHE = { prefetch: 'prefetch-cache-v1' }; self.addEventListener('install', event => { let prefetch = ['/T0t411y-R4D-Sans'] event.waitUntil(caches.open(CURRENT_CACHE['prefetch']) .then(cache => cache.addAll(prefetch.map((url) => new Request(url, { 'mode': 'no-cors' }) )) ) ) })
  • 27. let CURRENT_CACHE = { prefetch: 'prefetch-cache-v1' }; self.addEventListener('install', event => { let prefetch = ['/T0t411y-R4D-Sans'] event.waitUntil(caches.open(CURRENT_CACHE['prefetch']) .then(cache => cache.addAll(prefetch.map((url) => new Request(url, { 'mode': 'no-cors' }) )) ) ) })
  • 28. let CURRENT_CACHE = { prefetch: 'prefetch-cache-v1' }; self.addEventListener('install', event => { let prefetch = ['/T0t411y-R4D-Sans'] event.waitUntil(caches.open(CURRENT_CACHE['prefetch']) .then(cache => cache.addAll(prefetch.map((url) => new Request(url, { 'mode': 'no-cors' }) )) ) ) })
  • 29. let CURRENT_CACHE = { prefetch: 'prefetch-cache-v1' }; self.addEventListener('install', event => { let prefetch = ['/T0t411y-R4D-Sans'] event.waitUntil(caches.open(CURRENT_CACHE['prefetch']) .then(cache => cache.addAll(prefetch.map((url) => new Request(url, { 'mode': 'no-cors' }) )) ) ) })
  • 30. self.addEventListener('fetch', event => { event.respondWith(caches.match(event.request) .then((response) => { if (response) { return response; } return fetch(event.request) .then(response => response); })); });
  • 31. self.addEventListener('fetch', event => { event.respondWith(caches.match(event.request) .then((response) => { if (response) { return response; } return fetch(event.request) .then(response => response); })); });
  • 32. self.addEventListener('fetch', event => { event.respondWith(caches.match(event.request) .then((response) => { if (response) { return response; } return fetch(event.request) .then(response => response); })); });
  • 33.
  • 34.
  • 35.
  • 36. :(
  • 40.
  • 41. ...but it covers our use case
  • 42.
  • 43. if('serviceWorker' in navigator) { navigator.serviceWorker.register('/serviceworker.js') } else if ('applicationCache' in window) { // add AppCache }
  • 44. <html lang="en" manifest="/offline.appcache"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> ...
  • 45. <html lang="en" manifest="/offline.appcache"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> ...
  • 46. if('serviceWorker' in navigator) { navigator.serviceWorker.register('/serviceworker.js') } else if ('applicationCache' in window) { // add AppCache }
  • 47. let iframe = document.createElement('iframe') iframe.style.display = 'none' iframe.src = '/load-appcache.html' document.body.appendChild(iframe)
  • 48. let iframe = document.createElement('iframe') iframe.style.display = 'none' iframe.src = '/load-appcache.html' document.body.appendChild(iframe)
  • 49. let iframe = document.createElement('iframe') iframe.style.display = 'none' iframe.src = '/load-appcache.html' document.body.appendChild(iframe)
  • 50. let iframe = document.createElement('iframe') iframe.style.display = 'none' iframe.src = '/load-appcache.html' document.body.appendChild(iframe)
  • 59.
  • 60.
  • 61.
  • 62. radical new way to create web sites
  • 63. radical new way to update web sites
  • 65. commit 90b52e847359ae902d3f7ce7bc511cadfbc29ea8 Author: Alexey Proskuryakov <ap@webkit.org> Date: Thu Nov 6 07:04:47 +0000 Implement Worker global object
  • 66. 2008!
  • 67.
  • 68.
  • 69.
  • 70.
  • 74. lots of number crunchin’ === hardcore jank
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 85.
  • 89.
  • 90. { "lang": "en", "dir": "ltr", "name": "Super Racer 2000", "description": "The ultimate futuristic racing game from the future!", "short_name": "Racer2K", "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" }
  • 91. { "lang": "en", "dir": "ltr", "name": "Super Racer 2000", "description": "The ultimate futuristic racing game from the future!", "short_name": "Racer2K", "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" }
  • 92. { "lang": "en", "dir": "ltr", "name": "Super Racer 2000", "description": "The ultimate futuristic racing game from the future!", "short_name": "Racer2K", "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" }
  • 93. { "lang": "en", "dir": "ltr", "name": "Super Racer 2000", "description": "The ultimate futuristic racing game from the future!", "short_name": "Racer2K", "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" }
  • 94. { "lang": "en", "dir": "ltr", "name": "Super Racer 2000", "description": "The ultimate futuristic racing game from the future!", "short_name": "Racer2K", "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" }
  • 95. { "lang": "en", "dir": "ltr", "name": "Super Racer 2000", "description": "The ultimate futuristic racing game from the future!", "short_name": "Racer2K", "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" }
  • 96. { "lang": "en", "dir": "ltr", "name": "Super Racer 2000", "description": "The ultimate futuristic racing game from the future!", "short_name": "Racer2K", "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" }
  • 97. { "lang": "en", "dir": "ltr", "name": "Super Racer 2000", "description": "The ultimate futuristic racing game from the future!", "short_name": "Racer2K", "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" }
  • 98. { "lang": "en", "dir": "ltr", "name": "Super Racer 2000", "description": "The ultimate futuristic racing game from the future!", "short_name": "Racer2K", "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" }
  • 99. "related_applications": [{ ”platform": ”play", ”url": "https://play.google.com/store/apps/details?id=com.example.app1", ”id": "com.example.app1" },{ "platform": ”itunes", ”url": "https://itunes.apple.com/app/example-app1/id123456789" }, { ”platform": ”windows", ”url": "ms-windows-store://pdp?PFN=Example.App_pfhei292v8qza" }], "prefer_related_applications": false,
  • 100. "related_applications": [{ ”platform": ”play", ”url": "https://play.google.com/store/apps/details?id=com.example.app1", ”id": "com.example.app1" },{ "platform": ”itunes", ”url": "https://itunes.apple.com/app/example-app1/id123456789" }, { ”platform": ”windows", ”url": "ms-windows-store://pdp?PFN=Example.App_pfhei292v8qza" }], "prefer_related_applications": false,
  • 101. <html lang=en dir=ltr> <head> <title>Racer2K</title> <meta name=application-name content="Super Racer 2000”> <meta name=description content="The ultimate futuristic game"/> <meta name=apple-mobile-web-app-capable content=yes> <link rel=manifest href="manifest.webmanifest"> <meta name=screen-orientation content=landscape> <meta name=theme-color content=aliceblue> <link rel=favicon href="icon/lowres.png"> <meta name="msApplication-PackageFamilyName" content="Example
 <link rel=alternate href="ios-app://id123456789/racer/begin"> <link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png"> <link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png"> <link rel=start href="/racer/start.html">
  • 102. <html lang=en dir=ltr> <head> <title>Racer2K</title> <meta name=application-name content="Super Racer 2000”> <meta name=description content="The ultimate futuristic game”> <meta name=apple-mobile-web-app-capable content=yes> <link rel=manifest href="manifest.webmanifest"> <meta name=screen-orientation content=landscape> <meta name=theme-color content=aliceblue> <link rel=favicon href="icon/lowres.png"> <meta name="msApplication-PackageFamilyName" content="Example
 <link rel=alternate href="ios-app://id123456789/racer/begin"> <link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png"> <link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png"> <link rel=start href="/racer/start.html">
  • 103. { "lang": "en", "dir": "ltr", "name": "Super Racer 2000", "description": "The ultimate futuristic racing game from the future!", "short_name": "Racer2K", "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" }
  • 104. <html lang=en dir=ltr> <head> <title>Racer2K</title> <meta name=application-name content="Super Racer 2000”> <meta name=description content="The ultimate futuristic game”> <meta name=apple-mobile-web-app-capable content=yes> <link rel=manifest href="manifest.webmanifest"> <meta name=screen-orientation content=landscape> <meta name=theme-color content=aliceblue> <link rel=favicon href="icon/lowres.png"> <meta name="msApplication-PackageFamilyName" content="Example
 <link rel=alternate href="ios-app://id123456789/racer/begin"> <link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png"> <link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png"> <link rel=start href="/racer/start.html">
  • 105. <html lang=en dir=ltr> <head> <title>Racer2K</title> <meta name=application-name content="Super Racer 2000”> <meta name=description content="The ultimate futuristic game”> <meta name=apple-mobile-web-app-capable content=yes> <link rel=manifest href="manifest.webmanifest"> <meta name=screen-orientation content=landscape> <meta name=theme-color content=aliceblue> <link rel=favicon href="icon/lowres.png"> <meta name="msApplication-PackageFamilyName" content="Example
 <link rel=alternate href="ios-app://id123456789/racer/begin"> <link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png"> <link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png"> <link rel=start href="/racer/start.html">
  • 106.
  • 107. let cheerio = require(’cheerio') let cld = require('cld') let getLang = (html, callback) => { let $ = cheerio.load(html) let lang = $('html[lang]').attr(‘lang') if (!lang) { lang = $('html[xml:lang]').attr(‘xml:lang’) } if (!lang) { lang = $(’meta[name:”dc.language”]').attr(‘content’) } ...
  • 108. let cheerio = require(’cheerio') let cld = require('cld') let getLang = (html, callback) => { let $ = cheerio.load(html) let lang = $('html[lang]').attr(‘lang') if (!lang) { lang = $('html[xml:lang]').attr(‘xml:lang’) } if (!lang) { lang = $(’meta[name:”dc.language”]').attr(‘content’) } ...
  • 109. let cheerio = require(’cheerio') let cld = require('cld') let getLang = (html, callback) => { let $ = cheerio.load(html) let lang = $('html[lang]').attr(‘lang') if (!lang) { lang = $('html[xml:lang]').attr(‘xml:lang’) } if (!lang) { lang = $(’meta[name:”dc.language”]').attr(‘content’) } ...
  • 110. let cheerio = require(’cheerio') let cld = require('cld') let getLang = (html, callback) => { let $ = cheerio.load(html) let lang = $('html[lang]').attr(‘lang') if (!lang) { lang = $('html[xml:lang]').attr(‘xml:lang’) } if (!lang) { lang = $(’meta[name:”dc.language”]').attr(‘content’) } ...
  • 111. let cheerio = require(’cheerio') let cld = require('cld') let getLang = (html, callback) => { let $ = cheerio.load(html) let lang = $('html[lang]').attr(‘lang') if (!lang) { lang = $('html[xml:lang]').attr(‘xml:lang’) } if (!lang) { lang = $(’meta[name:”dc.language”]').attr(‘content’) } ...
  • 112. let cheerio = require(’cheerio') let cld = require('cld') let getLang = (html, callback) => { let $ = cheerio.load(html) let lang = $('html[lang]').attr(‘lang') if (!lang) { lang = $('html[xml:lang]').attr(‘xml:lang’) } if (!lang) { lang = $(’meta[name:”dc.language”]').attr(‘content’) } ...
  • 113. cld.detect(html,{isHTML: true},(err, result) => { if (!err && result.reliable) { lang = result.language.code } callback(err, lang) }
  • 114. let url = require(’url') let async = require(’async’) let icojs = require(’icojs') let cheerio = require(’cheerio') let request= require(’request') let imgsize = require(’image-size') let imgtype = require(’image-type') let mime = require(’./mime-types’).lookup let FilteType = require(’file-type') let flatten = require(’lodash/flattenDeep') let filter = require(’lodash/filter') let icons = (obj, callback) => { let $ = cheerio.load(html) let favicon = $(’rel[“shortcut icon”]').attr(‘href')
  • 115. <link rel=favicon href="icon.ico"> <link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png"> <link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png”><meta name="msApplication-TileImage" content=”icon/tile.png”> <meta name="msApplication-config" content=”tileConfig.xml”>
  • 116. <link rel=favicon href="icon.ico"> <link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png"> <link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png"> <meta name="msApplication-TileImage" content=”icon/tile.png”> <meta name="msApplication-config" content=”tileConfig.xml”>
  • 117. <link rel=favicon href="icon.ico"> <link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png"> <link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png"> <meta name="msApplication-TileImage" content=”icon/tile.png”> <meta name="msApplication-config" content=”tileConfig.xml”>
  • 118. <link rel=favicon href="icon.ico"> <link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png"> <link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png"> <meta name="msApplication-TileImage" content=”icon/tile.png”> <meta name="msApplication-config" content=”tileConfig.xml”>
  • 120.
  • 121.
  • 122. <html lang=en dir=ltr> <head> <title>Racer2K</title> <meta name=application-name content="Super Racer 2000”> <meta name=description content="The ultimate futuristic game"/> <meta name=apple-mobile-web-app-capable content=yes> <link rel=manifest href="manifest.webmanifest"> <meta name=screen-orientation content=landscape> <meta name=theme-color content=aliceblue> <link rel=favicon href="icon/lowres.png"> <meta name="msApplication-PackageFamilyName" content="Example
 <link rel=alternate href="ios-app://id123456789/racer/begin"> <link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png"> <link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png"> <link rel=start href="/racer/start.html">
  • 124. <html lang=en dir=ltr> <head> <title>Racer2K</title> <meta name=application-name content="Super Racer 2000”> <meta name=description content="The ultimate futuristic game"/> <meta name=apple-mobile-web-app-capable content=yes> <link rel=manifest href="manifest.webmanifest"> <meta name=screen-orientation content=landscape> <meta name=theme-color content=aliceblue> <link rel=favicon href="icon/lowres.png"> <meta name="msApplication-PackageFamilyName" content="Example
 <link rel=alternate href="ios-app://id123456789/racer/begin"> <link rel=apple-touch-icon sizes=64x64 href="icon/lowres.png"> <link rel=apple-touch-icon sizes=128x128 href="icon/hd_hi.png"> <link rel=start href="/racer/start.html">
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133. let methodData = [{ supportedMethods: [’basic-card'], data: { supportedNetworks: [’visa', ’mastercard', ’amex'], supportedTypes: [’credit'] } }]; let details = { total: { label: ’Total Due', amount: { currency: ’USD', value : ’109.00' } }}; var options = { requestShipping: true };
  • 134. let methodData = [{ supportedMethods: [’basic-card'], data: { supportedNetworks: [’visa', ’mastercard', ’amex'], supportedTypes: [’credit'] } }]; let details = { total: { label: ’Total Due', amount: { currency: ’USD', value : ’109.00' } }}; var options = { requestShipping: true };
  • 135. let methodData = [{ supportedMethods: [’basic-card'], data: { supportedNetworks: [’visa', ’mastercard', ’amex'], supportedTypes: [’credit'] } }]; let details = { total: { label: ’Total Due', amount: { currency: ’USD', value : ’109.00' } }}; var options = { requestShipping: true };
  • 136. if (’PaymentRequest’ in window) { let payment = new PaymentRequest(methodData, details, options) }
  • 137. if (’PaymentRequest’ in window) { let payment = new PaymentRequest(methodData, details, options) } else { window.location.href = ‘/old-checkout’ }
  • 138.
  • 139.
  • 140. if (’Windows’ in window) { ... }
  • 146. commit 4334db65c2718d304d4792fbeb46f96e9d798b76 Author: Ben Turner <bent@mozilla.com> Date: Wed Jun 23 19:46:00 2010 +0000 Implement Asynchronous parts of the Indexed Database API
  • 148. window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction; window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange; if (!window.indexedDB) { alert("Sorry!Your browser doesn't support IndexedDB"); } var database; var request = window.indexedDB.open("foobar",1); request.onerror = function(event) { console.log(event.target.errorCode); }; request.onsuccess = function(event) { database=request.result; }; request.onupgradeneeded = function(event) { var db = event.target.result; var objectStore = db.createObjectStore("notes", { keyPath: "id",autoIncrement:true}); }; var note={title:"foo", body:"bar", date:”06/21/2016”}; var transaction = database.transaction(["hello"], "readwrite"); var objectStore = transaction.objectStore("world"); var request=objectStore.put(note); request.onsuccess = function(event) { //do something here }; var objectStore = database.transaction("hello").objectStore("world"); objectStore.openCursor().onsuccess = function(event) { var cursor = event.target.result; if (cursor) { alert("Note id: "+cursor.key+", Title: "+cursor.value.title); cursor.continue(); } };
  • 153.
  • 154. var db = new Dexie('MyDatabase'); db.friends .where(‘age’) .above(75) .each((friend) => { console.log(friend.name); });
  • 155.
  • 157.
  • 159.
  • 161.
  • 162. don’t wait for a rearch
  • 163. use the new shiny.

Hinweis der Redaktion

  1. I know what you are thinking
  2. This is what it looks like Define a cache – you can have separate caches in SWs, one for blog content, another for comments, whatever Listen for the install event Prefetch our font, and anything else we know is guaranteed to want Wait until our cache is opened up, then we request each and every one of those files and add them to our cache
  3. This is what it looks like Define a cache – you can have separate caches in SWs, one for blog content, another for comments, whatever Listen for the install event Prefetch our font, and anything else we know is guaranteed to want Wait until our cache is opened up, then we request each and every one of those files and add them to our cache
  4. This is what it looks like Define a cache – you can have separate caches in SWs, one for blog content, another for comments, whatever Listen for the install event Prefetch our font, and anything else we know is guaranteed to want Wait until our cache is opened up, then we request each and every one of those files and add them to our cache
  5. This is what it looks like Define a cache – you can have separate caches in SWs, one for blog content, another for comments, whatever Listen for the install event Prefetch our font, and anything else we know is guaranteed to want Wait until our cache is opened up, then we request each and every one of those files and add them to our cache
  6. This is what it looks like Define a cache – you can have separate caches in SWs, one for blog content, another for comments, whatever Listen for the install event Prefetch our font, and anything else we know is guaranteed to want Wait until our cache is opened up, then we request each and every one of those files and add them to our cache
  7. This is what it looks like Define a cache – you can have separate caches in SWs, one for blog content, another for comments, whatever Listen for the install event Prefetch our font, and anything else we know is guaranteed to want Wait until our cache is opened up, then we request each and every one of those files and add them to our cache
  8. After we do that, we set up listener for FETCH event Every time anything on the site is requested from our domain, we see if it is in the cache Got it? Give it Don’t? go get it Instantaneous responses, even with dozens upon dozens of requests
  9. After we do that, we set up listener for FETCH event Every time anything on the site is requested from our domain, we see if it is in the cache Got it? Give it Don’t? go get it Instantaneous responses, even with dozens upon dozens of requests
  10. After we do that, we set up listener for FETCH event Every time anything on the site is requested from our domain, we see if it is in the cache Got it? Give it Don’t? go get it Instantaneous responses, even with dozens upon dozens of requests
  11. It IS the future, but support is pretty meh
  12. Which sucks, beause I want something today – not a year or three from now If only we had something widely supported today

  13. I know what you are thinking
  14. Appcache is a douchebag Yes – it really is. It sucksin a lot of ways
  15. SW are WAY better, except for support
  16. SW are WAY better, except for support
  17. And it covers our basic usage of instant cache reading
  18. {{40% done – 20 minutes}} Appcache is everywhere
  19. Do basic namespace check
  20. You put it in your head
  21. You can’t add it programmatically. It HAS to be there on load
  22. Do basic namespace check
  23. We just load it in ANOTHER page Create iframe, load tiny page that is just the appcache manifest
  24. We just load it in ANOTHER page Create iframe, load tiny page that is just the appcache manifest
  25. We just load it in ANOTHER page Create iframe, load tiny page that is just the appcache manifest
  26. We just load it in ANOTHER page Create iframe, load tiny page that is just the appcache manifest
  27. Appcache takes over domain After initial load, firefox - NEXT
  28. Appcache is manifest driven Its just a big text file, with .appcache extension looks like this Blob of text that lists files, and a few rules Dunders are variables that we use to generate this file programatically Cache version important to break cache – just date epoch Assets is list of files to be added to the precache list
  29. Appcache is manifest driven Its just a big text file, with .appcache extension looks like this Blob of text that lists files, and a few rules Dunders are variables that we use to generate this file programatically Cache version important to break cache – just date epoch Assets is list of files to be added to the precache list
  30. Appcache is manifest driven Its just a big text file, with .appcache extension looks like this Blob of text that lists files, and a few rules Dunders are variables that we use to generate this file programatically Cache version important to break cache – just date epoch Assets is list of files to be added to the precache list
  31. Appcache is manifest driven Its just a big text file, with .appcache extension looks like this Blob of text that lists files, and a few rules Dunders are variables that we use to generate this file programatically Cache version important to break cache – just date epoch Assets is list of files to be added to the precache list
  32. Appcache is a douchebag Yes – it really is. It sucksin a lot of ways
  33. Added to webkit ri in 2008
  34. Chroem was in version 2!
  35. Chroem was in version 2!
  36. Chroem was in version 2!
  37. Chroem was in version 2!
  38. So what are they? It is a way to get around some browser limitations without breaking the web
  39. Means browser can only do one thing at a time Browser doesn’t know you won’t change page in scroll loop, So it has to execute code before it can paint the result of the scroll
  40. Scroll handlers, runaway scripts, underpowred machines
 Crappy user expierence
  41. Webworkers lets us take certain tasks, fence them off from the main thread of the browser, and have the browser opportunistically execute that code without effecting the page’s painting
  42. Appcache takes over domain After initial load, firefox - NEXT
  43. Appcache takes over domain After initial load, firefox - NEXT
  44. Appcache takes over domain After initial load, firefox - NEXT
  45. Appcache takes over domain After initial load, firefox - NEXT
  46. Appcache takes over domain After initial load, firefox - NEXT
  47. Appcache takes over domain After initial load, firefox - NEXT
  48. Appcache takes over domain After initial load, firefox - NEXT
  49. Appcache takes over domain After initial load, firefox - NEXT
  50. Appcache takes over domain After initial load, firefox - NEXT
  51. Appcache takes over domain After initial load, firefox - NEXT
  52. Appcache takes over domain After initial load, firefox - NEXT
  53. Appcache takes over domain After initial load, firefox - NEXT
  54. Appcache takes over domain After initial load, firefox - NEXT
  55. Appcache takes over domain After initial load, firefox - NEXT
  56. Appcache takes over domain After initial load, firefox - NEXT
  57. Appcache takes over domain After initial load, firefox - NEXT
  58. Do basic namespace check
  59. Do basic namespace check
  60. Do basic namespace check
  61. Do basic namespace check
  62. Do basic namespace check
  63. Do basic namespace check
  64. Do basic namespace check
  65. Do basic namespace check
  66. Appcache takes over domain After initial load, firefox - NEXT
  67. Appcache takes over domain After initial load, firefox - NEXT
  68. Appcache takes over domain After initial load, firefox - NEXT
  69. Appcache takes over domain After initial load, firefox - NEXT
  70. Appcache takes over domain After initial load, firefox - NEXT
  71. Appcache takes over domain After initial load, firefox - NEXT
  72. Appcache takes over domain After initial load, firefox - NEXT
  73. Appcache takes over domain After initial load, firefox - NEXT
  74. Appcache takes over domain After initial load, firefox - NEXT
  75. Appcache takes over domain After initial load, firefox - NEXT
  76. Appcache takes over domain After initial load, firefox - NEXT
  77. Appcache takes over domain After initial load, firefox - NEXT
  78. Appcache takes over domain After initial load, firefox - NEXT
  79. Appcache takes over domain After initial load, firefox - NEXT
  80. Appcache takes over domain After initial load, firefox - NEXT
  81. Do basic namespace check
  82. Do basic namespace check
  83. Do basic namespace check
  84. Do basic namespace check
  85. Do basic namespace check
  86. Do basic namespace check
  87. So what are they? It is a way to get around some browser limitations without breaking the web
  88. So what are they? It is a way to get around some browser limitations without breaking the web
  89. So what are they? It is a way to get around some browser limitations without breaking the web
  90. So what are they? It is a way to get around some browser limitations without breaking the web
  91. Added to webkit ri in 2008
  92. Browser’s don’t know everything, we just pretend to Real world usage WILL change the spec. Be a part of it!
  93. Browser’s don’t know everything, we just pretend to Real world usage WILL change the spec. Be a part of it!
  94. Always try to push the experience one step further, and then another
  95. I even had to do a lot of extra work to get it at microsoft That is my acutal work email – LET ME HEAR FROM YOU! Change the world