More Than You Ever Wanted to Know About Resource Hints

More Than You Ever Wanted to Know About Resource Hints

Resource Hints are a great way for developers to make their web pages faster by allowing us to be a little bit smarter than the browser. Although not a new specification—they’ve been around in some form or another for years!—are we truly getting the most out of them? And do we understand them thoroughly enough to use them most effectively? Heck, do we even know what a ‘Resource Hint’ is?! Well, by the end of this talk, we’ll all be experts.

Let’s take a look at all of the different Resource Hints we have available to us, real-world examples of how best to use them, and learn about some of the more obscure intricacies and gotchas that we need to be aware of if we want to really get the best out of them (and to make sure that we really are being smarter than the browser).

Bb854891c46db72f4a6f9da4504e879a?s=128

Harry Roberts

April 20, 2019
Tweet

Transcript

  1. More Than You Ever Wanted to Know About Resource Hints

    Harry Roberts • @csswizardry
  2. Hi, I’m Harry Consultant Performance Engineer Leeds, UK csswizardry.com @csswizardry

  3. None
  4. None
  5. i Pro-Tip / Short Summary

  6. ! Caveat / Warning / Bug

  7. None
  8. Resource Hints

  9. “ “These primitives enable the developer […] to assist the

    user agent in the decision process of which origins it should connect to, and which resources it should fetch and preprocess to improve page performance.”
  10. i Single lines of HTML that can dramatically speed up

    your site
  11. <head> ... <link rel="preconnect" href="https://www.youtube.com/" /> <link rel="prefetch" href="app.ae72eb.js" />

    <link rel="preload" href="/assets/webfont.woff2" as="font" type="font/woff2" crossorigin /> ... </head>
  12. csswz.it/rh

  13. Overview 1.dns-prefetch 2.preconnect 3.prefetch 4.preload 5.subresource 6.prerender

  14. dns-prefetch

  15. csswz.it/dns-prefetch

  16. i Resolve the IP address for a given domain ahead

    of time
  17. i When you know the domain but not the URL

  18. <link rel="dns-prefetch" href="https://youtube.com" />

  19. None
  20. 154 <iframe 155 src="https://www.youtube.com/embed/5g8a9luSZVI" 156 width="560" height="315"> 157 </iframe>

  21. 5g8a9luSZVI

  22. DNS Lookup

  23. 216.58.198.110

  24. “ “[…] common names […] can answer in closer to

    80–120ms. […] an uncommon name […] can average closer to 200–300ms.” — csswz.it/2GuZo21
  25. “ “More interestingly, for any of these queries that access

    the internet, dropped packets, and overworked (under provisioned) name resolvers, regularly increases the total resolution time to between 1 and 10 seconds.” — csswz.it/2GuZo21
  26. @andydavies

  27. ! dns-prefetch is implemented as prefetch in IE9…

  28. preconnect

  29. csswz.it/preconnect

  30. i Resolve the IP address and open a TCP/TLS connection

    for a given domain ahead of time
  31. i When you know the domain but not the URL

  32. <link rel="preconnect" href="https://fonts.googleapis.com" />

  33. None
  34. 5g8a9luSZVI

  35. TCP Handshake TLS Negotiation

  36. hpbn.co

  37. None
  38. None
  39. preconnect with
 dns-prefetch fallback

  40. <link rel="preconnect dns-prefetch" href="//twitter.com" />

  41. ! Breaks in Safari

  42. None
  43. @andydavies

  44. <link rel="preconnect" href="https://twitter.com" /> <link rel="dns-prefetch" href="https://twitter.com" />

  45. ! Be judicious with preconnect

  46. Be Judicious Only warm up frequent, significant, and likely origins

    Don’t warm up fourth, fifth, sixth party origins Opening many connections can have a CPU and battery cost Chrome can only conduct six simultaneous DNS resolutions
  47. ! Firefucked

  48. None
  49. prefetch

  50. csswz.it/prefetch

  51. i A file needed for subsequent navigation

  52. <link rel="prefetch" href="/assets/video-player.js" />

  53. None
  54. None
  55. None
  56. <!-- search-results.html --> <link rel="prefetch" href="/assets/video-player.js" />

  57. i Download the file and drop it into HTTP cache

    for later usage
  58. “ “The user agent SHOULD NOT apply preprocessing on the

    response and MUST NOT automatically execute or apply it against the current page context.”
  59. <!-- search-results.html --> <link rel="prefetch" href="/assets/video-player.js" /> <!-- video.html -->

    <script src="/assets/video-player.js"></script> Downloaded by this… … executed by this.
  60. Caching prefetch will not execute or otherwise process the resource

    It will drop it into HTTP cache as per its caching headers Except…
  61. “ “…those with the no-store Cache- Control header. A resource

    will be revalidated before use if there is a Vary response header, no-cache Cache- Control header, or if the resource is more than five minutes old.” — csswz.it/nostate-prefetch
  62. i Fetched with lowest possible priority

  63. i In-flight prefetches persist across navigations

  64. None
  65. None
  66. ! …prefetch acts like dns-prefetch in IE9

  67. <link rel="prefetch"
 href="https://code.jquery.com/jquery-3.4.0.js" />

  68. preload

  69. csswz.it/preload

  70. i A mandatory fetch for a file needed for the

    current navigation
  71. i A way to surface late- discovered resources

  72. <link rel="preload" href="/assets/webfont.woff2" as="font" type="font/woff2" crossorigin />

  73. <link rel="preload" href="/assets/webfont.woff2" as="font" type="font/woff2" crossorigin />

  74. None
  75. Late-discovered resource?

  76. HTML CSS Font } 1000ms

  77. HTML CSS Background } 1250ms

  78. HTML CSS Font JS VDOM } 1350ms

  79. preload helps the browser find them sooner

  80. <script src="assets/app.js"></script> <link rel="preload" href="assets/app.css" as="style" /> <link rel="preload" href="assets/font.woff2"

    as="font" type="font/woff2" crossorigin />
  81. HTML CSS Font JS VDOM } 750ms

  82. The as Attribute

  83. <link rel="preload" href="/assets/webfont.woff2" as="font" type="font/woff2" crossorigin />

  84. "audio" "document" "embed" "fetch" "font" as="image" "object" "script" "style" "track"

    "video" "worker"
  85. “ “The attribute is necessary to guarantee correct prioritization, request

    matching, application of the correct CSP3 policy, and setting of the appropriate Accept request header.”
  86. None
  87. ! Don’t try to be sneaky

  88. <link rel="preload" href="style.css" as="style" /> <link rel="preload" href="app.js" as="script" />

    <link rel="preload" href="image.jpg" as="image" />
  89. <link rel="preload" href="style.css" as="image" /> <link rel="preload" href="app.js" as="style" />

    <link rel="preload" href="image.jpg" as="script" />
  90. None
  91. i Priority Hints will help

  92. <link rel="preload" href="masthead.jpg" as="image" importance="high" /> <link rel="preload" href="lazy.css" as="style"

    importance="low" />
  93. The type Attribute

  94. <link rel="preload" href="hero.webp" as="image" type="image/webp" />

  95. The crossorigin Attribute

  96. “ “Preload links for CORS enabled resources, such as fonts

    or images with a crossorigin attribute, must also include a crossorigin attribute, in order for the resource to be properly used.”
  97. i Keep an eye on Console

  98. None
  99. ! Beware Google Chrome

  100. Chrome Issues Chrome over-prioritises preload Dispatches preloads before other critical

    resources Often returns less-critical resources sooner
  101. @andydavies

  102. @andydavies

  103. 0.4s slower to start render @andydavies

  104. subresource

  105. i Precursor to preload…

  106. ! …but completely deprecated.

  107. <link rel="subresource" href="/assets/webfont.woff2" />

  108. SUBRESOURCE

  109. “ “…not useful, proprietary, and buggy.” — Yoav Weiss, csswz.it/2VOEyQc

  110. prerender

  111. csswz.it/prerender

  112. i Download and build entire webpages in the background…

  113. i …kinda…

  114. i …it’s complicated.

  115. None
  116. <link rel="prerender" href="/login/" />

  117. None
  118. None
  119. PRERENDER

  120. Problematic Prerender Huge memory footprint with rendering whole new pages

    Bandwidth usage spikes for site and user Register multiple analytics hits, ad impressions How do we handle timers, HTTP auth, interstitials, autoplay media? How do we handle animations? Do we expect the carousel to start running? Or do we write more code to wait for page visibility? What if we get MitM and are made to prerender a malicious page? How would the user know? They wouldn’t!
  121. Prerender is dead,
 long live prerender!

  122. Prerender is dead,
 long live prerender! NoState Prefetch

  123. i prerender is the API; NoState Prefetch is the mechanism

  124. ! prerender will not render anything

  125. ! prerender will not render anything !

  126. NoState Prefetch

  127. i A recursive prefetch

  128. A B B1 B2 B3 B4 B5

  129. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport"

    content="width=device-width, minimum-scale=1.0" /> <title>Prerender</title> <link rel="prerender" href="https://csswizardry.com" /> </head> <body> <h1>Prerender</h1> </body> </html>
  130. i Fetched with lowest possible priority

  131. None
  132. Tips, Tricks, and Gotchas

  133. i Deploy as HTTP Headers

  134. None
  135. @andydavies

  136. ! Edge only supports HTTP header for preconnect

  137. ! Edge doesn’t support HTTP header for preload

  138. i Generate Dynamically

  139. instant.page

  140. None
  141. ! Have an escape hatch

  142. if ($omgWeAreBeingDDoSed == false) { <script src="https://instant.page/1.1.0" defer></script> }

  143. ! You Need a Scheme

  144. <link rel="preconnect" href="domain.com" /> == <link rel="preconnect" href="./domain.com" />

  145. <link rel="preconnect" href="https://domain.com" />

  146. All Together!

  147. Implementing Resource Hints 1.Identify a key page 2.Audit important assets

    and origins 3.Assess likely user flows 4.Design bespoke Resource Hint strategies
  148. Web font Likely next navigation Critical third party

  149. Web font Likely next navigation Critical third party JS image

    gallery
  150. Resource Hint Strategy 1.HTTP header preconnect to cloudinary 2.Regular preconnect

    for other third parties 3.preload to discover web font sooner 4.prefetch for gallery.js 5.prerender or prefetch for likely next navigation
  151. // HTTP response header link: <https://res.cloudinary.com>; rel=preconnect

  152. <!-- Preconnect other third party origins --> <link rel="preconnect" href="https://www.google-analytics.com">

    <link rel="dns-prefetch" href="https://www.google-analytics.com">
  153. <!-- Early-discover web font --> <link rel="stylesheet" href="/assets/app.css" /> <link

    rel="preload" href="/assets/webfont.woff2" as="font" type="font/woff2" crossorigin />
  154. <!-- Prefetch image gallery for next page --> <link rel="prefetch"

    href="/assets/gallery.js" />
  155. <!-- Prerender first three search results --> <link rel="prerender" href="/products/one.html"

    /> <link rel="prerender" href="/products/two.html" /> <link rel="prerender" href="/products/three.html" />
  156. <head> <link rel="preconnect" href="https://www.google-analytics.com"> <link rel="dns-prefetch" href="https://www.google-analytics.com"> <link rel="stylesheet" href="/assets/app.css"

    /> <link rel="preload" href="/assets/webfont.woff2" as="font" type="font/woff2" crossorigin /> <link rel="prefetch" href="/assets/gallery.js" /> <link rel="prerender" href="/products/one.html" /> <link rel="prerender" href="/products/two.html" /> <link rel="prerender" href="/products/three.html" /> </head>
  157. <head> <link rel="prefetch" href="/assets/product-01-large.jpg" /> <link rel="prefetch" href="/assets/product-02-large.jpg" /> <link

    rel="prefetch" href="/assets/product-03-large.jpg" /> </head>
  158. Thank You! @csswizardry csswizardry@gmail.com speakerdeck.com/csswizardry harry.is/for-hire