Top Banner
SERVICE WORKERS OFFLINE WEB COM
145

Offline Web com Service Workers - Sérgio Lopes

Dec 02, 2014

Download

Technology

Caelum

Palestra de Novembro de 2014 do Sérgio Lopes da Caelum sobre a nova especificação dos Service Workers e como isso muda muita coisa na Web.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Offline Web com Service Workers - Sérgio Lopes

SERVICE WORKERSOFFLINE WEB COM

Page 2: Offline Web com Service Workers - Sérgio Lopes

@sergio_caelumsergiolopes.org

Page 3: Offline Web com Service Workers - Sérgio Lopes

WEB. OFFLINE?

Page 4: Offline Web com Service Workers - Sérgio Lopes

os primórdios do HTML5 offline

Application Cache API

Page 5: Offline Web com Service Workers - Sérgio Lopes

<html manifest="demo.appcache">

Minha página offline…

Page 6: Offline Web com Service Workers - Sérgio Lopes

CACHE MANIFEST

/index.html/imagens/logo.png/javascript/script.js/css/estilo.css

O manifesto…

Page 7: Offline Web com Service Workers - Sérgio Lopes

CACHE MANIFEST

/index.html/imagens/logo.png/javascript/script.js/css/estilo.css

O manifesto…

NETWORK:http://www.google-analytics.com/ga.js

Page 8: Offline Web com Service Workers - Sérgio Lopes

CACHE MANIFEST

/index.html/imagens/logo.png/javascript/script.js/css/estilo.css

O manifesto…

NETWORK:http://www.google-analytics.com/ga.js

FALLBACK:/img/avatares/ /img/avatar-generico.png

Page 9: Offline Web com Service Workers - Sérgio Lopes

Pronto! O maravilhoso AppCache entra em ação.

Page 10: Offline Web com Service Workers - Sérgio Lopes
Page 11: Offline Web com Service Workers - Sérgio Lopes

Tem que acertar o mime-type no servidor.

Page 12: Offline Web com Service Workers - Sérgio Lopes

Tem que acertar o mime-type no servidor.Não posso esquecer nenhuma URL.

Page 13: Offline Web com Service Workers - Sérgio Lopes

Tem que acertar o mime-type no servidor.Não posso esquecer nenhuma URL.Sempre cacheia a página.

Page 14: Offline Web com Service Workers - Sérgio Lopes

Tem que acertar o mime-type no servidor.Não posso esquecer nenhuma URL.Sempre cacheia a página.Nada pode dar erro 404 ou 500.

Page 15: Offline Web com Service Workers - Sérgio Lopes

Tem que acertar o mime-type no servidor.Não posso esquecer nenhuma URL.Sempre cacheia a página.Nada pode dar erro 404 ou 500.Cuidado pra não cachear o manifesto.

Page 16: Offline Web com Service Workers - Sérgio Lopes

Tem que acertar o mime-type no servidor.Não posso esquecer nenhuma URL.Sempre cacheia a página.Nada pode dar erro 404 ou 500.Cuidado pra não cachear o manifesto.Usuário não pode controlar nada.

Page 17: Offline Web com Service Workers - Sérgio Lopes

Tem que acertar o mime-type no servidor.Não posso esquecer nenhuma URL.Sempre cacheia a página.Nada pode dar erro 404 ou 500.Cuidado pra não cachear o manifesto.Usuário não pode controlar nada.Impossível escolher o que cachear.

Page 18: Offline Web com Service Workers - Sérgio Lopes

Tem que acertar o mime-type no servidor.Não posso esquecer nenhuma URL.Sempre cacheia a página.Nada pode dar erro 404 ou 500.Cuidado pra não cachear o manifesto.Usuário não pode controlar nada.Impossível escolher o que cachear.Potencial para detonar o 3G do usuário.

Page 19: Offline Web com Service Workers - Sérgio Lopes

Tem que acertar o mime-type no servidor.Não posso esquecer nenhuma URL.Sempre cacheia a página.Nada pode dar erro 404 ou 500.Cuidado pra não cachear o manifesto.Usuário não pode controlar nada.Impossível escolher o que cachear.Potencial para detonar o 3G do usuário.Remover o cache é um parto.

Page 20: Offline Web com Service Workers - Sérgio Lopes

