Slide 1

Slide 1 text

SEGREDOS NÃO DITOS DE PWA M U I TO A L É M D O W E B A P P M A N I F E S T

Slide 2

Slide 2 text

OI, EU SOU O E D U @eduardojmatos

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

D E V N A E S T R A DA . C O M . B R

Slide 5

Slide 5 text

H T T P : / / D I V E R S I DA D E . T E C H

Slide 6

Slide 6 text

H T T P S : / / G I T H U B . C O M / F R O N T E N D B R

Slide 7

Slide 7 text

OK, PWA O QUÊ?

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

Public Work Administrations era uma agência do governo dos EUA pra cuidar de grandes construções públicas na década de 30/40. Só de curiosidade mesmo.

Slide 10

Slide 10 text

Progressive Web Apps é um 
 conjunto de conceitos:
 Rapidez, Integridade, Confiabilidade e Engajamento.

Slide 11

Slide 11 text

Como uma “agência”, PWA contém algumas “auditorias” pra certificar que estamos seguindo esses conceitos.

Slide 12

Slide 12 text

PWA É SÓ FRONT-END?

Slide 13

Slide 13 text

NÃO

Slide 14

Slide 14 text

BACK-END E DEVOPS TAMBÉM ESTÃO NO JOGO MUITAS COISAS ANTES DO FRONT-END PRECISAM DE CUIDADO

Slide 15

Slide 15 text

SERVER SIDE PWA ❤ BACK-END

Slide 16

Slide 16 text

GZIP SE VOCÊ AINDA NÃO ESTÁ USANDO, BEM… Nginx, Node, Apache, IIS.
 Todos têm possibilidade de enviar conteúdo 
 comprimido com GZIP

Slide 17

Slide 17 text

GZIP NGINX # Enable gzip compression.
 gzip on; # Compression level (1-9) # 5 is a perfect compromise between size and CPU usage
 gzip_comp_level 5; # Don't compress anything that's already small and unlikely to shrink much
 gzip_min_length 256;

Slide 18

Slide 18 text

npm install compression --save const compression = require('compression'); const express = require('express'); const app = express(); app.use(compression()); GZIP NODE

Slide 19

Slide 19 text

IMAGE COMPRESSION IMAGENS NA WEB NÃO PRECISAM TER 100% DE QUALIDADE

Slide 20

Slide 20 text

34KB 11KB

Slide 21

Slide 21 text

IMAGE COMPRESSION FERRAMENTAS PARA OTIMIZAÇÃO jpegoptim SVGO pngquant 2 Gifsicle

Slide 22

Slide 22 text

AUTOMATIZE imagemin-webpack-plugin gulp-imagemin middleman-imageoptim imagemin USE FERRAMENTAS NO BUILD DO PROJETO PRA COMPRESSÃO TODAS USAM QUASE AS MESMAS LIBS DE OTIMIZAÇÃO

Slide 23

Slide 23 text

TIME TO FIRST BYTE O TEMPO PRA QUE O PRIMEIRO BYTE CHEGUE NO CLIENT

Slide 24

Slide 24 text

TIME TO FIRST BYTE • Tempo pra envio da requisição HTTP; • Tempo para o servidor processar a requisição; • Tempo para o servidor responder o primeiro byte;

Slide 25

Slide 25 text

TIME TO FIRST BYTE http://bytecheck.com/

Slide 26

Slide 26 text

TIME TO FIRST BYTE TEMPO DE SERVIDOR, REQUEST TIME… • Aqui não tem jeito: precisa melhorar o tempo de resposta do servidor; • Dá pra usar cache na frente pra amenizar (Varnish, ou outra tecnologia); • Ou uma CDN (veremos logo mais).

Slide 27

Slide 27 text

TIME TO FIRST BYTE É IMPORTANTE PARA A PRIMEIRA EXPERIÊNCIA DO PWA. SENSAÇÃO DE VELOCIDADE É UM DOS ASPECTOS MAIS IMPORTANTES NUM WEB APP.

Slide 28

Slide 28 text

SINCRONIA DE DADOS SUPORTE OFFLINE NO BROWSER, E SINCRONIA COM BACK-END

Slide 29

Slide 29 text

SINCRONIA DE DADOS POUCHDB É UMA IMPLEMENTAÇÃO COM JAVASCRIPT DO COUCHDB. O OBJETIVO É EMULAR O COUCHDB RODANDO NO BROWSER OU ATÉ MESMO NO NODEJS

