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

Web App Checklist 〜高品質のWebアプリケーションをつくるために〜 / We...

Web App Checklist 〜高品質のWebアプリケーションをつくるために〜 / Web App Checklist 2019 at Inside Frontend

#insideFE slide with @tokimariri.

Web App Checklist😉:
💡Rendering patterns
💡CDN
💡Perf Budget
💡a11y
💡PWA
💡WASM in Web Worker
💡Monitoring tools
💡DX (including LGTM!)
and so on! 🙌

Kazunari Hara

May 18, 2019
Tweet

More Decks by Kazunari Hara

Other Decks in Technology

Transcript

  1. 高品質のWebアプリケーションをつくるために Web App Checklist - To make high quality app

    for better user experience 2019.05.18 Inside Frontend @Abema Towers / Kazunari Hara & tokimari Web App Checklist
  2. 幅広いユーザー 投稿/閲覧スタイル Post function that creates blog entry just by

    speaking お風呂中にも子供を抱っこしていても、料理中でも寝 ながらでも投稿、閲覧ができます
  3. 高品質のWebアプリケーションをつくるために Web App Checklist - To make high quality app

    for better user experience 2019.05.18 Inside Frontend @Abema Towers / Kazunari Hara & tokimari Web App Checklist
  4. no genre title 13 a11y 文字のコントラストは4.5:1以上 14 a11y 色だけで説明しない 15

    a11y 要素の選択は適切に 16 a11y キー操作だけで利用できる 17 a11y,UX フォーカスを可視化する 18 UX スクロール位置を復元 19 UX,a11y 修正・削除ができる 20 UX 継続的なモニタリング 21 UX ストレスのない遷移とローディング 22 UX レイアウトを固定する 23 a11y,UX 突然音を出さない 24 Security セキュリティ監査する no genre title 1 UX 適切なレンダリングパターンを選択 2 Perf 安定したサーバレスポンス 3 Perf 圧縮したメディアフォーマットを利用 4 Perf,UX リソースを必要なタイミングで読み込む 5 Perf Webパフォーマンスを監視 6 UX Off the main thread 7 UX オフラインでも利用できる 8 UX モバイルでもデスクトップでも使える 9 PWA メタデータを提供 10 DX OSSのように開発 11 UX Progressive Enhancement 12 a11y,SEO 画像に代替テキストを設定する Checklist: 36
  5. no genre title 13 a11y 文字のコントラストは4.5:1以上 14 a11y 色だけで説明しない 15

    a11y 要素の選択は適切に 16 a11y キー操作だけで利用できる 17 a11y,UX フォーカスを可視化する 18 UX スクロール位置を復元 19 UX,a11y 修正・削除ができる 20 UX 継続的なモニタリング 21 UX ストレスのない遷移とローディング 22 UX レイアウトを固定する 23 a11y,UX 突然音を出さない 24 Security セキュリティ監査する no genre title 1 UX 適切なレンダリングパターンを選択 2 Perf 安定したサーバレスポンス 3 Perf 圧縮したメディアフォーマットを利用 4 Perf,UX リソースを必要なタイミングで読み込む 5 Perf Webパフォーマンスを監視 6 UX Off the main thread 7 UX オフラインでも利用できる 8 UX モバイルでもデスクトップでも使える 9 PWA メタデータを提供 10 DX OSSのように開発 11 UX Progressive Enhancement 12 a11y,SEO 画像に代替テキストを設定する Checklist: 36 Today: only 20
  6.   TTI = FCP   Inflexible Server Side Rendering ロジックは

    サーバー側 GET / Network JS TTIはJS構成 に依存する Logics are in server side TTI depends on JS architecture
  7. SSR with hydration   Flexible   TTI >>>> FCP データを使ってク

    ライアントで描画 GET / Network JS DATA={} bundle.js render(DATA) Client rendering with initial data
  8. Client Side Rendering   Flexible, Fast TTFB   TTI >>>>

    FCP GET / FCP TTI Network JS bundle.js render() FCPはもっと遅く なることも
  9. GET / FCP TTI JS app.js render() • H2 Server

    Push (Preload) • Web Components ... こえのブログ はCSRを選択 できるだけはやい CSRに挑戦 JSの並列配信 Parallel JS requests Our challenge was to make CSR app as fast as possible 小さいJS Light JS
  10. Server response is fundamental for web performance. サーバレスポンス は根本的 サーバレスポンスが遅い

    と何も表示されない Waiting with blank page when server response is too slow.
  11. Reasons for server-side latency. サーバ遅延の要因 • 地理 Location • 計算量

    Computation • キャパシティ Capacity • リダイレクト Redirect • DBクエリ DB Queries ...
  12. Use CDN for edge side caching.こえのブロ グで利 CDNキャッシュ の利用 高キャッシュヒット率で

    オリジンサーバーに 1度しかリクエストしない Only requests content to the origin server once because of high cache hit ratio.
  13. Cache content in CDN as long as possible. できるだけ長く CDNキャッシュ

    長いTTLと Surrogate Keyを指定 JavaScript TTL: 30days Key: web/release Entry data 30days blogger/${ID} entry/${ID} Setting long TTL and Surrogate Key
  14. Edge-side computing. エッジサイド コンピュー ティング URLからSurrogate Key を抽出 sub vcl_fetch

    { declare local var.SurrogateKey STRING; if (req.http.x-url ~ "/([a-z0-9-]{3,24})/([a-zA-Z0-9]+)") { set var.SurrogateKey = var.SurrogateKey + " blogger/" + re.group.1 + " entry/" + re.group.2; // e.g. ogger/abcde", "entry/12345" } set beresp.http.Surrogate-Key = var.SurrogateKey; } Extracting surrogate keys from URL
  15. According to Lighthouse, the size of images could still be

    reduced. まだまだ減らせる画像容量
  16. List of image file formats 画像フォーマット • JPEG • Progressive

    JPEG • PNG • WebP • SVG • Animation GIF 画質を指定して利用 ファイルサイズに注意 高圧縮 動画のが軽いことも
  17. List of image CDN providers. Image CDN • Akamai •

    Cloudinary • Imgix • Fastly • Hayabusa
  18. List of image CDN providers. Image CDN • Akamai •

    Cloudinary • Imgix • Fastly • Hayabusa こえのブログ で利用
  19. Feature Detection if ('loading' in HTMLImageElement.prototype) { // Use Native

    lazy-loading } else { // Use Intersection Observer (or polyfill) }
  20. パフォーマンス バジェットは 超えちゃいけない制限 Performance budget is a limit for pages

    which the team is not allowed to exceed. Timing Resource Rule カスタム指標もOK Custom metrics are also available
  21. “Performance budgets are not just thresholds. Much like a financial

    budget, they're something consciously spent.“ Addy Osmani Perf指標を財政予算に見立てて管理
  22. こえのブログ Perf Budget Perf Budget Values. Entrypoint HTML <= 14KB

    App Shell JS <= 120KB Chunk JS <= 20KB FCP on Fast 3G <= 1.5s TTI on Fast 3G <= 3s 品質劣化をはやめに検知する ため、アグレッシブな設定 Aggressive budgets to find out quality deterioration 予算オーバーすると デプロイできない CI stops deployment if resource size exceeds the budget
  23. Service Worker Precache index.html Revision:adcoaeo voice-app.js Revision:4f39dn3 logo.svg Revision:mfj48dj Revision変

    わったファイ ルのみ再取得 ビルドした全アセッ トをプリキャッシュ Precaching all assets Re-fetching only updated scripts
  24. Workbox.routing.registerNavigationroute( '/index.html', { whitelist: [ /^\/editor/, /^\/embed/, ... ] },

    ); 特定パスへのナビゲー ションリクエスト時に プリキャッシュした index.htmlを返却する Return precache HTML when navigation request Service Worker Precache
  25. メディア クエリ Media Queries @media screen and (min-width: 1025px) {

    :root { --app-header-height: 60px; --app-page-background-color: var(--clr-whitesmoke); --app-drawer-width: 400px; } } カスタムプロパティで 全体レイアウトを一箇 所で指定 Set layout as custom properties in root selector.
  26. Web App Manifest { “name”: “こえのブログ by Ameba”, “description”: “「こえのブログ」は...”,

    “lang”: “ja-JP”, “icons”: [...], “background_color”: “#fff”, “theme_color”: “#fff”, “start_url”: “/?source=homescreen”, “scope”: “/”, “display”: “standalone” } iOS 12.2での対応により スタンドアローンで OAuthも利用可能に OAuth is available in standalone mode on later iOS 12.2
  27. Meta for Social Media. <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:site" content="@ameba_official">

    <meta name="twitter:title" content="1月24日のこえ"> <meta name="twitter:description" content="こんばんは..."> <meta property="twitter:image" content="https://voice.ameba.jp/share.jpg"> <meta property="fb:app_id" content="311629842256842"> <meta property="og:type" content="website"> <meta property="og:url" content="https://voice.ameba.jp/embed/"> <meta property="og:title" content="1月24日のこえ"> <meta property="og:image" content="https://voice.ameba.jp/share.jpg"> SNS用 メタデータ
  28. • IE11~ • Edge • Android OS 5~ • iOS11~

    こえのブログの”閲覧” =アメブロの標準機能 “Browsing” Koe-no-blog is a standard feature of Ameblo. User can experience it by followings browsers:
  29. { "builds": [ { "name": "esm-bundled", "browserCapabilities": ["es2015","modules"], "js": {

    "minify": true }, … "bundle": true, "addServiceWorker": false }, { "name": "es5-bundled", "js": { "compile": "es5", "minify": false, "transformModulesToAmd": true }, … "bundle": true, "addServiceWorker": false } ] } • ES Modules bundled file • ES5 bundled file CDNで別の ファイルを配信 Deliver another assets file by CDN. Method 1
  30. PASS ./build/es5-bundled/src/components/voice-app.js: 124.69KB < maxSize 140KB PASS ./build/esm-bundled/src/components/voice-app.js: 77.81KB <

    maxSize 120KB PASS ./build/es5-bundled/src/components/voice-embed.js: 21.49KB < maxSize 25KB PASS ./build/esm-bundled/src/components/voice-embed.js: 18.61KB < maxSize 20KB PASS ./build/es5-bundled/src/components/lazy-resources.js: 17.36KB < maxSize 20KB PASS ./build/esm-bundled/src/components/lazy-resources.js: 12.26KB < maxSize 15KB PASS ./build/es5-bundled/index.html: 9.47KB < maxSize 14KB PASS ./build/esm-bundled/index.html: 3.15KB < maxSize 14KB File size reduced: -37% ESModules bundle < ES5 bundle CDNで別の ファイルを配信 Method 1 Deliver another assets file by CDN.
  31. • Web Share API • Network Information API • Intersection

    Observer • Vibration API • etc... Provide better experience with new technologies 新しい技術を より良い体験に Web Share API Original Dialog Method 2
  32. 閲覧の状況で見え方は違う How user sees it depends on the situation. •

    視力 Sight • 色覚異常 Color blindness • 外出先 Outside • etc…
  33. Too low (2.8:1)→ little higher (4.3:1) Use high contrast color

    for text • Ameba Green: for logo, icon / 4.26:1 • Dark Green: for text / 4.66:1 1か0かではなく、まずは向上する At first, we improve contrast a little more than now.
  34. まだ見ぬ未来のデバイス、ちょっと変わったUI キー操作できる If it can be operated with the keyboard,

    = 色々なデバイスで操作できる it can be operated with various devices
  35. if (prevPage && prevPage !== currentPage) { const title =

    `${title} | ${siteName}`; const announcer = document.getElementById('js-announcer'); window.document.title = title; if (announcer) { announcer.innerHTML = documentTitle; } document.body.focus(); } <body tabindex=”-1”> <div id="js-announcer" aria-live="assertive"></div> … </body> Move focus, Read title Example 2
  36. .drawer-list > a { color: var(--app-dark-text-color); font-size: 1.4rem; -webkit-tap-highlight-color: var(--app-focus-background-color);

    outline: none; text-decoration: none; } .drawer-list > a:focus { background-color: var(--app-focus-background-color); } スタイル適用 → 標準スタイル削除 Apply your own focus style and then remove the default style.
  37. .drawer-list > a { color: var(--app-dark-text-color); font-size: 1.4rem; -webkit-tap-highlight-color: var(--app-focus-background-color);

    outline: none; text-decoration: none; } .drawer-list > a:focus { background-color: var(--app-focus-background-color); } スタイル適用 → 標準スタイル削除 Apply your own focus style and then remove the default style.
  38. if (isChrome) { if ('scrollRestoration' in window.history) { // ブラウザの復元処理を使わない

    window.history.scrollRestoration = 'manual'; } var scriptEl = document.createElement('script'); scriptEl.setAttribute('src', 'node_modules/delayed-scroll-restoration-polyfill/ index.js'); scriptEl.setAttribute('defer', 'defer'); document.body.appendChild(scriptEl); } 基本は ブラウザ任せ Use browser's standard process.
  39. if (isChrome) { if ('scrollRestoration' in window.history) { // ブラウザの復元処理を使わない

    window.history.scrollRestoration = 'manual'; } var scriptEl = document.createElement('script'); scriptEl.setAttribute('src', 'node_modules/delayed-scroll-restoration-polyfill/ index.js'); scriptEl.setAttribute('defer', 'defer'); document.body.appendChild(scriptEl); } マニュアル 操作にする Use manual operation if possible.
  40. no genre title 13 a11y 文字のコントラストは4.5:1以上 14 a11y 色だけで説明しない 15

    a11y 要素の選択は適切に 16 a11y キー操作だけで利用できる 17 a11y,UX フォーカスを可視化する 18 UX スクロール位置を復元 19 UX,a11y 修正・削除ができる 20 UX 継続的なモニタリング 21 UX ストレスのない遷移とローディング 22 UX レイアウトを固定する 23 a11y,UX 突然音を出さない 24 Security セキュリティ監査する no genre title 1 UX 適切なレンダリングパターンを選択 2 Perf 安定したサーバレスポンス 3 Perf 圧縮したメディアフォーマットを利用 4 Perf,UX リソースを必要なタイミングで読み込む 5 Perf Webパフォーマンスを監視 6 UX Off the main thread 7 UX オフラインでも利用できる 8 UX モバイルでもデスクトップでも使える 9 PWA メタデータを提供 10 DX OSSのように開発 11 UX Progressive Enhancement 12 a11y,SEO 画像に代替テキストを設定する Web App Checklist http://bit.ly/web_app_checklist
  41. • アメブロ2019: こえのブログでのPWA | CyberAgent Developers Blog https://developers.cyberagent.co.jp/blog/archives/20506/ • アクセシブルなブログ開発、

    その後どうなったの https://www.slideshare.net/MarinaToki/ss-135424096 • こえのブログでのPWA ~ 開発現場編 ~ / Koe-No-Blog PWA - Speaker Deck https://speakerdeck.com/herablog/koe-no-blog-pwa • こえのブログでのPWA ~ PWA編 ~ / PWA Night Vol.4 https://speakerdeck.com/herablog/pwa-night-vol-dot-4 Related Slides