Armazenamento Offline: APIs para Progressive Web Apps

Armazenamento Offline: APIs para Progressive Web Apps

Algumas APIs de JavaScript que você já pode usar para que seu PWA funcione offline

Bfcf5c88d40733a45ce754e6ce225a8b?s=128

Eduardo Matos

June 23, 2017
Tweet

Transcript

  1. ARMAZENAMENTO OFFLINE APIS PARA PROGRESSIVE WEB APPS

  2. @eduardojmatos eduardomatos.me OI, EU SOU O EDU

  3. a maior plataforma de contratação de serviços do Brasil

  4. None
  5. VAMOS FALAR SOBRE INTERNET?

  6. www.teleco.com.br/3G_cobertura.asp

  7. http://www.teleco.com.br/4G_cobertura.asp

  8. NETFLIX ISP SPEED INDEX

  9. 53% dos consumidores perdem a paciência e desistem de acessar

    o site após apenas três segundos. A expectativa do consumidor (afirmação feita por 79% dos entrevistados) é de encontrar as informações que deseja instantaneamente. http://exame.abril.com.br/marketing/quer-posicionar-bem-a-marca-entao-de-um-jeito-no-seu-site-movel/
  10. Mais da metade deles (56%) preferem comprar em sites móveis

    ou apps que permitem salvar preferências— entre consumidores entre 18 e 34 anos, esse número sobe para 64%. http://exame.abril.com.br/marketing/quer-posicionar-bem-a-marca-entao-de-um-jeito-no-seu-site-movel/
  11. 68% consideram 6 segundos um tempo de carregamento aceitável, mas

    que até 3 segundos era o “ponto ideal”. https://www.tecmundo.com.br/apps/81635-paciencia-brasileiro-apps-lentos-dura-somente-3-segundos.htm
  12. 3 segundos era o “ponto ideal”

  13. None
  14. COMO ISSO DEVERIA IMPACTAR NOSSO DESENVOLVIMENTO?

  15. PWA progressive web apps

  16. Progressive Web Apps é a experiência do usuário ao alcance

    da web sendo Confiável, Rápida e Engajante.
  17. TÁ, E COMO FAZ?

  18. CONFIÁVEL • Carrega quase que instantaneamente; • Independe das condições

    de conexão com a internet; • Honestidade com relação à conectividade.
  19. APPLICATION CACHE CACHE DE ARQUIVOS NO BROWSER

  20. <html manifest="manifest.appcache"> CACHE MANIFEST # version 1 CACHE: http://jsexperience2017.imasters.com.br/images/logo.jpg http://jsexperience2017.imasters.com.br/palestrantes/01.jpg

    http://jsexperience2017.imasters.com.br/palestrantes/02.jpg NETWORK: https://facebook.com/sdk.js FALLBACK: index.html offline.html
  21. SERVICE WORKERS e

  22. if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/js/sw.js') .then(reg => { if(reg.installing)

    { console.log('Service worker installing'); } else if(reg.waiting) { console.log('Service worker installed'); } else if(reg.active) { console.log('Service worker active'); } }).catch(error => { console.error('Registration failed with', error); }); };
  23. navigator.serviceWorker.register('/js/sw.js') .then(reg => { reg.addEventListener('updatefound', () => { const newServiceWorker

    = reg.installing; newServiceWorker.addEventListener('statechange', () => { if (newServiceWorker.state == 'activated') { console.info('SW is active!'); } }) }); }) .catch(error => error)
  24. None
  25. CACHE API CACHE PROGRAMÁTICO DE ARQUIVOS NO BROWSER

  26. // /js/sw.js self.addEventListener('install', event => { event.waitUntil( caches.open('v1').then(cache => {

    return cache.addAll([ '/index.html', '/js/app.js', '/css/styles.css', '/images/avatar/profile/01.jpg' ]); }) ); }); VERSIONAMENTO DE CACHE
  27. None
  28. ANTES DE SERVICE WORKERS DEPOIS DE SERVICE WORKERS

  29. INTERCEPTAÇÃO DE REQUEST QUALQUER REQUEST PASSA PELO EVENTO DE FETCH

  30. self.addEventListener('fetch', event => { event.respondWith(caches.open('v1').then(cache => { return cache.match(event.request) .then(cached

    => { if (cached) return cached; throw new Error('No cache founded'); }) .catch(error => { return fetch(event.request) .then(response => { cache.put(event.request, response.clone()); return response; }).catch(error => caches.match('offline.html')); }) }) ); });
  31. None
  32. None
  33. RÁPIDA • JavaScript performático; • Interações fluídas e com sensação

    de velocidade; • Cache First.
  34. document.write( '<script src="https://js.com/script.js"></script>' ); JS PERFORMÁTICO https://developers.google.com/web/updates/2016/08/removing-document-write NOT • 38%

    de redução em conexão 2G; • 21% de redução até o first paint;
  35. DOMAttrModified DOMAttributeNameChanged DOMCharacterDataModified DOMElementNameChanged DOMNodeInserted DOMNodeInsertedIntoDocument DOMNodeRemoved DOMNodeRemovedFromDocument DOMSubtreeModified JS

    PERFORMÁTICO https://developers.google.com/web/tools/lighthouse/audits/mutation-events NOT • Performance baixa! • Deprecated events!
  36. document.addEventListener('DOMContentLoaded', (event) => { navigator.geolocation.getCurrentPosition(success, error); Notification.requestPermission((result) => { resolve(result);

    }); }); EVITE JS PERFORMÁTICO https://developers.google.com/web/fundamentals/engage-and-retain/push-notifications/display-a-notification • Apenas use esses recursos quando o usuário precisar; • Exiba notificações somente quando necessário;
  37. document.addEventListener( 'touchstart', onTouchStart, { passive: true }); INTERAÇÕES FLUÍDAS https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection

  38. INTERAÇÕES FLUÍDAS https://www.youtube.com/watch?v=65VMej8n23A

  39. CACHE FIRST self.addEventListener('fetch', event => { event.respondWith(caches.open('v1').then(cache => { return

    cache.match(event.request) .then(cached => { if (cached) return cached; //…
  40. CACHE FIRST npm i sw-precache -g sw-precache —config=precache-config.js --verbose USE

    SW-PRECACHE module.exports = { staticFileGlobs: [ 'app/css/**.css', 'app/**.html', 'app/images/**.*', 'app/js/**.js' ], stripPrefix: 'app/', runtimeCaching: [{ handler: 'cacheFirst' }] };
  41. ENGAJANTE • Web App Manifest; • Push Notifications;

  42. WEB APP MANIFEST <link rel="manifest" href="/manifest.json">

  43. { "name": "Offline App Presentation", "short_name": "OfflineAPp", "start_url": ".", "display":

    "standalone", "background_color": "#fff", "description": "Testing our Offline App Presentation", "icons": [{ "src": “images/touch/icon-168.png", "sizes": "168x168", "type": "image/png" }], "related_applications": [{ "platform": "web" }, { "platform": "play", "url": "https://play.google.com/store/apps/details?id=offapp" }] }
  44. None
  45. None
  46. window.addEventListener('beforeinstallprompt', function(e) { e.userChoice.then(function(choiceResult) { console.log(choiceResult.outcome); if(choiceResult.outcome == 'dismissed') {

    console.log('Sad, but user cancelled home screen install'); } else { console.log('Yes! User added to home screen'); } }); });
  47. WEB APP MANIFEST • Ter um web app manifest com:

    • short_name (usado na home screen); • name (usado no banner de instalação); • um ícone png de 144x144; • “start_url” que o app é carregado. • Ter um service worker registrado em seu site; • Servido com HTTPS (pra usar Service Worker isso já é um requisito); • Foi visitado pelo menos duas vezes, em pelo menos 5 minutos entre as visitas CRITÉRIOS PRA EXIBIÇÃO DO BANNER DE INSTALAÇÃO DO WEB APP
  48. NOTIFICAÇÕES

  49. function askPermission() { return new Promise((resolve, reject) => { const

    permissionResult = Notification.requestPermission((result) => { resolve(result); }); if (permissionResult) { permissionResult.then(resolve, reject); } }) .then((permissionResult) => { if (permissionResult !== 'granted') { throw new Error('Fail on granted permission.'); } }); }
  50. function subscribeUserToPush() { return getSWRegistration() .then((registration) => { const subscribeOptions

    = { userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array( 'BEl62iUYgUivxIkv69yViEuiBIa-Ib9- SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U' ) }; return registration.pushManager.subscribe(subscribeOptions); }) .then((pushSubscription) => { console.log('Received: ', JSON.stringify(pushSubscription)); return pushSubscription; }); }
  51. self.addEventListener('push', function(event) { const promiseChain = self.registration.showNotification( 'Hello, World.', {

    body: 'notification test!', icon: '/images/icon-512x512.png', image: '/images/body-notification.jpg', vibrate: [ 500, 110, 500, 110, 450, 110, 200, 110, 170, 40, 450, 110, 200, 110, 170, 40, 500 ], sound: 'starWarsPing.mp3' } ); event.waitUntil(promiseChain); });
  52. NOTIFICAÇÕES https://tests.peter.sh/notification-generator https://web-push-book.gauntface.com/demos/notification-examples/

  53. TESTE A NOTA DO SEU PWA

  54. npm install -g lighthouse lighthouse https://www.google.com TESTE A NOTA DO

    SEU PWA
  55. RESUMINDO…

  56. JAVASCRIPT ❤ PWA

  57. PWA É PROGRESSIVO USE E ABUSE PENSANDO QUE FOI FEITO

    PRA WEB TESTE SE AS API’S ESTÃO DISPONÍVEIS NO BROWSER
  58. JABÁ http://bit.ly/design-patterns-2

  59. JABÁ 2 http://bit.ly/pwa-js-2

  60. @eduardojmatos http://eduardomatos.me eduardoj.matos@gmail.com OBRIGADO ;)