Tem que acertar o mime-type no servidor.Não posso esquecer nenhuma URL.Sempre cacheia a página.Nada pode dar erro 404 ou 500.Cuidado pra não cachear o manifesto.Usuário não pode controlar nada.Impossível escolher o que cachear.Potencial para detonar o 3G do usuário.Remover o cache é um parto.Não posso impedir update automático.

Page 21: Offline Web com Service Workers - Sérgio Lopes

Tem que acertar o mime-type no servidor.Não posso esquecer nenhuma URL.Sempre cacheia a página.Nada pode dar erro 404 ou 500.Cuidado pra não cachear o manifesto.Usuário não pode controlar nada.Impossível escolher o que cachear.Potencial para detonar o 3G do usuário.Remover o cache é um parto.Não posso impedir update automático.Terrível pra desenvolver e debugar.

Page 22: Offline Web com Service Workers - Sérgio Lopes

Tem que acertar o mime-type no servidor.Não posso esquecer nenhuma URL.Sempre cacheia a página.Nada pode dar erro 404 ou 500.Cuidado pra não cachear o manifesto.Usuário não pode controlar nada.Impossível escolher o que cachear.Potencial para detonar o 3G do usuário.Remover o cache é um parto.Não posso impedir update automático.Terrível pra desenvolver e debugar. …

Page 23: Offline Web com Service Workers - Sérgio Lopes

Tem que acertar o mime-type no servidor. Não posso esquecer nenhuma URL. Sempre cacheia a página. Nada pode dar erro 404 ou 500. Cuidado pra não cachear o manifesto. Usuário não pode controlar nada. Impossível escolher o que cachear. Potencial para detonar o 3G do usuário. Remover o cache é um parto. Não posso impedir update automático. Terrível pra desenvolver e debugar. …

AppCache é

chato, limitado e

complicado.

Page 24: Offline Web com Service Workers - Sérgio Lopes

http://sergiolopes.org/palestra-appcache-html5-offline/

Page 25: Offline Web com Service Workers - Sérgio Lopes

Declarativo e Mágico.

Page 26: Offline Web com Service Workers - Sérgio Lopes

SERVICE WORKERS

Page 27: Offline Web com Service Workers - Sérgio Lopes

<!DOCTYPE html><html><head>

</head><body><h1>Página offline</h1>

</body></html>

Page 28: Offline Web com Service Workers - Sérgio Lopes

<!DOCTYPE html><html><head><script>navigator.serviceWorker.register('o-futuro.js');

</script></head><body><h1>Página offline</h1>

</body></html>

Page 29: Offline Web com Service Workers - Sérgio Lopes

this.onfetch = function(event) {

console.log(event.request.url);

};

Page 30: Offline Web com Service Workers - Sérgio Lopes

this.onfetch = function(event) {event.respondWith(

new Response("<h1>Página offline!</h1>") );};

Page 31: Offline Web com Service Workers - Sérgio Lopes

É um Worker orientado a eventos, que controla as páginas em background. Lá, tudo é assíncrono, e

ele pode interceptar chamadas de rede e usar um cache de recursos.

SERVICE WORKER

Page 32: Offline Web com Service Workers - Sérgio Lopes

<script src="script.js" async></script>

JAVASCRIPT COMUM

Page 33: Offline Web com Service Workers - Sérgio Lopes

<script src="script.js" async></script>

DOM

CSSOM

LAYOUT

EVENTOS

SCROLL

JAVASCRIPT COMUM

Page 34: Offline Web com Service Workers - Sérgio Lopes

<script src="script.js" async></script>

DOM

CSSOM

LAYOUT

EVENTOS

SCROLL

script

script

script

script

JAVASCRIPT COMUM

Page 35: Offline Web com Service Workers - Sérgio Lopes

<script> new Worker('worker.js'); </script>

WEB WORKERS

Page 36: Offline Web com Service Workers - Sérgio Lopes

<script> new Worker('worker.js'); </script>

DOM

CSSOM

LAYOUT

EVENTOS

SCROLL

WEB WORKERS

Page 37: Offline Web com Service Workers - Sérgio Lopes

script script script script

<script> new Worker('worker.js'); </script>

DOM

CSSOM

LAYOUT

EVENTOS

SCROLL

WEB WORKERS

Page 38: Offline Web com Service Workers - Sérgio Lopes