Slide 30

Slide 30 text

const PouchDB = require('pouchdb'); // sample === database name const db = new PouchDB('http://localhost:5984/sample'); const myUser = { _id: 'Edu-v1', name: 'Eduardo Matos', email: '[email protected]', company_name: 'GetNinjas', };

Slide 31

Slide 31 text

db.find({ selector: { _id: myUser._id } }) .then((result) => { db.put(myUser) .then(doc => console.log('created:', doc)) .catch((err) => { const updatedUser = Object.assign({ _rev: result.docs[0]._rev }, myUser); if (err.name === 'conflict') { db.put(updatedUser).then((user) => { console.log('putted =>', user); }); } }); });

Slide 32

Slide 32 text

SINCRONIA DE DADOS const PouchDB = require('pouchdb'); // sample === database name const db = new PouchDB('sample'); db.sync('http://localhost:5984/sample', { live: true, retry: true }); VERSÃO “NO-BRAINER”

Slide 33

Slide 33 text

SINCRONIA DE DADOS POUCHDB É BUILT-IN EM DIVERSOS ENVIRONMENTS

Slide 34

Slide 34 text

DEVOPS PWA ❤ DEVOPS

Slide 35

Slide 35 text

PAGESPEED MÓDULO DE OTIMIZAÇÃO PARA NGINX E APACHE

Slide 36

Slide 36 text

PAGESPEED MAIS DE 40 FILTROS DE OTIMIZAÇÃO Combine CSS Combine JS Filters and Options for Optimizing Images Prioritize Critical CSS Lazily Load Images Remove Quotes Move CSS to Head Inline Preview Images Inline Google Fonts API CSS Hint Resource Preloading

Slide 37

Slide 37 text

PAGESPEED MAIS DE 40 FILTROS DE OTIMIZAÇÃO pagespeed on; pagespeed FileCachePath /var/ngx_pagespeed_cache; pagespeed LogDir /var/log/pagespeed; # config pagespeed LowercaseHtmlNames on; pagespeed EnableFilters remove_comments; pagespeed EnableFilters collapse_whitespace; pagespeed EnableFilters remove_quotes; pagespeed EnableFilters elide_attributes;

Slide 38

Slide 38 text

SEUS AMIGUINHOS DA PERFORMANCE DNS-PREFETCH, PRECONNECT, E PRELOAD

Slide 39

Slide 39 text

DNS-PREFETCH OLHA SÓ, VAI VIR ALGO DESSE DOMÍNIO DNS-Prefetch Notifica o cliente que há assets que vão ser baixados dentro de um domínio, assim que o browser resolver o DNS do mesmo.

Slide 40

Slide 40 text

DNS-PREFETCH OLHA SÓ, VAI VIR ALGO DESSE DOMÍNIO

Slide 41

Slide 41 text

DNS-PREFETCH OLHA SÓ, VAI VIR ALGO DESSE DOMÍNIO dns lookup | connect | ssl

Slide 42

Slide 42 text

DNS-PREFETCH OLHA SÓ, VAI VIR ALGO DESSE DOMÍNIO connect | ssl

Slide 43

Slide 43 text

PRECONNECT EI! JÁ CONECTA AÍ! Preconnect Parecido com o dns-prefetch, o preconnect faz o hand-shake e negociação de TLS de forma opcional.

Slide 44

Slide 44 text

PRECONNECT EI! JÁ CONECTA AÍ! sem dns lookup, connect e ssl!

Slide 45

Slide 45 text

PRECONNECT BÔNUS! PRA FAZER O PRECONNECT COM A API DO GOOGLE FONTS E EVITAR O HAND-SHAKE ;)

Slide 46

Slide 46 text

Preload Faz o download de um asset, independente do browser achar que precisa ou não. PRELOAD JÁ BAIXA AÍ, POR FAVOR

Slide 47

Slide 47 text

PRELOAD JÁ BAIXA AÍ, POR FAVOR O “as” suporta:
 audio, document, embed, fetch, font, image, object, script, style, track, worker, video

Slide 48

Slide 48 text

PRELOAD JÁ BAIXA AÍ, POR FAVOR em 0.6 segundos, já iniciou o download, e em 149ms respondeu

Slide 49

Slide 49 text

CDN DISTRIBUINDO SEUS ASSETS RAPIDAMENTE, COM CACHE E POR REGIÕES

