As maravilhas do
Service worker
Transformando um site em uma
aplicação offline
LEONN
LEITE
PHPDF
PHPESTE
MAJOR
EM PHP
MINOR
EM JS
SEXY
SEM SER
VULGAR
@LEONN
LEITE
IRMÃO
DO
LENON
PARA
DIFEREN
CIAR
ELE É
MAIS
GORDO
FAMILIA
AMAZO-
NENSE
+LEONN
LEITE
/LEONN
LEITE
MAS
SOU
BRASILI-
ENSE
Imagine a wifi
em um apartamento
Na cama do casal
a internet funciona
assim:
PELO MENOS DÁ PRA
JOGAR
¯_(ツ)_/¯
MOSTRAR OFFLINE É
MELHOR QUE NÃO DAR
RESPOSTA
QUANDO NÃO SE ESTÁ
OFFLINE, MAS NÃO
TEM RESPOSTA …
É CONHECIDO POR:
EU CHAMO DE:
EU CHAMO DE:
TELA BRANCA
SOLUÇÕES?!
Criar um app na app store ou google play
VENCEMOS!
UMA OUTRA SOLUÇÃO
leonnleite.com/phpeste
leonnleite.com/phpeste
leonnleite.com/phpeste
leonnleite.com/phpeste
PODE MELHORAR
ISSO NÃO PARECE UM
APP
VAMOS ADICIONAR
ALGUMAS COISAS
VAMOS SUBSTITUIR TUDO ISSO
manifest.json
VAMOS VER QUEM É
MELHOR
Vamos testar, sem conexão?
UAI, MAS NÃO IA FUNCIONAR OFFLINE?
CALMA, EU POSSO EXPLICAR
CADE O SERVICE WORKER?!
navigator.serviceWorker.register('sw.js');
if (navigator.serviceWorker) {
navigator.serviceWorker.register('sw.js');
}
ISSO PORQUE TEM UM BROWSER
QUE AINDA NÃO DÁ SUPORTE
ADIVINHA QUAL
PENSOU QUE
ERA O IE, NÉ?
PENSOU QUE
ERA O IE, NÉ?
VOLTANDO AO ASSUNTO SW
if (navigator.serviceWorker) {
navigator.serviceWorker.register('sw.js');
}
VOCÊ PODE VER QUE ESTÁ FUNCIONANDO,
NO DEVELOPER TOOLS
AGORA TEMOS UM SERVICE WORKER
sw.js
self.addEventListener('fetch', event => {
debugger;
});
sw.js
self.addEventListener('fetch', event => {
debugger;
});
HABILITA O DEBBUGER NO EVENTO FETCH
OU SEJA, QUANDO BUSCAR CADA REQUISIÇÃO
TEMOS VÁRIOS OUTROS EVENTOS:
• FETCH
• INSTALL
• PUSH
• ACTIVATE
• …
MOSTRA O REQUEST COMPLETO
sw.js
self.addEventListener('fetch', event => {
event.respondWith(
new Response('Hello PHPeste')
);
});
sw.js
self.addEventListener('fetch', event => {
event.respondWith(
new Response('Hello PHPeste')
);
});
EM QUALQUER REQUISIÇÃO, VAI MOSTRAR A MENSAGEM
HELLO PHPESTE
POSSO ALTERAR SÓ
PARTE DO CONTEÚDO
VAMOS ALTERAR
SÓ AS IMAGENS
sw.js
self.addEventListener('fetch', event => {
var url = new URL(event.request.url);
if (url.pathname.endsWith('.jpg')) {
event.respondWith(
fetch('/toy-story.gif')
)
}
});
sw.js
self.addEventListener('fetch', event => {
var url = new URL(event.request.url);
if (url.pathname.endsWith('.jpg')) {
event.respondWith(
fetch('/toy-story.gif')
)
}
});
PODEMOS MODIFICAR TELAS
DE ERROR
404
POR EXEMPLO
sw.js
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request).then(response => {
if (response.status === 404) {
return fetch ('404.png');
}
)
}
});
sw.js
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request).then(response => {
if (response.status === 404) {
return fetch ('404.png');
}
)
}
});
UAU, MAS SE ESTIVER
OFFLINE?
sw.js
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request).catch(error => {
return new Response('Ixi, deu ruim... ' +
'Você está offline e eu' +
' não posso fazer nada');
)
}
});
sw.js
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request).catch(error => {
return new Response('Ixi, deu ruim... ' +
'Você está offline e eu' +
' não posso fazer nada');
)
}
});
PARTICULARMENTE, ACHO MELHOR
DEIXAR O DINOSAURO
Desculpe o transtorno, preciso falar do Cache 
Duvivier, Gregorio
sw.js
        caches.open('phpeste-v1') // return promise