PÁGINA #1

WEB WORKERS

Page 39: Offline Web com Service Workers - Sérgio Lopes

PÁGINA #1

web worker A

WEB WORKERS

Page 40: Offline Web com Service Workers - Sérgio Lopes

PÁGINA #1

web worker A

WEB WORKERS

web worker B

Page 41: Offline Web com Service Workers - Sérgio Lopes

PÁGINA #1

web worker A

WEB WORKERS

web worker B

PÁGINA #2

web worker A

web worker B

Page 42: Offline Web com Service Workers - Sérgio Lopes

WEB WORKERS

PÁGINA #2

web worker A

web worker B

Page 43: Offline Web com Service Workers - Sérgio Lopes

WEB WORKERS

Page 44: Offline Web com Service Workers - Sérgio Lopes

<script>navigator.serviceWorker.register('sw.js');</script>

PÁGINA #1

Service Worker

PÁGINA #2

PÁGINA #3

SERVICE WORKER

Page 45: Offline Web com Service Workers - Sérgio Lopes

<script>navigator.serviceWorker.register('sw.js');</script>

PÁGINA #1

Service Worker

PÁGINA #2

SERVICE WORKER

Page 46: Offline Web com Service Workers - Sérgio Lopes

<script>navigator.serviceWorker.register('sw.js');</script>

PÁGINA #1

Service Worker

SERVICE WORKER

Page 47: Offline Web com Service Workers - Sérgio Lopes

<script>navigator.serviceWorker.register('sw.js');</script>

Service Worker

SERVICE WORKER

Page 48: Offline Web com Service Workers - Sérgio Lopes

É um Worker orientado a eventos, que controla as páginas em background. Lá, tudo é assíncrono, e

ele pode interceptar chamadas de rede e usar um cache de recursos.

SERVICE WORKER

Page 49: Offline Web com Service Workers - Sérgio Lopes

navigator.serviceWorker.register('sw.js').then(function(){console.log('Registrado!');

}, function(erro) {console.log('Problemas', erro);

});

PROMISES

Page 50: Offline Web com Service Workers - Sérgio Lopes

this.oninstall = function(event) {console.log('instalou');

};

this.onactivate = function(event) {console.log('ativou');

};