Slide 50

Slide 50 text

CDN DISTRIBUINDO SEUS ASSETS RAPIDAMENTE, COM CACHE E POR REGIÕES

Slide 51

Slide 51 text

HTTP/2 A CAMADA DE TRANSPORTE MODERNA E ÁGIL

Slide 52

Slide 52 text

HTTP/2 REQUESTS PARALELOS E NÃO BLOCANTES

Slide 53

Slide 53 text

HTTP/2 HEADER COMPRESSION

Slide 54

Slide 54 text

HTTP/2 HPACK Quase 88% de redução no tamanho do request

Slide 55

Slide 55 text

FRONT-END FRONT PIRA NO PWA

Slide 56

Slide 56 text

IMAGENS NO TAMANHO CERTO 40X40? NÃO USE UMA DE 50X50

Slide 57

Slide 57 text

resolução tamanho natural display size (CSS px) Pixels desnecessários bytes 
 desnecessários 1x 110 x 110 100 x 100 110 x 110 - 100 x 100 = 2100 2100 x 4 / 1024 = 
 8 KB 1x 410 x 410 400 x 400 410 x 410 - 400 x 400 = 8100 8100 x 4 / 1024 = 
 31.6 KB 1x 810 x 810 800 x 800 810 x 810 - 800 x 800 = 16100 16100 x 4 / 1024 =
 62.9 KB 2x 220 x 220 100 x 100 210 x 210 - (2 x 100) x (2 x 100) = 8400 8400 x 4 / 1024 =
 32.8 KB 2x 820 x 820 400 x 400 820 x 820 - (2 x 400) x (2 x 400) = 32400 32400 x 4 / 1024 =
 126.5 KB 2x 1620 x 1620 800 x 800 1620 x 1620 - (2 x 800) x (2 x 800) = 64400 64400 x 4 / 1024 =
 251.6 KB

Slide 58

Slide 58 text

SOBRE FONTES… 
 USE MENOS! • MAIS QUE 2 FAMÍLIAS DE FONTES NUM WEB APP… PARECE ESTRANHO! • FONTES SÃO BLOCANTES; • CAUSAM FOIT (FLASH OF INVISIBLE TEXT);

Slide 59

Slide 59 text

PRA EVITAR FOIT FONT FACE OBSERVER

Slide 60

Slide 60 text

.default-font { font-family: Arial, sans-serif; }

Slide 61

Slide 61 text

var fonts = [ { name: 'Lato', weight: 400 }, { name: 'Lato', weight: 700 }, { name: 'Lato', weight: 900 } ]; fonts.forEach(function(font, index) { fonts[index].observer = new FontFaceObserver(font.name, { 
 weight: font.weight 
 }); }); Promise .all(fonts.map(function(font) { return font.observer.load(); })) .then(() => document.body.classList.remove("default-font") );

Slide 62

Slide 62 text

No content

Slide 63

Slide 63 text

No content

Slide 64

Slide 64 text

No content

Slide 65

Slide 65 text

INPUT LATENCY SENSAÇÃO DE VELOCIDADE NO INPUT DO USUÁRIO • O ideal é a interação de input ser menor que 100ms. • Digitar, Clicar, Mover sobre hover, etc. Mais que 100ms, repense muito!

Slide 66

Slide 66 text

UM SIMPLES EFEITO DE HOVER COM 2S…

Slide 67

Slide 67 text

GPU mouseover com transition e animation Paint, Recalculate Style

Slide 68

Slide 68 text

document.addEventListener( 'touchstart', onTouchStartHandler, { passive: true }); TOUCH MOVE, START, ETC., SEM O DOUBLE CHECK DE “TOUCH OR SCROLL" TOUCH PASSIVE

Slide 69

Slide 69 text

https://www.youtube.com/watch?v=65VMej8n23A TOUCH PASSIVE

Slide 70

Slide 70 text

PRIORIZANDO O ESSENCIAL PRO USUÁRIO CRITICAL PATH above the fold

Slide 71

Slide 71 text

CSS INLINE CRITICAL PATH

Slide 72

Slide 72 text

CRITICAL PATH ATENÇÃO! MUITO INLINE PREJUDICA O TTFB!

Slide 73

Slide 73 text

QUANDO O USUÁRIO VAI COMEÇAR A VER SUA PÁGINA DE VERDADE FIRST MEANINGFUL PAINT

Slide 74

