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

Scalable PWA

Kazunari Hara
February 01, 2020

Scalable PWA

Scalable PWA 〜こえのブログ最新事例〜

PWA Night CONFERENCE 2020
https://conf2020.pwanight.jp/

Kazunari Hara

February 01, 2020
Tweet

More Decks by Kazunari Hara

Other Decks in Technology

Transcript

  1. Feb. 1 2020, PWA Night CONFERENCE 2020
    Kazunari Hara, CyberAgent
    Scalable
    〜こえのブログ最新事例〜

    View full-size slide

  2. is
    a web app
    focusing on UX

    View full-size slide

  3. voice.ameba.jp voice.ameba.jp voice.ameba.jp
    AD
    Loading too slow Unexpected layout shift Desktop view on mobile

    View full-size slide

  4. meow にゃーん (やーん)

    View full-size slide

  5. ● Reliable - Load instantly even when offline
    ● Fast - Respond quickly and no junk scrolling
    ● Engaging - Feel like a natural app on the device
    https://developers.google.com/web/progressive-web-apps

    View full-size slide

  6. ● Reliable - Load instantly even when offline
    ● Fast - Respond quickly and no junk scrolling
    ● Engaging - Feel like a natural app on the device
    ● Scalable - Being improved consistently

    View full-size slide

  7. こえのブログ
    Posting a blog entry just by
    speaking
    ● Audio recording
    ● Speech-to-Text
    ● Audio player
    ● Installable

    View full-size slide

  8. ● Posting blog with audio
    and text
    ● The editor is a PWA

    View full-size slide

  9. Device
    Microphone
    with
    MediaDevices.getUserMedia()
    https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
    navigator.mediaDevices.getUserMedia({
    audio:
    autoGainControl: false, channelCount: 1,
    echoCancellation: true, noiseSuppression: true,
    })
    .then(stream => // use stream);

    View full-size slide

  10. Getting Audio
    from Mic
    and save/post it later
    const mediaRecorder = new MediaRecorder(stream, options);
    mediaRecorder.addEventListener('stop', () => {
    const audioBlob = new Blob(recordedChunks);
    const audioUrl = URL.createObjectURL(audioBlob);
    downloadLink.href = audioUrl;
    downloadLink.download = 'audio.wav';
    });
    mediaRecorder.start();

    View full-size slide

  11. Transcoding
    with WASM
    reduces audio sizes
    https://github.com/Kagami/vmsg
    ● In Web Worker
    ● Execute periodically
    ● WAV to MP3
    -90%
    Audio sizes

    View full-size slide

  12. Speech-to-Text
    on Cloud
    converts audio to text by applying powerful neural
    network models
    const speech = require('@google-cloud/speech');
    const client = new speech.SpeechClient();
    const recognize = () => {
    const request = {
    audio: { uri: 'gs://...' },
    config: { languageCode: 'ja-JP', enableWordTimeOffsets: true },
    };
    return client.recognize(request);
    };

    View full-size slide

  13. Saving Draft
    to IndexedDB and restore it

    View full-size slide

  14. Playing Audio
    with the user’s permission
    ● Asking permission to play audio after
    prompt on the first encounter
    ● If the user says “OK”, start playing audio
    and save the status to the browser
    storage
    ● If the user says “NO”, always ask before
    playing audio

    View full-size slide

  15. Add to
    Home Screen
    as an application on OSes
    Criteria:
    ● https
    ● Service Worker with fetch
    ● Web App Manifest etc...

    View full-size slide

  16. Full experiences:
    Works on
    Limited experiences:

    View full-size slide

  17. Challenges for
    Scalable PWA

    View full-size slide

  18. Single Origin
    with HTTPS
    helps overcome many
    challenges in PWAs
    ● Service worker scopes
    ● New feature permissions
    ● Controllable caches
    ● Reading cookies
    https://web.dev/multi-origin-pwas/
    https://voices.ameba.jp/*/
    {api, assets, images, src}
    voice.ameba.jp

    View full-size slide

  19. App Strategy
    at Ameba
    こえのブログ shipped as a PWA:
    ● To create experimental fetures
    ● To provide app to major OSes
    ● Not to increase native app sizes
    ● PWA already works on many
    browsers

    View full-size slide

  20. Including Polyfill
    to provide modern functionality on older browsers
    Some polyfill options:
    Bundle JS files with polyfills like core-js
    Using polyfill services like polyfill.io
    Differential script loading
    is also recommended


    ECMAScript 2016+ compatibility
    table is almost all green, but
    we need to load polyfill for now
    https://kangax.github.io/compat-t
    able/

    View full-size slide

  21. Perf is Critical
    for user experience in PWA
    ● High priority for better UX
    ● Users prefer fast apps
    ● Better for business metrics
    voice.ameba.jp
    -44%
    Client Rendering Time
    +57%
    Page Views
    https://developers.cyberagent.co.jp/blog/archives/636/

    View full-size slide

  22. https://twitter.com/addyosmani/status/1194710153414594561
    Speed Badges on Chrome (planning)

    View full-size slide

  23. Consistently
    Fast
    even during traffic spikes
    (13x traffic spikes occurred)
    Caches ensure site stability:
    ● Server-side caches
    ● Client-side caches

    View full-size slide

  24. CDN
    for server-side stability
    ● Long TTL (1 day by default)
    ● Event-driven cache purging
    ● Serving stale content
    98%
    Cache Hit Ratio
    99%
    Cache Coverage

    View full-size slide

  25. Service Worker
    for client-side caching
    ● Pre-caching app assets
    ○ updated precisely with server
    file update
    ● Runtime assets caches (except partial
    audios)
    ● HTTP caches if the browser does
    not support SW
    98%
    Cache Cavarage

    View full-size slide

  26. Cache Overview
    to improve site speed and consistency
    Origin Server / DB
    CDN
    Browser
    Purge on data update
    98%
    Cache Cavarage
    98%
    Cache Hit
    Fetch on file change
    High cache hit/coverage
    reduces unnecessary network
    requests

    View full-size slide

  27. https://speakerdeck.com/herablog/using-cdn-to-improve-web-performance

    View full-size slide

  28. Perf Budget
    helps ensure good user
    experience and business
    metrics
    The team need to maintain
    ● Perf budget
    ● Performance monitoring
    ● Improve decision making in
    development flow

    View full-size slide

  29. Lab data vs Field data
    Assessing app performance using both types of data
    Lab
    Controlled/Consistent Real-world/Wild
    Field
    Lighthouse
    DevTools
    SpeedCurve
    Chrome User Experience Report
    Firebase Performance Monitoring
    SpeedCurve

    View full-size slide

  30. Setting
    Perf Budget
    1. Measuring the app in lab
    2. Comparing metrics to competitors
    with 20% rule
    3. Setting perf budgets
    4. Monitoring budgets on a daily or a
    deployment basis
    5. Updating budgets (e.g. adding Field metrics)

    View full-size slide

  31. Perf Budget Now
    Setting aggressive budgets to find out regressions early
    FCP on Fast 3G <= 1.5s
    TTI on Fast 3G <= 3s
    Entrypoint HTML <= 14KB
    App shell JS <= 120KB
    Chunk JS <= 20KB

    View full-size slide

  32. Monitoring Perf Budget
    Daily basis:
    SpeedCurve, Lighthouse CI... (Lab)
    Firebase Perf, CrUX… (Field)
    Deployment basis:
    SpeedCurve (Lab)
    Before deployment:
    Bundle size on CI

    View full-size slide

  33. Perf Budget
    in development flow
    Some steps before consuming
    perf budget:
    ● Reducing size if possible
    ● Finding reason for size
    increases
    ● Issuing it to refactor later
    Exceeded?
    Ship it!
    Can reduce size?
    Reduce size
    Issue reason
    Consume budget
    Refactor
    Ship it!
    No
    Yes
    No
    Yes

    View full-size slide

  34. Apps need to be cleaned
    everyday like cats

    View full-size slide

  35. Continuous
    Deployment
    for site realiability
    ● Deployment is fast, easy, safe,
    and frequent
    ● Rollbacks are also easy
    ● Master branch is deployed
    automatically (on a daily basis,
    planning)
    >= 1,000
    Releases in 10 Month
    Push
    CLI
    Purge

    View full-size slide

  36. Tech Stack
    better performance, higher security,
    cheaper, easier scaling, and better DX
    Similar approach to JAMStack:
    ● Entire Project on a CDN
    ● Everything Lives in Git
    ● Modern Build Tools
    ● Automated Builds
    ● Atomic Deploys
    ● Instant Cache Invalidation
    Cloud
    Functions
    Cloud
    Storage
    Cloud
    Functions
    Web App Assets
    Audios
    API
    POST/DELETE
    API
    GET
    93%
    Endpoints Cacheable
    https://jamstack.org/

    View full-size slide

  37. Writing Tests
    ensures continuous deployment
    and app quality
    ● Logic unit testing
    ● Visual regression testing (pages)
    Tests working in progress:
    ● Logic unit testing on brosers
    ● Server-side testing
    https://qiita.com/junkisai/items/016c567a9fbade08d65b

    View full-size slide

  38. Traffic reffarals
    to increase visitors
    Social media
    Native Apps Search engines
    Open PWA from native apps
    Primary pages are on
    ameblo.jp not voice.ameba.jp

    View full-size slide

  39. Differential Rendering
    for social media crowlers and browsers inc Googlebot
    Server-side meta rendering
    ${pageTitle}



    src="src/components/voice-app.js"
    crossorigin>
    Client-side app rendering

    View full-size slide

  40. Image CDN
    creates eyecatch images
    displayed in social media
    ● Inserting landmark
    ● Cropping, resizing
    ● Converting appropriate
    format
    /image.jpg?
    crop=1200:630&width=1200&overlay=share

    View full-size slide

  41. Accessibility
    improves user experience
    ● Color contrast
    ● Machine readability
    ● Keyboard usability
    ● User preferences etc...
    voice.ameba.jp
    Only a subset of
    accessibility issues can be
    automatically detected

    View full-size slide

  42. Accessibility Tools
    checks additional accessibility issues
    Checking screen reader
    using VoiceOver
    Inspecting Accessibility
    Tree using DevTools
    Collaboration between
    designers and developers
    using VisBug

    View full-size slide

  43. Keyboard Usability
    screen reader usability
    as well
    Ensuring current position:
    ● Displaying outlines
    ● Controlling focuses

    View full-size slide

  44. Reduce
    Motions
    stops animations if the user
    prefers-reduced-motion
    @media (prefers-reduced-motion: reduce) {
    .item-placeholder {
    animation: none;
    }
    }

    View full-size slide

  45. Dark Mode
    respects prefers-color-scheme
    Applied with CSS custom
    properties
    @media (prefers-color-scheme: dark) {
    :root {
    --app-background-color: black;
    --app-text-color: white;
    }
    }
    Planning

    View full-size slide

  46. Accessibility
    Guidelines
    explains how can we improve
    user experience
    ● Based on WCAG 2.1
    ● Web Bundle is available
    https://openameba.github.io/a11y-guidelines/
    openameba.github.io
    https://github.com/openameba/a11y-guidelines/releases

    View full-size slide

  47. Progressive
    Enhancement
    to provide first-class
    experiences to the user
    Not only for visual designs:
    ● Feature detections
    ● Polyfill or other solutions
    voice.ameba.jp
    voice.ameba.jp

    View full-size slide

  48. Permissions API
    Not available:
    Always asking the permission
    Available:
    Checking the permission
    before recording
    const checkMicPermission = async () => {
    const permissionStatus =
    await navigator.permissions.query({
    name: 'microphone',
    });
    if (permissionStatus.state === 'denied') {
    // Display dialog...
    } else {
    // Start recording...
    }
    // You can also use addEventListener
    //
    permissionStatus.addEventListener('change');
    };

    View full-size slide

  49. Native
    Lazy-loading
    defers the loading of off-screen
    elements




    if ('loading' in HTMLImageElement.prototype) {
    // copy value from data-src to src
    } else {} // fallback with Intersection Observer
    https://twitter.com/herablog/status/1164475719100952576

    View full-size slide

  50. Is Native Lazy-loading
    too eager?
    If it is true for your app, you can
    load images with
    ● Intersection Observer
    ● Element Lazy-rendering
    https://calendar.perfplanet.com/2019/native-image-lazy-loading-in-chrome-is-way-too-eager/

    View full-size slide

  51. Web Share
    invokes the native sharing
    mechanism of the device
    The apps or the person could be
    suggested based on the user’s
    engagement

    View full-size slide

  52. Web Share
    invokes the native sharing
    mechanism of the device
    if ('share' in navigator) { // Chrome, Safari
    navigator.share({ title: '', text: '', url: '' });
    } else {
    // Display custom dialog
    }

    View full-size slide

  53. Wake Lock
    prevents devices from dimming
    while recording
    The users can
    ● check the remaining time
    ● tap the stop button
    ● remove noises of when the
    device starts recording in
    background
    O
    rigin
    Trial

    View full-size slide

  54. Wake Lock
    prevents devices from dimming
    while recording
    if ('wakeLock' in navigator) { // Chrome
    let wakeLock;
    const requestWakeLock = async () => {
    try {
    wakeLock
    = await navigator.wakeLock.request('screen');
    } catch (err) { console.error(err); }
    };
    document.addEventListener('visibilitychange', handler);
    document.addEventListener('fullscreenchange', handler);
    } else {
    // you can use NoSleep.js if wake lock is a critical fearture
    // no fallback also makes sence
    }
    O
    rigin
    Trial

    View full-size slide

  55. Native File
    System
    enables developers to control
    device storage
    Use cases (planning):
    ● opening files in the storage
    ● saving recorded audios
    ● downloading favorite audios
    Planning

    View full-size slide

  56. Native File
    System
    enables developers to control
    device storage
    // Chrome
    if (‘chooseFileSystemEntries’ in window) {
    const fileHandle =
    await window.chooseFileSystemEntries();
    } else {
    // fallback with HTML element
    // use to open file
    // use to download files
    }
    Planning

    View full-size slide

  57. Periodic
    Background Sync
    refreshes data periodically in
    backgound
    Use cases (planning):
    ● updating rankings
    ● downloading audios by
    favorite bloggers
    Planning

    View full-size slide

  58. Periodic
    Background Sync
    refreshes data periodically in
    backgound
    const registration
    = await navigator.serviceWorker.ready;
    if ('periodicSync' in registration) { // Chrome
    await registration.periodicSync.register(
    'content-sync',
    { minInterval: 24 * 60 * 60 * 1000 } // one day
    );
    }
    Planning

    View full-size slide

  59. UA Client Hints
    simplify User Agent string
    HTTP request header , User-Agent,
    is going to be freezed
    Tested in Google Chrome Canary 81
    if (req.http.Sec-CH-UA ~ "Google Chrome (\d+)$")
    if (std.atoi(re.group.1) >= 63) {
    call esm_origin;
    }
    }

    View full-size slide

  60. Project Fugu
    for the future web apps
    https://goo.gle/fugu-api-tracker

    View full-size slide

  61. Passion and
    Collaborations

    View full-size slide

  62. @herablog
    Related documents:
    ● アメブロ2019: こえのブログでのPWA
    https://developers.cyberagent.co.jp/blog/archives/20506/
    ● Web App Checklist 〜高品質のWebアプリケーションをつくる
    ために〜
    https://speakerdeck.com/herablog/web-app-checklist-2019-at-inside-frontend
    ● こえのブログでのPWA ~ PWA編 ~
    https://speakerdeck.com/herablog/pwa-night-vol-dot-4
    ● こえのブログでのPWA ~ 開発現場編 ~
    https://speakerdeck.com/herablog/koe-no-blog-pwa
    ● 最新CDN入門 WEB+DB PRESS Vol.109
    https://gihyo.jp/magazine/wdpress/archive/2019/vol109
    ● CDNフル活用でつくる高速 Webアプリ
    https://speakerdeck.com/herablog/using-cdn-to-improve-web-performance
    Life
    Have a nice

    View full-size slide