this.onfetch = function(event) {event.respondWith(

new Response("<h1>Página offline!</h1>”) );};

EVENTOS

Page 51: Offline Web com Service Workers - Sérgio Lopes

CACHE API

Page 52: Offline Web com Service Workers - Sérgio Lopes

caches.open('aplicacao');

Page 53: Offline Web com Service Workers - Sérgio Lopes

caches.open('aplicacao').then(function(cache) {

});

Page 54: Offline Web com Service Workers - Sérgio Lopes

caches.open('aplicacao').then(function(cache) { cache.add('pg.html');});

Page 55: Offline Web com Service Workers - Sérgio Lopes

caches.open('aplicacao').then(function(cache) { cache.put('pg.html', new Response("Página offline"));});

Page 56: Offline Web com Service Workers - Sérgio Lopes

caches.open('aplicacao').then(function(cache) { cache.add('pg.html'); cache.add('style.css');});

Page 57: Offline Web com Service Workers - Sérgio Lopes

caches.open('aplicacao').then(function(cache) { cache.addAll([ '/index.html', '/style.css', '/logo.png', '/contato.html', 'http://code.jquery.com/jquery-2.1.1.min.js' ]); })

Page 58: Offline Web com Service Workers - Sérgio Lopes

caches.open('aplicacao').then(function(cache) { return cache.addAll([ '/index.html', '/style.css', '/logo.png', '/contato.html', 'http://code.jquery.com/jquery-2.1.1.min.js' ]); })

Page 59: Offline Web com Service Workers - Sérgio Lopes

this.oninstall = function(event) {

caches.open('aplicacao').then(function(cache) { return cache.addAll([ '/index.html', '/style.css', '/logo.png', '/contato.html', 'http://code.jquery.com/jquery-2.1.1.min.js' ]); })

};

Page 60: Offline Web com Service Workers - Sérgio Lopes

this.oninstall = function(event) { event.waitUntil( caches.open('aplicacao').then(function(cache) { return cache.addAll([ '/index.html', '/style.css', '/logo.png', '/contato.html', 'http://code.jquery.com/jquery-2.1.1.min.js' ]); }) );};

Page 61: Offline Web com Service Workers - Sérgio Lopes

CACHE programático & controlável

Page 62: Offline Web com Service Workers - Sérgio Lopes

CACHE programático & controlável

Cacheio URLs como quero.

Page 63: Offline Web com Service Workers - Sérgio Lopes

CACHE programático & controlável

Cacheio URLs como quero.

Gero endereços num for com certa regra.

Page 64: Offline Web com Service Workers - Sérgio Lopes

CACHE programático & controlável

Cacheio URLs como quero.

Gero endereços num for com certa regra.

Recursos diferentes dependendo do browser.

Page 65: Offline Web com Service Workers - Sérgio Lopes

CACHE programático & controlável

Cacheio URLs como quero.

Gero endereços num for com certa regra.

Recursos diferentes dependendo do browser.

Levo em conta alguma preferência do usuário.

Page 66: Offline Web com Service Workers - Sérgio Lopes

CACHE programático & controlável

Cacheio URLs como quero.

Gero endereços num for com certa regra.

Recursos diferentes dependendo do browser.

Levo em conta alguma preferência do usuário.

Mudo de acordo com hardware e contexto.

Page 67: Offline Web com Service Workers - Sérgio Lopes

RESPOSTA OFFLINE

Page 68: Offline Web com Service Workers - Sérgio Lopes

this.onfetch = function(event) {

console.log(event.request.url);

};

Page 69: Offline Web com Service Workers - Sérgio Lopes

this.onfetch = function(event) { event.respondWith( new Response(‘conteúdo!') );};

Page 70: Offline Web com Service Workers - Sérgio Lopes

this.onfetch = function(event) { event.respondWith( caches.match(event.request) );};

Page 71: Offline Web com Service Workers - Sérgio Lopes
Page 72: Offline Web com Service Workers - Sérgio Lopes

RESPOSTA DO CACHE

Page 73: Offline Web com Service Workers - Sérgio Lopes

RESPOSTA DO CACHEE se não existir?

Page 74: Offline Web com Service Workers - Sérgio Lopes

this.onfetch = function(event) { event.respondWith( caches.match(event.request).then(function(response){

}) );};

Page 75: Offline Web com Service Workers - Sérgio Lopes

this.onfetch = function(event) { event.respondWith( caches.match(event.request).then(function(response){ return response || event.default(); })

);};

Page 76: Offline Web com Service Workers - Sérgio Lopes
Page 77: Offline Web com Service Workers - Sérgio Lopes

BAIXA NA REDE

Page 78: Offline Web com Service Workers - Sérgio Lopes

BAIXA NA REDEE se estiver offline?

Page 79: Offline Web com Service Workers - Sérgio Lopes

this.onfetch = function(event) { event.respondWith( caches.match(event.request).then(function(response){ return response || event.default(); }).catch(function() { return caches.match('/contato.html'); }) );};

Page 80: Offline Web com Service Workers - Sérgio Lopes

FALLBACK DE URLs

Page 81: Offline Web com Service Workers - Sérgio Lopes

RESPOSTA programática & controlável

Page 82: Offline Web com Service Workers - Sérgio Lopes

RESPOSTA programática & controlável

Busco no cache.

Page 83: Offline Web com Service Workers - Sérgio Lopes

RESPOSTA programática & controlável

Busco no cache.

Busco na rede.

Page 84: Offline Web com Service Workers - Sérgio Lopes

RESPOSTA programática & controlável

Busco no cache.

Busco na rede.

Devolvo fallback.

Page 85: Offline Web com Service Workers - Sérgio Lopes

RESPOSTA programática & controlável

Busco no cache.

Busco na rede.

Devolvo fallback.

Construo resposta na mão.

Page 86: Offline Web com Service Workers - Sérgio Lopes

RESPOSTA programática & controlável

Busco no cache.

Busco na rede.

Devolvo fallback.

Construo resposta na mão.

Tudo com a lógica e a sequência que eu quiser.

Page 87: Offline Web com Service Workers - Sérgio Lopes

ATUALIZAÇÕES

Page 88: Offline Web com Service Workers - Sérgio Lopes
Page 89: Offline Web com Service Workers - Sérgio Lopes

Mudo o worker.js

Page 90: Offline Web com Service Workers - Sérgio Lopes

Mudo o worker.jsDetecta na próxima navegação.

Page 91: Offline Web com Service Workers - Sérgio Lopes

Mudo o worker.jsDetecta na próxima navegação.

Dispara instalação (oninstall) em background.

Page 92: Offline Web com Service Workers - Sérgio Lopes

Mudo o worker.jsDetecta na próxima navegação.

Dispara instalação (oninstall) em background.

(worker original ainda comanda a página)

Page 93: Offline Web com Service Workers - Sérgio Lopes

Mudo o worker.jsDetecta na próxima navegação.

Dispara instalação (oninstall) em background.

(worker original ainda comanda a página)

Fecho a página.

Page 94: Offline Web com Service Workers - Sérgio Lopes

Mudo o worker.jsDetecta na próxima navegação.

Dispara instalação (oninstall) em background.

(worker original ainda comanda a página)

Fecho a página.

Worker velho é desativado.

Page 95: Offline Web com Service Workers - Sérgio Lopes

Mudo o worker.jsDetecta na próxima navegação.

Dispara instalação (oninstall) em background.

(worker original ainda comanda a página)

Fecho a página.

Worker velho é desativado.

Novo worker é ativado (onactivate).

Page 96: Offline Web com Service Workers - Sérgio Lopes

Mudo o worker.jsDetecta na próxima navegação.

Dispara instalação (oninstall) em background.

(worker original ainda comanda a página)

Fecho a página.

Worker velho é desativado.

Novo worker é ativado (onactivate).

(novo worker em ação)

Page 97: Offline Web com Service Workers - Sérgio Lopes

Mudo o worker.jsDetecta na próxima navegação.

Dispara instalação (oninstall) em background.

(worker original ainda comanda a página)

Fecho a página.

Worker velho é desativado.

Novo worker é ativado (onactivate).

(novo worker em ação)

Abro a página de novo.

Page 98: Offline Web com Service Workers - Sérgio Lopes

this.oninstall = function(event) { event.waitUntil( caches.open('aplicacao-v2').then(function(cache) { return cache.addAll([ '/index.html', '/style.css', '/logo.png', '/contato.html', 'http://code.jquery.com/jquery-2.1.1.min.js' ]); }) );};

Page 99: Offline Web com Service Workers - Sérgio Lopes

this.onactivate = function(event) { event.waitUntil( caches.delete('aplicacao-v1') );};

Page 100: Offline Web com Service Workers - Sérgio Lopes

ATUALIZAÇÃO

Page 101: Offline Web com Service Workers - Sérgio Lopes

ATUALIZAÇÃO

Totalmente em background.

Page 102: Offline Web com Service Workers - Sérgio Lopes

ATUALIZAÇÃO

Totalmente em background.

Não incomoda o usuário.

Page 103: Offline Web com Service Workers - Sérgio Lopes

ATUALIZAÇÃO

Totalmente em background.

Não incomoda o usuário.

Só troca no próximo acesso.

Page 104: Offline Web com Service Workers - Sérgio Lopes

ATUALIZAÇÃO

Totalmente em background.

Não incomoda o usuário.

Só troca no próximo acesso.

Chrome-like.

Page 105: Offline Web com Service Workers - Sérgio Lopes

detalhes dos

SERVICE WORKERS

Page 106: Offline Web com Service Workers - Sérgio Lopes

controle de escopo

Page 107: Offline Web com Service Workers - Sérgio Lopes

navigator.serviceWorker.register('worker.js');

Page 108: Offline Web com Service Workers - Sérgio Lopes

navigator.serviceWorker.register('worker.js', {scope: '/blog/'

});

Page 109: Offline Web com Service Workers - Sérgio Lopes

HTTPS only

Page 110: Offline Web com Service Workers - Sérgio Lopes

tudo assíncrono

Page 111: Offline Web com Service Workers - Sérgio Lopes

pode ser morto a qualquer momento

Page 112: Offline Web com Service Workers - Sérgio Lopes

muito mais poderoso muito mais complicado

Page 113: Offline Web com Service Workers - Sérgio Lopes

ainda não existe em nenhum browser

Page 114: Offline Web com Service Workers - Sérgio Lopes

FUTURO FANTÁSTICO

Page 115: Offline Web com Service Workers - Sérgio Lopes

BACKGROUND SYNC

Page 116: Offline Web com Service Workers - Sérgio Lopes

postaTweet(texto);

Page 117: Offline Web com Service Workers - Sérgio Lopes

try {postaTweet(texto);

} catch (err) {

}

Page 118: Offline Web com Service Workers - Sérgio Lopes

try {postaTweet(texto);

} catch (err) {salvaTweet(texto);registration.sync.register('envia-tweet');

}

Page 119: Offline Web com Service Workers - Sérgio Lopes

postaTweet(texto).catch(function(){

});

Page 120: Offline Web com Service Workers - Sérgio Lopes

postaTweet(texto).catch(function(){ salvaTweet(texto).then(function(){

}).then(function(){

});});

Page 121: Offline Web com Service Workers - Sérgio Lopes

postaTweet(texto).catch(function(){return salvaTweet(texto).then(function(){return navigator.serviceWorker.ready;

}).then(function(registration){return registration.sync.register('envia-tweet');

});});

Page 122: Offline Web com Service Workers - Sérgio Lopes

this.onsync = function (event) {if (event.id === 'envia-tweet') {

}};

Page 123: Offline Web com Service Workers - Sérgio Lopes

this.onsync = function (event) {if (event.id === 'envia-tweet') {event.waitUntil(carregaTweet().then(function(texto){postaTweet(texto);

}));

}};

Page 124: Offline Web com Service Workers - Sérgio Lopes

registration.sync.register('atualiza-inbox', {minInterval: 60 * 60 * 1000

});

Page 125: Offline Web com Service Workers - Sérgio Lopes

PUSH NOTIFICATION

Page 126: Offline Web com Service Workers - Sérgio Lopes

registration.pushRegistrationManager.register()

Page 127: Offline Web com Service Workers - Sérgio Lopes

registration.pushRegistrationManager.register() .then(function(detalhes) {

});

Page 128: Offline Web com Service Workers - Sérgio Lopes

registration.pushRegistrationManager.register() .then(function(detalhes) { return avisaServidor(detalhes);

});

Page 129: Offline Web com Service Workers - Sérgio Lopes

this.onpush = function(event) {if (event.message.data == 'nova-mensagem') {

}};

Page 130: Offline Web com Service Workers - Sérgio Lopes

this.onpush = function(event) {if (event.message.data == 'nova-mensagem') {event.waitUntil(atualizaMensagens().then(function(){

}));

}};

Page 131: Offline Web com Service Workers - Sérgio Lopes

this.onpush = function(event) {if (event.message.data == 'nova-mensagem') {event.waitUntil(atualizaMensagens().then(function(){new Notification("Chegou mensagem!");

}));

}};

Page 132: Offline Web com Service Workers - Sérgio Lopes

this.onnotificationclick = function(event) {

};

Page 133: Offline Web com Service Workers - Sérgio Lopes

this.onnotificationclick = function(event) {new ServiceWorkerClient('/mensagens.html');

};

Page 134: Offline Web com Service Workers - Sérgio Lopes

GEOFENCING

Page 135: Offline Web com Service Workers - Sérgio Lopes

ALARMES TEMPORAIS

Page 136: Offline Web com Service Workers - Sérgio Lopes

hoje, depois do evento

SERVICE WORKERS

Page 137: Offline Web com Service Workers - Sérgio Lopes

estude Service Workers hoje. esse é o futuro.

Page 138: Offline Web com Service Workers - Sérgio Lopes

brinque no ChromeChrome Canary - chrome://flags

#enable-experimental-web-platform-features

Page 139: Offline Web com Service Workers - Sérgio Lopes
Page 140: Offline Web com Service Workers - Sérgio Lopes

vote no status.modern.ie

Page 141: Offline Web com Service Workers - Sérgio Lopes

use AppCache como fallback

Page 142: Offline Web com Service Workers - Sérgio Lopes

offline como progressive enhancement

if ('serviceWorker' in navigator) {

}

Page 143: Offline Web com Service Workers - Sérgio Lopes

pense offline first

Page 144: Offline Web com Service Workers - Sérgio Lopes

SERVICE WORKERSOFFLINE WEB COM

Page 145: Offline Web com Service Workers - Sérgio Lopes

OBRIGADO!

sergiolopes.org @sergio_caelum