HTML Optimization for Web Performance

0d605a3350dd7e91b8136aecffd5ceeb?s=47 Shogo Sensui
November 16, 2019

HTML Optimization for Web Performance

2019年11月16日に開催された Frontend Conference Fukuoka 2019 https://eventon.jp/18416/ の「HTML Optimization for Web Performance」のセッション資料です。また、セッション内容を書き起こした解説記事はこちら https://tech.mercari.com/entry/2019/12/02/000000 です。

0d605a3350dd7e91b8136aecffd5ceeb?s=128

Shogo Sensui

November 16, 2019
Tweet

Transcript

  1. HTML Optimization for Web Perfomance Frontend Conference Fukuoka 2019 Shogo

    SENSUI (@1000ch)
  2. Chromium Blog: Moving towards a faster web

  3. Shogo SENSUI (@1000ch) • Software Engineer focusing on the web

    technology • Engineering Manager and Tech Lead at Merpay, Inc. • This is the second in Fukuoka. My first time was 2014.01.25
  4. Why HTML Optimization?

  5. HTML is the first step of rendering a page

  6. The origin of subresources Loading order affects rendering speed directly

  7. Independent of web page type Regardless of dynamic web application

    or not
  8. Easy to optimize relatively Mostly completing in HTML

  9. 3 steps for HTML Optimization 1. Understanding Critical Rendering Path

    2. Measuring Performance Metrics 3. Optimizing HTML
  10. Understanding Critical Rendering Path

  11. Browser Loading Process 1. Download HTML a. Parse HTML to

    construct DOM 2. Download subresources a. Parse CSS to construct CSSOM b. Parse and evaluate JavaScript synchronously c. Parse images, audios, videos, etc. 3. Create Render Tree using DOM and CSSOM a. Wait for DOM and CSSOM b. Layout nodes c. Paint nodes Construct DOM Tree Construct CSSOM Tree Create Render Tree Layout & Paint Execute JavaScript
  12. 1st step. Load HTML • Download HTML from requested URL

    • Parse HTML to construct DOM tree • HTML will be evaluated from the top <html> <head> <meta charset="utf-8"> <title>Basic HTML structure</title> <link rel="stylesheet" href="foo.css"> <link rel="stylesheet" href="bar.css"> </head> <body> <img src="hero.jpg"> <script src="app.js"></script> <script defer src="3rd-party.js"></script> </body> </html>
  13. 2nd step. Load subresources • Download subresources specified in HTML

    elements ◦ <link> ◦ <script> ◦ <img> ◦ <iframe> ◦ etc… • CSS will be downloaded and evaluated asynchronously • JavaScript will be downloaded and evaluated synchronously ◦ will affect DOM and CSSOM <html> <head> <meta charset="utf-8"> <title>Basic HTML structure</title> <link rel="stylesheet" href="foo.css"> <link rel="stylesheet" href="bar.css"> </head> <body> <img src="hero.jpg"> <script src="app.js"></script> <script defer src="3rd-party.js"></script> </body> </html>
  14. 3rd step. Render pages • Wait for DOM and CSSOM

    are completely parsed • Create Render Tree using DOM and CSSOM • Display page ◦ Layout nodes ◦ Paint nodes without CSSOM with CSSOM
  15. Measuring Performance Metrics

  16. Wait, Load and DOMContentLoaded events? • They are not user-centralized

    performance metrics • We want to score the real-user experience
  17. Which experience would you prefer?

  18. Time to Interactive Demo (Airbnb mobile web)

  19. User Centric Performance Metrics

  20. Speed Index • Visual Progress Score of the page •

    Introduced at WebPagetest ◦ Speed Index - WebPagetest Documentation ◦ Further information in Japanese: Speed IndexというWebパフォーマンスの指標 • Slightly difficult to understand and calculate. We need simpler metrics!
  21. First Paint and First Contentful Paint • First Paint: When

    anything on the first view is visible to the users • First Contentful Paint: When any content on the first view is visible to the users
  22. Largest Contentful Paint • Timing when the biggest content on

    the first view was painted • These elements are considered ◦ <img>, <image> in <svg>, <video> ◦ An element with a background image loaded via CSS url() ◦ Block-level elements
  23. Long Tasks • The process make the main thread busy

    • Long Tasks will cause the UI to freeze ◦ Delay time-to-interactive ◦ Input latency
  24. Time to Interactive • How long it takes a page

    to become fully interactive • Use GoogleChromeLabs/tti-polyfill to measure ◦ It requires Long Tasks API is supported
  25. PerformanceObserver API • Enables you to measure the web application

    performance on the user’s device const po = new PerformanceObserver(list => { for (const entry of list.getEntries()) { // `entry` is a PerformanceEntry instance. console.log(entry.entryType); console.log(entry.startTime); console.log(entry.duration); } }); // Start observing the entry types you care about. po.observe({ entryTypes: ['resource', 'paint'] });
  26. To measure FP, FCP, LCP: const observer = new PerformanceObserver(list

    => { for (const entry of list.getEntries()) { ga('send', 'event', { eventCategory: 'Performance Metrics', eventAction: entry.name, eventValue: entry.startTime + entry.duration, nonInteraction: true }); } }); // Start observing the entry types, FP, FCP, LCP. observer.observe({ entryTypes: ['paint', 'largest-contentful-paint'] });
  27. To measure LongTasks: const observer = new PerformanceObserver(list => {

    for (const entry of list.getEntries()) { ga('send', 'event', { eventCategory: 'Performance Metrics', eventAction: 'longtask', eventValue: Math.round(entry.startTime + entry.duration), eventLabel: JSON.stringify(entry.attribution), }); } }); // Start observing the entry types, Long Task. observer.observe({ entryTypes: ['longtask'] });
  28. Performance Audit Tools

  29. Lighthouse • Automated auditing, performance metrics, and best practices for

    the web. • Bundled on Chrome DevTools • GoogleChrome/lighthouse to use from the command line • GoogleChrome/lighthouse-ci to integrate with CI
  30. WebPageTest • Measuring and analyzing the performance of web pages

    • Open-sourced at GitHub. • SpeedCurve - WebPageTest wrapper • Calibre - WebPageTest wrapper • The test result of shogosensui.com • The lighthouse test result of shogosensui.com
  31. How to optimize HTML?

  32. All (sub-)resources should be minified

  33. Optimize CSS Loading 1. Put <link rel=stylesheet> in <head> a.

    To prefer loading CSS and constructing CSSOM b. Putting multiple <link>s is OK! Because browser will load them asynchronously 2. Separate CSS files as possible a. Should NOT be concatenated
  34. Optimize JavaScript Loading 1. Put <script></script> at the end of

    <body> a. To prefer constricting HTML b. To prefer loading subresources 2. Add defer attribute to <script> that loads 3rd party JavaScript a. To prefer rendering the current web page
  35. Basic HTML structure will be... <html> <head> <meta charset="utf-8"> <title>Basic

    HTML structure</title> <link rel="stylesheet" href="foo.css"> <link rel="stylesheet" href="bar.css"> </head> <body> <!-- ... --> <script src="app.js"></script> <script defer src="3rd-party.js"></script> </body> </html>
  36. Preload subresources • Load subresources actively • Specify preload attribute

    for <link> • Preload directive: as attribute to specify the kind of subresource ◦ as=media: Audio, Video ◦ as=script: Script file ◦ as=style: CSS file ◦ as=font: Font file ◦ as=image: Image file ◦ etc... <link rel="preload" href="audio.mp3" as="media"> <link rel="preload" href="app.css" as="style"> <link rel="preload" href="app.js" as="script"> <link rel="preload" href="hero.jpg" as="image">
  37. Preload for module scripts • Load module scripts actively •

    Specify modulepreload attribute for <link> • Further information about modulepreload: ES Modulesを優先 的にロードするmodulepreload <head> <link rel="modulepreload" href="app.mjs"> </head> <!-- ... --> <script type="module" src="app.mjs"></script>
  38. Native lazy-loading for <img> and <iframe> • loading attribute to

    defer the loading of off-screen images and iframes ◦ <img> ◦ <iframe> • Don’t have to use IntersectionObserver and to observe scroll and resize events. <img src="image.png" loading="lazy" alt="…"> <iframe src="https://example.com" loading="lazy"></iframe>
  39. Priority Hints for subresources • importance attribute to suggest the

    resource priority ◦ <link> ◦ <img> ◦ <script> ◦ <iframe> <!-- An image the browser assigns "High" priority, but we don't actually want that. --> <img src="in_viewport_but_not_important.svg" importance="low" alt="..."> <!-- We want to initiate an early fetch for a resource, but also deprioritize it --> <link rel="preload" href="/js/script.js" as="script" importance="low"> <script src="/js/app.js" defer importance="high"></script>
  40. Resource Hints • Load subresources speculatively • DNS Prefetch ◦

    Resolves DNS • Preconnect ◦ Creates TCP connection • Prefetch ◦ Fetches resources • Prefender ◦ Renders HTML page <link rel="dns-prefetch" href="//example.com"> <link rel="preconnect" href="//example.com"> <link rel="preconnect" href="//cdn.example.com" crossorigin> <link rel="prefetch" href="next-page.html" as="document"> <link rel="prefetch" href="lib.js" as="script"> <link rel="prerender" href="next-page.html">
  41. quicklink • Faster subsequent page-loads by prefetching in-viewport links during

    idle time
  42. Conclusion

  43. Conslusion 1. Understanding Critical Rendering Path a. Browsers wait for

    DOM and CSSOM are parsed before rendering 2. Measuring Web Performance Metrics a. Use WebPageTest and Lighthouse to audit the web page b. Audit the web page continuously 3. Optimizing HTML a. For initial loading b. For runtime c. Minimizing payload is the premise for both
  44. Further information? • 基礎知識と実践的なノウハウを体系的 に解説し、Web パフォーマンスに関する 本質的な理解を促します • 詳しくは https://webperf.guide

    を御 覧ください
  45. Thank for listening Ask me anything ❤ by @1000ch