Slide 74 text

LEMBRA DO PREFETCH E PRELOAD? POIS É! FIRST MEANINGFUL PAINT

Slide 75

Slide 75 text

NÃO É ESSENCIAL DE INÍCIO? CARREGA DEPOIS! JAVASCRIPT NÃO BLOCANTE Testing

Slide 76

Slide 76 text

NÃO É ESSENCIAL DE INÍCIO? CARREGA DEPOIS! JAVASCRIPT NÃO BLOCANTE Com async, o JavaScript é carregado enquanto o DOM é construído. Assim que carregado ele já é executado.

Slide 77

Slide 77 text

NÃO É ESSENCIAL DE INÍCIO? CARREGA DEPOIS! JAVASCRIPT NÃO BLOCANTE Com defer, o JavaScript é carregado enquanto o DOM é construído também, mas só é carregado quando o DOM está 100% pronto.

Slide 78

Slide 78 text

NÃO É ESSENCIAL DE INÍCIO? CARREGA DEPOIS! JAVASCRIPT NÃO BLOCANTE

Slide 79

Slide 79 text

USE ESTRATÉGIAS DE CACHE COM SERVICE WORKERS Como o Service Workers funciona

Slide 80

Slide 80 text

O QUE É SERVICE WORKERS? // index.html if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/js/sw.js') .then(reg => { if(reg.active) { console.log('Service worker active'); } }).catch(error => { console.error('Registration failed with', error); }); };

Slide 81

Slide 81 text

O QUE É SERVICE WORKERS? // 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' ]); }) ); });

Slide 82

Slide 82 text

O QUE É SERVICE WORKERS? // js/sw.js
 self.addEventListener('fetch', (event) => { event.respondWith( caches.open('v1').then((cache) => { return cache.match(event.request).then((response) => { if (response) { return response.clone(); } throw Error('Response cached missing'); }).catch((error) => { return fetch(event.request.url); //fallback para online }); }) ); });

Slide 83

Slide 83 text

No content

Slide 84

Slide 84 text

NETWORK FIRST? CACHE FIRST? SW-PRECACHE PRA CRIAR O ARQUIVO DO SW USE ESTRATÉGIAS DE CACHE COM SERVICE WORKERS

Slide 85

Slide 85 text

NETWORK FIRST? CACHE FIRST? SW-PRECACHE PRA CRIAR O ARQUIVO DO SW USE ESTRATÉGIAS DE CACHE COM SERVICE WORKERS npm i sw-precache -g sw-precache —config=precache-config.js --verbose module.exports = { staticFileGlobs: [ 'app/css/**.css', 'app/**.html', 'app/images/**.*', 'app/js/**.js' ], stripPrefix: 'app/', runtimeCaching: [{ handler: 'cacheFirst' }] };

Slide 86

Slide 86 text

PASSE UMA “AUDITORIA” NO SEU WEB APP https://github.com/GoogleChrome/lighthouse/

Slide 87

Slide 87 text

TAVA BOM, NÃO TAVA MUITO BOM, TAVA MEIO RUIM TAMBÉM, AGORA PARECE QUE PIOROU

Slide 88

Slide 88 text

WEB APPS CONTINUAM SENDO COMPLEXAS…

Slide 89

Slide 89 text

PWA SÓ ADICIONOU “AUDITORIAS” PRA AVALIAR SEU WEB APP CTZ QUE VÃO ME XINGAR

Slide 90

Slide 90 text

A MAIORIA DOS PADRÕES DO PWA JÁ EXISTIAM

Slide 91

Slide 91 text

RESUMINDO…

Slide 92

Slide 92 text

HÁ MUITO POR TRÁS DE APENAS UM WEB APP MANIFESTO COM ÍCONE DE APP E INSTALAÇÃO NO DEVICE

Slide 93

Slide 93 text

BACK-END DEVOPS FRONT-END PWA NÃO É SÓ A RESPONSA DE UMA ÁREA EM TECNOLOGIA

Slide 94

Slide 94 text

DÁ PRA USAR ESSAS DICAS MESMO NÃO CONSTRUINDO UM PWA

Slide 95

Slide 95 text

E NÃO, OS APPS NATIVOS NÃO VÃO MORRER TÃO CEDO ;) CTZ QUE VÃO ME XINGAR [2]

Slide 96

Slide 96 text

@eduardojmatos http://eduardomatos.me [email protected] OBRIGADO ;)