sw.js
        caches.open('phpeste-v1') // return promise
ABRE A COLEÇÃO DO CACHE. SE NÃO EXISTIR, CRIA.
sw.js
        caches.open('phpeste-v1').then(function(cache) { 
            return cache.addAll([ ... ]);
        }
sw.js
        caches.open('phpeste-v1').then(function(cache) { 
            return cache.addAll([ ... ]);
        }
NO ADDALL ADICIONA ELEMENTOS AO CACHE
GERALMENTE POPULAMOS SÓ NO INSTALL
sw.js
self.addEventListener('install', event => {
event.waitUntil(
caches.open('phpeste-v1').then(function(response) {
return cache.addAll([ ... ]);
})
);
});
NO EVENT INSTALL DO SERVICE WORKER
sw.js
self.addEventListener('install', event => {
event.waitUntil(
caches.open('phpeste-v1').then(function(response) {
return cache.addAll([ ... ]);
})
);
});
sw.js
caches.delete('phpeste-v1');
sw.js
caches.delete('phpeste-v1');
DELETA UMA COLEÇÃO DO CACHE
sw.js
caches.keys(); // return promise
sw.js
caches.keys(); // return promise
RETORNA TODOS OS CACHENAME
caches.keys().then(function(cacheNames)
{ cacheNames.filter(function(cacheName) {
return cacheName.startsWith('phpeste-')
&& cacheName != 'phpeste-v1';
}).map(function(cacheName) {
return caches.delete(cacheName);
});
})
REMOVE TODOS OS CACHES, QUE COMEÇAM COM PHPESTE-
E QUE NÃO SEJA O PHPESTE-V1
caches.keys().then(function(cacheNames)
{ cacheNames.filter(function(cacheName) {
return cacheName.startsWith('phpeste-')
&& cacheName != 'phpeste-v1';
}).map(function(cacheName) {
return caches.delete(cacheName);
});
})
ENTÃO, PODEREMOS PEDIR PARA O CACHE RESPONDER
NÃO PRECISA MAIS IR PARA INTERNET
O QUE ANTES ERA ASSIM
AGORA PODE SER ASSIM
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
O SERVICE WORKER
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
VAI ESCUTAR UM EVENTO
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
DE BUSCA DE CADA REQUEST
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
E VAI RESPONDER COM
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
O CACHE
MAS PARA RESPONDER COM CACHE
ELE PRECISA SER ADICIONADO
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('phpeste-v1').then(function(cache) {
return cache.addAll([
'./',
'https://fonts.googleapis.com/css?family=Ro...',
'vendor/bootstrap/bootstrap.min.css’...,
'/phpeste/manifest.json' ...,
'vendor/angular/angular.min.js' ...,
'assets/img/b_1024.jpg ', 'img/b_2048.jpg ',
'api/sessions',
'api/speakers',
'api/schedule',
]);
})
);
});
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('phpeste-v1').then(function(cache) {
return cache.addAll([
'./',
'https://fonts.googleapis.com/css?family=Ro...',
'vendor/bootstrap/bootstrap.min.css’...,
'/phpeste/manifest.json' ...,
'vendor/angular/angular.min.js' ...,
'assets/img/b_1024.jpg ', 'img/b_2048.jpg ',
'api/sessions',
'api/speakers',
'api/schedule',
]);
})
);
});
QUANDO INSTALAR
O SERVICE WORKER
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('phpeste-v1').then(function(cache) {
return cache.addAll([
'./',
'https://fonts.googleapis.com/css?family=Ro...',
'vendor/bootstrap/bootstrap.min.css’...,
'/phpeste/manifest.json' ...,
'vendor/angular/angular.min.js' ...,
'assets/img/b_1024.jpg ', 'img/b_2048.jpg ',
'api/sessions',
'api/speakers',
'api/schedule',
]);
})
);
});
ADICIONO OS ARQUIVOS ESTATICOS
NO CACHE
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('phpeste-v1').then(function(cache) {
return cache.addAll([
'./',
'https://fonts.googleapis.com/css?family=Ro...',
'vendor/bootstrap/bootstrap.min.css’...,
'/phpeste/manifest.json' ...,
'vendor/angular/angular.min.js' ...,
'assets/img/b_1024.jpg ', 'img/b_2048.jpg ',
'api/sessions',
'api/speakers',
'api/schedule',
]);
})
);
});
ISSO NÃO DEVERIA ESTAR AQUI,
MAS É SÓ COMO EXEMPLO
OFFLINE
As maravilhas do service worker
As maravilhas do service worker

As maravilhas do service worker