Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Pennapps hackathon - Workshop: Progressive Web Apps, the future of web development - University of Pennsylvania

Pennapps hackathon - Workshop: Progressive Web Apps, the future of web development - University of Pennsylvania

📹 Video: https://www.youtube.com/watch?v=de1xiqz-BTE
🔗 Twitter: https://twitter.com/JGFerreiro
🔗 Linkedin: https://www.linkedin.com/in/jgferreiro/

Progressive Web Apps is a term that Google created in 2015. Representing the next revolution in web development, PWAs enable more reliable, faster and engaging user experiences while also incorporating mobile app functionalities into websites. These and other features lead many engineers to believe that PWA’s are the future of web development.

I run this workshop at the University of Pennsylvania for Pennapps. We created a progressive web app with the following functionalities:

- Offline mode
- Caching requests: images, CSS, index.html.
- Local Notifications
- Payments API
- How to set up your app manifest
- Add to the home screen

- - -

Subscribe: https://jorgeferreiro.com/newsletter

on https://www.twitter.com/jgferreiro
on https://www.linkedin.com/in/jgferreiro/
on https://www.instagram.com/jgferreiro/

Jorge Ferreiro

October 08, 2019
Tweet

More Decks by Jorge Ferreiro

Other Decks in Programming

Transcript

  1. @JGFERREIRO @JGFERREIRO #PENNPWA Agenda 1. What, why and the industry

    2. Metadata + manifest 3. Service workers 4. Cache API 5. Web Payments 6. Local Notifications 7. Action items Important quote
  2. @JGFERREIRO @JGFERREIRO #PENNPWA Our first Progressive Web App! ✅ Offline

    mode ✅ Local Notifications ✅ Cache requests ✅ Payments API ❌ Background Sync ❌ IndexedDB Emotion CSS-in-JS
  3. @JGFERREIRO @JGFERREIRO #PENNPWA Responsive ( Works offline ⚙ App-like- interactions

    Fresh Safe Discoverable Re-engageable PWA features (Alex Russell Jake Archibald) Durable Linkable Alex Russel “Progressive Web Apps: Escaping Tabs Without Losing Our Soul”
  4. @JGFERREIRO @JGFERREIRO #PENNPWA Using latest browser features when they are

    available, and adapt the user experience Progressive enhancement:
  5. @JGFERREIRO @JGFERREIRO #PENNPWA ๏ Simplified web version ๏ Data save

    mode ๏ Limit access to advanced features Progressive enhancement: Example ๏ High quality media ๏ Advanced Features: Push, background sync, etc. United States Bad 2G connection | Cheap phone 5G connection | High quality phones 2 Africa
  6. @JGFERREIRO @JGFERREIRO #PENNPWA Progressive enhancement: Simplification if ('feature' in browser)

    { !// Feature is available!!! !// Do something cool with it! } else { !// Party pooper !// Browser does not support this feature !// Change your browser!!... }
  7. @JGFERREIRO @JGFERREIRO #PENNPWA Distribution Freedom No need apple store or

    play store 5 Key Benefits of Progressive Web Apps Push notifications Parity feature with Native. Re-engaging users No install required A matter of seconds to have them installed Smaller Native apps tend to occupy more space. Offline! Improves user retention and converstions. Why?
  8. @JGFERREIRO @JGFERREIRO #PENNPWA Twitter -70% data consumption +65% increase in

    pages per session +75% increase in Tweets sent How we built Twitter Lite
  9. @JGFERREIRO @JGFERREIRO #PENNPWA Alibaba +76% conversions 4X higher interaction rate

    from Add to Homescreen https://developers.google.com/web/showcase/2016/alibaba
  10. @JGFERREIRO @JGFERREIRO #PENNPWA Starbucks +12% growth on orders w/w (May

    2018) Nearly doubled daily & monthly active users Google I/O 18’
  11. @JGFERREIRO @JGFERREIRO #PENNPWA Pinterest A one year PWA retrospective +401%

    number of pins +103% active users y/y on mobile web +843% new signups y/y
  12. @JGFERREIRO @JGFERREIRO #PENNPWA Pinterest A one year PWA retrospective +401%

    number of pins +103% active users y/y on mobile web +843% new signups y/y
  13. @JGFERREIRO @JGFERREIRO #PENNPWA Our first Progressive Web App! Emotion CSS-in-JS

    ✅ Offline mode ✅ Local Notifications ✅ Cache requests ✅ Payments API ❌ Background Sync ❌ IndexedDB
  14. @JGFERREIRO @JGFERREIRO #PENNPWA Apple metatags Apple: Configuring web applications <meta

    name="apple-mobile-web-app-title" content="Pennapps"> <meta name="apple-mobile-web-app-status-bar-style" content="white"> <meta name="apple-mobile-web-app-capable" content="yes">
  15. @JGFERREIRO @JGFERREIRO #PENNPWA More Apple metatags… icons favicon-generator.org <link rel="apple-touch-icon"

    sizes="57x57" href=“image_57_57.png"> <link rel="apple-touch-icon" sizes="60x60" href="image_60_60.png"> <link rel="apple-touch-icon" sizes="72x72" href="image_72_72.png"> <link rel="apple-touch-icon" sizes="76x76" href="image_76_76.png"> <link rel="apple-touch-icon" sizes="114x114" href="image_114_114.png"> <link rel="apple-touch-icon" sizes="120x120" href="image_120_120.png"> <link rel="apple-touch-icon" sizes="144x144" href="image_144_144.png"> <link rel="apple-touch-icon" sizes="152x152" href="image_152_152.png"> <link rel="apple-touch-icon" sizes="180x180" href="image_180_180.png">
  16. @JGFERREIRO @JGFERREIRO #PENNPWA manifest.json is a configuration file to tell

    the browser how your should behave once installed
  17. @JGFERREIRO @JGFERREIRO #PENNPWA Create manifest.json "short_name": "Pennapps", "name": "Pennapps agenda",

    "start_url": "/?utm_source=pwa", "display": "standalone", "theme_color": "#ffffff", "background_color": "#ffffff", "scope": "/", "icons": [] { } <link href="/static/manifest.json" rel="manifest">
  18. @JGFERREIRO @JGFERREIRO #PENNPWA “short_name": "Pennapps", "name": "Pennapps agenda", "start_url": "/?utm_source=pwa",

    "display": "standalone", "theme_color": "#ffffff", "background_color": "#ffffff", "scope": "/", "icons": [] { } { !// 192 for the “home screen icon” "src": "/static/images/pennapps_logo_pwa_192_192.png", "sizes": "192x192", "type": "image/png" }, { !// 512 for splash screen (on Android) "src": "/static/images/pennapps_logo_pwa_512_512.png", "sizes": "512x512", "type": "image/png" } ]
  19. @JGFERREIRO @JGFERREIRO #PENNPWA Manifest.json - display fullscreen No browser UI

    ✅ Videogames standalone Hides standard browser UI elements ✅ Standalone native app minimal-ui Fullscreen display. Minimal UI elements browser Standard browser experience Google: Web App Manifest
  20. @JGFERREIRO @JGFERREIRO #PENNPWA A service worker is a JavaScript file

    that runs separately from the main browser thread
  21. SERVICE WORKER :: REGistering new SW if ('serviceWorker' in navigator)

    { console.log('⭐ Start to register a service worker') navigator.serviceWorker.register('/sw.js') .then((registration) !=> { console.log('SW!::Registration', registration) }) .catch((error) !=> { console.log('SW!::Error registering', error) }); }
  22. SERVICE WORKER :: FETCH CALLBACK self.addEventListener('fetch', (event) !=> { console.log('I

    am intercepting network requests!') const url = event.request.url console.log('Requested resource url: ', url) })
  23. CACHE API :: HELLO WORLD const cacheNameVersion = 'resources-v1' caches.open(cacheNameVersion)

    .then((cache) !=> { !// Do something cool with the cache }) .catch((error) !=> { !// Error opening the cache :/ })
  24. CACHE API :: HELLO WORLD const cacheNameVersion = 'resources-v1' self.addEventListener('install',

    () !=> { caches.open(cacheNameVersion) .then((cache) !=> { !// Do something cool with the cache }) .catch((error) !=> { !// Error opening the cache :/ }) })
  25. CACHE API :: REQUIRING CRITICAL ASSETs const cacheVersion = 'version-1'

    const criticalAssets = ['/index.html', '/client.bundle.js'] self.addEventListener('install', (event) !=> { event.waitUntil(cacheAssets()) }) function cacheAssets() { return caches.open(cacheVersion) .then((cache) !=> { cacheNoCriticalAssets(cache) return cacheCriticalAssets(cache) }) } function cacheCriticalAssets (cache) { return cache.addAll(criticalAssets) } function cacheNoCriticalAssets(cache) { cache.add('./foo.css') }
  26. @JGFERREIRO @JGFERREIRO #PENNPWA event.waitUntil Service worker will stay in “install”

    mode, until waitUntil is resolved
 If the resolved promise fails, it will not install anything…
  27. CACHE API :: REMOVING CACHED ASSETS self.addEventListener('install', (event) !=> {

    !// Add assets to the service worker cache }) self.addEventListener('activated', (event) !=> { !// Remove cached assets from previous version }) Make sure to remove cached ASSETS!
  28. CACHE API :: Fetch image or placeholder self.addEventListener('fetch', (event) !=>

    { const acceptHeader = event.request.headers.get('accept') if (acceptHeader.includes('image')) { return event.respondWith( fetchImageOrPlaceholder(event) ) } })
  29. CACHE API :: Fetch image or placeholder function fetchImageOrPlaceholder(fetchEvent) {

    return fetch(fetchEvent.request, { mode: 'no-cors' }) .then((response) !=> { if (!response.ok) { throw Error(‘Can not download from server…’) } return response }) .catch(() !=> { !// NB: Return placeholder. return caches.match(PLADEHOLDER_IMAGE, { cacheName: cacheVersion }) }) }
  30. CACHE API :: Fetch image or placeholder function fetchImageOrPlaceholder(fetchEvent) {

    return fetch(fetchEvent.request, { mode: 'no-cors' }) .then((response) !=> { if (!response.ok) { throw Error(‘Can not download from server…’) } return response }) .catch(() !=> { !// NB: Return placeholder. return caches.match(PLADEHOLDER_IMAGE, { cacheName: cacheVersion }) }) }
  31. CACHE API :: Fetch image or placeholder self.addEventListener('fetch', (event) !=>

    { const acceptHeader = event.request.headers.get('accept') if (acceptHeader.includes('image')) { return event.respondWith( fetchImageOrPlaceholder(event) ) } })
  32. CACHE API :: Fetch image or placeholder function fetchImageOrFallback(fetchEvent) {

    return fetch(fetchEvent.request, {mode: ‘no-cors’}) READ CacheStorage .then((response) !=> { if (!response.ok) { throw Error('Can not download image from server') } caches.open(cacheVersion).then(function(cache) { !// Cache in background cache.put(fetchEvent.request, response) }) return response.clone() !// NB: We can't reuse responses twice }) .catch(() !=> { return caches.match(fetchEvent.request).catch(function() { !// try to get cached return caches.match(PLADEHOLDER_IMAGE, { !// Return placeholder cacheName: cacheVersion }) }) }) }
  33. Web payments api :: REQUEST OBJECT const request = new

    PaymentRequest(methods, details, options) PAYMENT REQUEST CONSTRUCTOR const methods = [{ supportedMethods: 'basic-card', data: { supportedNetworks: [ 'visa', 'mastercard' ] } }] const details = { displayItems: [{ label: 'Computer to mine bitcoin', amount: { currency: 'USD', value: 1000 } }], total: { label: 'Total due', amount: { currency: tickets.currency, value : 1000 } } } const options = { !// requestPayerPhone, requestShipping, shippingType requestPayerEmail: true, requestPayerName: true, }
  34. Web payments api const request = new PaymentRequest(methods, details, options)

    PAYMENT REQUEST DEMO !// Add event listeners on user actions. Eg: shippingaddresschange paymentRequest.addEventListener( 'paymentmethodchange', handlePaymentChange, false ) paymentRequest.addEventListener( ‘shippingaddresschange', handleShippingAddressChange, false ) request.show().then(response !=> { !// [process payment] !// Send to a Payment service provider (PWA), metrics, etc response.complete('success') }).catch((error) !=> {!/* Notify user on the error !*/})
  35. CACHE API :: HELLO WORLD export const launchNotification = ({artistId,

    isEnabled}) !=> { if ('Notification' in window) { Notification.requestPermission().then((permission) !=> { const artist = artists[artistId] const title = isEnabled ? `✅ Notifications for ${artist.name} are activated!` : `❌ Deactivate ${artist.name} notifications!` const options = { body: 'You will be notified for this event', icon: '/images/pennapps_logo_pwa_192_192.png', } }) } } new Notification(title, options)
  36. @JGFERREIRO #PENNPWA The app "shell" is the minimal HTML, CSS

    and JavaScript required to power the user interface
  37. @JGFERREIRO @JGFERREIRO #PENNPWA Who to follow? Jake Archibald Google @jaffathecake

    Alex Russell Chrome Team @slightlylate Sarah Clark Google @a_bowl_of_stars Pete LePage Google @petele Dominick Ng Chrome PWA @dominickng Scott Domes Indeed @scottdomes Kenneth C. Intel @kennethrohde Henrik Joreteg Consultant @HenrikJoreteg Charlie Croom Twitter @CharlieCroom Monica Dinculescu Polymer @notwaldorf
  38. @JGFERREIRO @JGFERREIRO #PENNPWA Action items 1. Fork “pwa 101” repo

    and start it locally 2. Re-read this presentation, and open some of the links in the resources 3. Execute each of the steps to add progressive enhancement to your app
  39. @JGFERREIRO @JGFERREIRO #PENNPWA Research on advanced topics: 1. Background sync

    2. IndexedDB 3. Push notifications with Web Push 4. HTTP2 Action items (II)
  40. @JGFERREIRO @JGFERREIRO #PENNPWA Resources 1. Google I/O 2014 - Bridging

    the gap between the web and apps 2. How we built Twitter Lite 3. Twitter Lite and High Performance React Progressive Web Apps at Scale 4. Google workbox 5. Payment request 6. Frontend masters: Progressive web apps 7. Background sync 8. Google: Progressive web apps YouTube traiing
  41. @JGFERREIRO @JGFERREIRO #PENNPWA ✅ T-shirt Eventbrite ✅ T-shirt "DevelopersInDepth" (DID)

    ✅ 1h pair programming session / coaching session with me ✅ Eventbrite stickers + DID stickers ✅ Badge "Best PWA in Pennapps" Pennapps PWA Contest bit.ly/pwa-contest