requestmetrics.com.rss.xml - sfeed_tests - sfeed tests and RSS and Atom files
HTML git clone git://git.codemadness.org/sfeed_tests
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
requestmetrics.com.rss.xml (187688B)
---
1 <?xml version="1.0" encoding="UTF-8"?>
2 <rss version="2.0"
3 xmlns:atom="http://www.w3.org/2005/Atom"
4 xmlns:content="http://purl.org/rss/1.0/modules/content/"
5 xmlns:media="http://search.yahoo.com/mrss/"
6 xmlns:webfeeds="http://webfeeds.org/rss/1.0">
7 <channel>
8 <title>Web Performance | Request Metrics</title>
9 <link rel="alternate">https://requestmetrics.com/web-performance/</link>
10 <atom:link rel="self" href="https://requestmetrics.com/web-performance/feed.xml" type="application/rss+xml" />
11 <description>Learn about performance on the web with tutorials on the concepts, tools, and tactics to make your site faster.</description>
12 <category>Web Performance</category>
13 <image>
14 <url>https://requestmetrics.com/assets/images/request_metrics_logo_rss.png</url>
15 <title>Web Performance | Request Metrics</title>
16 <link>https://requestmetrics.com/web-performance/</link>
17 </image>
18 <webfeeds:cover image="https://requestmetrics.com/assets/images/share.min.png" />
19 <webfeeds:icon>https://requestmetrics.com/assets/images/favicon/apple-touch-icon.png</webfeeds:icon>
20 <webfeeds:logo>https://requestmetrics.com/assets/images/request_metrics_logo.svg</webfeeds:logo>
21 <webfeeds:accentColor>4879D9</webfeeds:accentColor>
22 <webfeeds:related layout="card" target="browser"/>
23 <webfeeds:analytics id="UA-42539664-5" engine="GoogleAnalytics" />
24 <language>en-us</language>
25 <managingEditor>hello@requestmetrics.com (Request Metrics)</managingEditor>
26 <webMaster>hello@requestmetrics.com (Request Metrics)</webMaster>
27 <copyright>2019-2021 TrackJS LLC. All rights reserved.</copyright>
28 <pubDate>Wed, 15 Dec 2021 15:23:05 +0000</pubDate>
29 <lastBuildDate>Wed, 15 Dec 2021 15:23:05 +0000</lastBuildDate>
30
31
32
33
34
35 <item>
36 <title>HTTP/3 is Fast</title>
37 <link>https://requestmetrics.com/web-performance/http3-is-fast</link>
38 <guid isPermaLink="true">https://requestmetrics.com/web-performance/http3-is-fast</guid>
39 <description>
40 HTTP/3 is here, and it’s a big deal for web performance. See just how much faster it makes websites!
41
42 </description>
43 <media:content url="https://requestmetrics.com/assets/images/webperf/http3/http3-teaser-2000.png" medium="image" type="image/png" height="350" width="700" />
44 <enclosure url="https://requestmetrics.com/assets/images/webperf/http3/http3-teaser-2000.png" type="image/png" />
45 <content:encoded><![CDATA[
46 <div><img src="https://requestmetrics.com/assets/images/webperf/http3/http3-teaser-2000.png" alt="HTTP/3 is Fast" class="webfeedsFeaturedVisual" /></div>
47
48 <p>HTTP/3 is here, and it’s a big deal for web performance. See just how much faster it makes websites!</p>
49
50 <!--more-->
51
52 <p>Wait, wait, wait, what happened to HTTP/2? Wasn’t that all the rage only a few short years ago? It sure was, but there were some <a href="https://en.wikipedia.org/wiki/HTTP/2#Criticisms">problems</a>. To address them, there’s a <a href="https://quicwg.org/base-drafts/draft-ietf-quic-http.html">new version</a> of the venerable protocol working its way through the standards track.</p>
53
54 <p>Ok, but does HTTP/3 actually make things faster? It sure does, and we’ve got the benchmarks to prove it.</p>
55
56 <h2 id="a-quick-preview">A Quick Preview</h2>
57 <p>Before we get too deep in the details, let’s look at a quick preview of the benchmark results. In the charts below the same browser was used to request the same site, over the same network, varying only the HTTP protocol in-use. Each site was retrieved 20 times and the response time measured via the performance API. (More details on <a href="#benchmarking-http3">benchmark methodology</a> later)</p>
58
59 <p>You can clearly see the performance improvement as each new version of the HTTP protocol is used:</p>
60
61 <figure class="wide flex">
62 <div class="image-wrap-3x wide-wrap">
63 <img src="https://requestmetrics.com/assets/images/webperf/http3/ny-all-protocols.png" width="1144" loading="lazy" height="353" alt="Comparing the three HTTP protocol versions when loading pages from NY" />
64 </div>
65 </figure>
66
67 <p>And the changes become even more pronounced when requesting resources over larger geographic distances and less reliable networks.</p>
68
69 <p>But before we can get fully in to all the HTTP/3 benchmark minutiae, a little context is required.</p>
70
71 <h2 id="a-brief-history-of-http">A Brief History of HTTP</h2>
72
73 <p>The <a href="https://datatracker.ietf.org/doc/html/rfc1945">first official version</a> of HTTP (Hypertext Transfer Protocol 1.0) was finalized in 1996. There were some practical issues and parts of the standard that needed updating, so <a href="https://datatracker.ietf.org/doc/html/rfc2068">HTTP/1.1</a> was released a year later in 1997. Per the authors:</p>
74
75 <blockquote>
76 <p>However, HTTP/1.0 does not sufficiently take into consideration the effects of hierarchical proxies, caching, the need for persistent connections, and virtual hosts. In addition, the proliferation of incompletely-implemented applications calling themselves “HTTP/1.0” has necessitated a protocol version change in order for two communicating applications to determine each other’s true capabilities.</p>
77 </blockquote>
78
79 <p>It would be 18 more years before a new version of HTTP was released. In 2015, and with much fanfare, <a href="https://datatracker.ietf.org/doc/html/rfc7540">RFC 7540</a> would standardize HTTP/2 as the next major version of the protocol.</p>
80
81 <h3 id="one-file-at-a-time">One File at a Time</h3>
82 <p>If a web page requires 10 javascript files, the web browser needs to retrieve those 10 files before the page can finish loading. In HTTP/1.1-land, the web browser can only download a single file at a time over a TCP connection with the server. This means the files are downloaded sequentially, and any delay in one file would block everything else behind it. This is called <a href="https://en.wikipedia.org/wiki/Head-of-line_blocking">Head-of-line Blocking</a> and it’s not good for performance.</p>
83
84 <p>To work around this, browsers can open multiple TCP connections to the server to parallelize the data retrieval. But this approach is resource intensive. Each new TCP connection requires client and server resources, and when you add TLS in the mix there’s plenty of SSL negotiation happening too. A better way was needed.</p>
85
86 <h3 id="multiplexing-with-http2">Multiplexing with HTTP/2</h3>
87 <p>HTTP/2’s big selling point was multiplexing. It fixed <em>application level</em> head-of-line blocking issues by switching to a binary over-the-wire format that allowed multiplexed file downloads. That is, a client could request all 10 files at once and start downloading them all in parallel over a single TCP connection.</p>
88
89 <p>Unfortunately HTTP/2 still suffers from a head-of-line blocking issue, just one layer lower. TCP itself becomes the weak link in the chain. Any data stream that loses a packet must wait until that packet is <a href="https://quicwg.org/base-drafts/draft-ietf-quic-http.html#name-prior-versions-of-http">retransmitted to continue</a>.</p>
90
91 <blockquote>
92 <p>However, because the parallel nature of HTTP/2’s multiplexing is not visible to TCP’s loss recovery mechanisms, a lost or reordered packet causes all active transactions to experience a stall regardless of whether that transaction was directly impacted by the lost packet.</p>
93 </blockquote>
94
95 <p>In fact, in high packet loss environments, HTTP/1.1 performs better because of the multiple parallel TCP connections the browser opens!</p>
96
97 <h3 id="true-multiplexing-with-http3-and-quic">True Multiplexing with HTTP/3 and QUIC</h3>
98 <p>Enter HTTP/3. The major difference between HTTP/2 and HTTP/3 is which transport protocol they use. Instead of TCP, HTTP/3 uses a new protocol called <a href="https://www.rfc-editor.org/rfc/rfc9000.html">QUIC</a>. QUIC is a general purpose transport protocol meant to address the head-of-line blocking issues HTTP/2 has with TCP. It allows you to create a <a href="https://quicwg.org/base-drafts/draft-ietf-quic-http.html#name-delegation-to-quic">series of stateful streams</a> (similar to TCP) over UDP.</p>
99
100 <figure class="wide">
101 <img src="https://requestmetrics.com/assets/images/webperf/http3/udp-joke.min.png" width="400" height="480" loading="lazy" alt="I have a UDP Joke... but you might not get it" />
102 </figure>
103
104 <blockquote>
105 <p>The QUIC transport protocol incorporates stream multiplexing and per-stream flow control, similar to that provided by the HTTP/2 framing layer. By providing reliability at the stream level and congestion control across the entire connection, <strong>QUIC has the capability to improve the performance of HTTP compared to a TCP mapping</strong></p>
106 </blockquote>
107
108 <p>And improve the performance of HTTP it does! <a href="#so-how-fast-is-http3">Jump to the results if you don’t care about how the test was conducted</a></p>
109
110 <h2 id="benchmarking-http3">Benchmarking HTTP/3</h2>
111 <p>To see just what sort of performance difference HTTP/3 makes, a benchmarking test setup was needed.</p>
112 <h3 id="the-html">The HTML</h3>
113 <p>In order to more closely approximate actual usage, the test setup consisted of three scenarios - a small site, a content-heavy site (lots of images and some JS), and a single page application (heavy on the JS). I looked at several real-world sites and averaged the number of images and JS files for each, then coded up some demo sites that matched those resource counts (and sizes).</p>
114
115 <ul>
116 <li>Small Site
117 <ul>
118 <li><strong>10</strong> JS files from 2kb to 100kb</li>
119 <li><strong>10</strong> images from 1kb to 50kb</li>
120 <li>Total payload size <strong>600kb</strong>, 20 blocking resources total</li>
121 </ul>
122 </li>
123 <li>Content Site
124 <ul>
125 <li><strong>50</strong> JS files from 2kb to 1mb</li>
126 <li><strong>55</strong> images ranging in size from 1kb to 1mb.</li>
127 <li>Total payload size <strong>10MB</strong>, 105 resources total (look at cnn.com sometime in dev tools and you’ll see why this is so big)</li>
128 </ul>
129 </li>
130 <li>Single Page Application
131 <ul>
132 <li><strong>85</strong> JS files from 2kb to 1mb</li>
133 <li><strong>30</strong> images ranging in size from 1kb to 50kb.</li>
134 <li>Total payload size <strong>15MB</strong>, 115 resources total (look at JIRA sometime in dev tools)</li>
135 </ul>
136 </li>
137 </ul>
138
139 <h3 id="the-server">The Server</h3>
140 <p><a href="https://caddyserver.com/">Caddy</a> was used to serve all assets and HTML.</p>
141
142 <ul>
143 <li>All responses were served with <code class="language-plaintext highlighter-rouge">Cache-Control: "no-store"</code> to ensure the browser would re-download every time.</li>
144 <li>TLS 1.2 was used for HTTP/1.1 and HTTP/2</li>
145 <li><a href="https://www.rfc-editor.org/rfc/rfc9001.html">TLS 1.3</a> was used for HTTP/3.</li>
146 <li><a href="https://www.rfc-editor.org/rfc/rfc9001.html#name-0-rtt">0-RTT</a> was enabled for all HTTP/3 connections</li>
147 </ul>
148
149 <h3 id="the-locations">The Locations</h3>
150 <p>The tests were conducted from my computer in Minnesota, to three separate datacenters hosted by Digital Ocean:</p>
151
152 <ul>
153 <li>New York, USA</li>
154 <li>London, England</li>
155 <li>Bangalore, India</li>
156 </ul>
157
158 <h3 id="the-client">The Client</h3>
159 <p>I automated the browser to request the same page 20 times in a row, waiting 3 seconds after page load to begin the next request. The internet connection is rated at 200mbps. No other applications were running on the computer at the time of data capture.</p>
160
161 <h2 id="so-how-fast-is-http3">So How Fast Is HTTP/3?</h2>
162 <h3 id="new-york-usa">New York, USA</h3>
163 <p>Here’s the response times of HTTP/2 vs. HTTP/3 when requesting the three different sites from the NY datacenter:</p>
164
165 <figure class="wide">
166 <div class="wide-wrap">
167 <img src="https://requestmetrics.com/assets/images/webperf/http3/ny-http2and3.png" width="749" loading="lazy" height="353" alt="Comparing HTTP/2 and HTTP/3 protocol versions when loading pages from NY" />
168 </div>
169 </figure>
170
171 <p>HTTP/3 is:</p>
172 <ul>
173 <li><strong>200ms</strong> faster for the Small Site</li>
174 <li><strong>325ms</strong> faster for the Content Site</li>
175 <li><strong>300ms</strong> faster for the Single Page Application</li>
176 </ul>
177
178 <p>The distance from Minnesota to New York is 1,000 miles, which is pretty small by networking standards. It’s significant that even at a relatively short distance HTTP/3 was able to improve performance this much.</p>
179
180 <h3 id="london-england">London, England</h3>
181 <p>I’ve included the HTTP/1.1 benchmarking run for London in the results as well. In order to show just how much faster HTTP/2 and HTTP/3 are, I’ve kept the graphs to the same scale. You can see that for the Content Site, the timings are so slow that they don’t even fit entirely on the graph!</p>
182
183 <figure class="wide">
184 <div class="wide-wrap">
185 <img src="https://requestmetrics.com/assets/images/webperf/http3/london-all-protocols.png" width="1144" loading="lazy" height="353" alt="Comparing the three HTTP protocol versions when loading pages from London" />
186 </div>
187 </figure>
188
189 <p>As you can see, the speed increase is even more pronounced when greater distances over the network are in play. HTTP/3 is:</p>
190 <ul>
191 <li><strong>600ms</strong> faster for the Small Site (<strong>3x</strong> the speedup compared with New York)</li>
192 <li><strong>1200ms</strong> faster for the Content Site (over <strong>3.5x</strong> the speedup compared with New York)</li>
193 <li><strong>1000ms</strong> faster for the Single Page Application (over <strong>3x</strong> the speedup compared with New York)</li>
194 </ul>
195
196 <h3 id="bangalore-india">Bangalore, India</h3>
197 <p>The performance improvement with HTTP/3 is extremely pronounced when loading pages from the server in India. I didn’t even run an HTTP/1.1 test because it was so slow. Here are the results of HTTP/2 vs. HTTP/3:</p>
198
199 <figure class="wide">
200 <div class="wide-wrap">
201 <img src="https://requestmetrics.com/assets/images/webperf/http3/india-http2and3.png" width="749" loading="lazy" height="353" alt="Comparing the three HTTP protocol versions when loading pages from India" />
202 </div>
203 </figure>
204
205 <p>HTTP/3 continues to pull ahead when larger geographies and more network hops are involved. What’s perhaps more striking is just how tightly grouped the response times are for HTTP/3. QUIC is having a big impact when packets are traveling thousands of miles.</p>
206
207 <p>In every case HTTP/3 was faster than its predecessor!</p>
208
209 <h3 id="why-is-http3-so-much-faster">Why is HTTP/3 so Much Faster?</h3>
210
211 <h4 id="real-multiplexing">Real Multiplexing</h4>
212 <p>The true multiplexed nature of HTTP/3 means that there is no Head-of-line blocking happening anywhere on the stack. When requesting resources from further away, geographically, there is a much higher chance of packet loss and the need for TCP to re-transmit those packets.</p>
213
214 <h4 id="0-rtt-is-a-game-changer">0-RTT Is a Game Changer</h4>
215 <p>Additionally, HTTP/3 supports <a href="https://www.rfc-editor.org/rfc/rfc9001.html#section-4.6-1">O-RTT</a> QUIC connections, which lowers the number of round trips required to establish a secure TLS connection with the server.</p>
216
217 <blockquote>
218 <p>The 0-RTT feature in QUIC allows a client to send application data before the handshake is complete. This is made possible by reusing negotiated parameters from a previous connection. To enable this, 0-RTT depends on the client remembering critical parameters and providing the server with a TLS session ticket that allows the server to recover the same information.</p>
219 </blockquote>
220
221 <p>However, 0-RTT should not be blindly enabled. There are some <a href="https://www.rfc-editor.org/rfc/rfc8446#section-2.3">possible</a> <a href="https://www.rfc-editor.org/rfc/rfc9001.html#name-replay-attacks-with-0-rtt">security concerns</a> depending on your threat model.</p>
222
223 <blockquote>
224 <p>The security properties for 0-RTT data are weaker than those for other kinds of TLS data. Specifically:</p>
225 <ol>
226 <li>This data is not forward secret, as it is encrypted solely under keys derived using the offered PSK.</li>
227 <li>There are no guarantees of non-replay between connections.</li>
228 </ol>
229 </blockquote>
230
231 <h2 id="can-i-use-http3-today">Can I Use HTTP/3 Today?</h2>
232 <p>Maybe! While the protocol is currently in <em>Internet-Draft</em> status, there are plenty of existing <a href="https://en.wikipedia.org/wiki/HTTP/3#Server">implementations</a>.</p>
233
234 <p>I specifically chose <strong>Caddy</strong> for these benchmarks because HTTP/3 can be enabled with a <a href="https://caddyserver.com/docs/caddyfile/options#protocol">simple config value</a> in the <code class="language-plaintext highlighter-rouge">Caddyfile</code></p>
235
236 <p>NGINX also has experimental support and is <a href="https://www.nginx.com/blog/our-roadmap-quic-http-3-support-nginx/">working towards an official HTTP/3</a> release in the near future.</p>
237
238 <p>The big tech players like Google and Facebook are serving their traffic over HTTP/3 already. <a href="https://google.com">Google.com</a> is entirely served over HTTP/3 for modern browsers.</p>
239
240 <p>For those folks stuck in the Windows ecosystem, supposedly Windows Server 2022 will support HTTP/3, with some rather <a href="https://techcommunity.microsoft.com/t5/networking-blog/enabling-http-3-support-on-windows-server-2022/ba-p/2676880">esoteric steps required</a> to enable it.</p>
241
242 <h2 id="conclusion">Conclusion</h2>
243 <p>HTTP/3 can make a big difference in how users experience your site. In general, the more resources your site requires, the bigger the performance improvement you’ll see with HTTP/3 and QUIC. As the standard continues to inch closer to finalization, it may be time to start looking at enabling it for your sites.</p>
244
245
246 ]]></content:encoded>
247 <pubDate>Mon, 29 Nov 2021 11:00:00 +0000</pubDate>
248 <author>hello@requestmetrics.com (Request Metrics)</author>
249 </item>
250
251
252 <item>
253 <title>Using HTTP Caching: 2021 Guide</title>
254 <link>https://requestmetrics.com/web-performance/http-caching</link>
255 <guid isPermaLink="true">https://requestmetrics.com/web-performance/http-caching</guid>
256 <description>The fastest website is the website that is already loaded, and that’s exactly what we can do with HTTP caching. HTTP caching lets web browsers reuse of previously loaded resources, like pages, images, JavaScript, and CSS. It’s a powerful tool to improve your web performance, but misconfiguration can cause big performance problems. Here’s what you need to know to use HTTP caching without reading hundreds of pages of HTTP Caching Spec.
257
258 </description>
259 <media:content url="https://requestmetrics.com/assets/images/webperf/http-caching/http-caching-2000.png" medium="image" type="image/png" height="350" width="700" />
260 <enclosure url="https://requestmetrics.com/assets/images/webperf/http-caching/http-caching-2000.png" type="image/png" />
261 <content:encoded><![CDATA[
262 <div><img src="https://requestmetrics.com/assets/images/webperf/http-caching/http-caching-2000.png" alt="Using HTTP Caching: 2021 Guide" class="webfeedsFeaturedVisual" /></div>
263 <p>The fastest website is the website that is already loaded, and that’s exactly what we can do with HTTP caching. HTTP caching lets web browsers reuse of previously loaded resources, like pages, images, JavaScript, and CSS. It’s a powerful tool to improve your web performance, but misconfiguration can cause <a href="/web-performance/how-hackernews-crushed-davidwalshblog">big performance problems</a>. Here’s what you need to know to use HTTP caching without reading hundreds of pages of <a href="https://datatracker.ietf.org/doc/html/rfc7234">HTTP Caching Spec</a>.</p>
264
265 <!--more-->
266
267 <p>HTTP caching is controlled by headers returned as part of the server response. The most important of these is the <code class="language-plaintext highlighter-rouge">Cache-Control</code> header, which informs the browser how and when a resource may be cached. The <code class="language-plaintext highlighter-rouge">Cache-Control</code> header has many, many options that control caching behavior. But to avoid writing a novel, we’ll focus on the basics of controlling cache, and give you some recipes for common scenarios.</p>
268
269 <h2 id="how-to-use-the-browser-cache">How to use the Browser Cache</h2>
270 <p>The browser calculates “Cache Freshness” using headers in the HTTP response. Cache freshness is how long a cached asset is valid since it was downloaded. Freshness is calculated depending on which headers are returned.</p>
271
272 <h3 id="the-cache-control-header">The <code class="language-plaintext highlighter-rouge">Cache-Control</code> Header</h3>
273 <p>The <code class="language-plaintext highlighter-rouge">Cache-Control</code> header has a number of directives to control caching behavior, but the most common is <code class="language-plaintext highlighter-rouge">max-age</code>. Max-age specifies how many seconds after download the cached resource is valid. Here’s an example:</p>
274
275 <figure class="code oneliner" id="code-79">
276 <div class="code-wrap">
277 <pre class="prettyprint lang-bsh">
278 # Cache this response for 10 minutes (600 seconds).
279 Cache-Control: max-age=600</pre>
280 <!-- <button type="button" class="btn copy-button yes-js">
281 <img src="/assets/images/copy.svg" alt="Copy" />
282 <span class="label">Copy</span>
283 </button> -->
284
285 </div>
286 </figure>
287
288 <h3 id="the-expires-header">The <code class="language-plaintext highlighter-rouge">Expires</code> Header</h3>
289 <p>The <code class="language-plaintext highlighter-rouge">Expires</code> header contains a date and time at which the cached resource should be marked stale, but only if you didn’t already use the <code class="language-plaintext highlighter-rouge">max-age</code> <code class="language-plaintext highlighter-rouge">Cache-Control</code> option. <code class="language-plaintext highlighter-rouge">Expires</code> is used to determine freshness if the response also contains a <code class="language-plaintext highlighter-rouge">Date</code> header for when the response was sent. Freshness is simply subtracting <code class="language-plaintext highlighter-rouge">Date</code> from the <code class="language-plaintext highlighter-rouge">Expires</code> time.</p>
290
291 <figure class="code oneliner" id="code-147">
292 <div class="code-wrap">
293 <pre class="prettyprint lang-bsh">
294 # This response can be cached for 1 hour (Expires - Date == freshness).
295 Expires: Tue, 09 Nov 2021 21:09:28 GMT
296 Date: Tue, 09 Nov 2021 20:09:28 GMT</pre>
297 <!-- <button type="button" class="btn copy-button yes-js">
298 <img src="/assets/images/copy.svg" alt="Copy" />
299 <span class="label">Copy</span>
300 </button> -->
301
302 </div>
303 </figure>
304
305 <h2 id="the-browsers-automatic-caching">The Browser’s Automatic Caching</h2>
306 <p>Even if you don’t use the <code class="language-plaintext highlighter-rouge">Cache-Control</code> or <code class="language-plaintext highlighter-rouge">Expires</code> header, most web browsers will cache resources automatically and <em>guess</em> how long they will remain fresh. This guessing is referred to as <strong>“heuristic freshness”</strong>. Usually, the guess is based on the <code class="language-plaintext highlighter-rouge">Last-Modified</code> header included automatically by most web servers. But each browser implements this differently, so it’s dangerous to rely on it for your caching.</p>
307
308 <p>One method that browser’s use is to assume a resource is “fresh” for 10% of the time since the resource was last modified.</p>
309
310 <figure class="code oneliner" id="code-179">
311 <div class="code-wrap">
312 <pre class="prettyprint lang-bsh">
313 # Freshness = 2 hours (20 hours since last modified)
314 # (Date - Last-Modified) * 10% == freshness
315 Last-Modified: Tue, 09 Nov 2021 02:00:00 GMT
316 Date: Tue, 09 Nov 2021 22:00:00 GMT</pre>
317 <!-- <button type="button" class="btn copy-button yes-js">
318 <img src="/assets/images/copy.svg" alt="Copy" />
319 <span class="label">Copy</span>
320 </button> -->
321
322 </div>
323 </figure>
324
325 <!-- class="wide">
326 <div class="wrap callout left flex">
327 <div class="picture">
328 <img loading="lazy" class="lazyload" src="https://requestmetrics.com/assets/images/illustrations/sloth_laptop_500.png" srcset="https://requestmetrics.com/assets/images/illustrations/sloth_laptop_500.png 500w,
329 https://requestmetrics.com/assets/images/illustrations/sloth_laptop_1000.png 1000w" sizes="(max-width: 900px) 100vw, 400px" alt="Sloth Laptop" width="600" height="450" />
330 </div>
331 <div class="blurb">
332 <h2>Check Your Caching Headers!</h2>
333 <p>
334 Check how your caching is configured right now! We made a neat tool that checks your HTTP cache settings.
335 </p>
336 <div class="flex cta-buttons">
337 <a class="btn btn-big btn-grey" href="/tools/http-cache-checker">
338 Test My Cache
339 </a>
340 </div>
341 </div>
342 </div>
343 -->
344
345 <h2 id="handling-expired-resources">Handling Expired Resources</h2>
346
347 <p>What happens when a resource “expires”? This is referred to as a <strong>“stale resource”</strong>, and the browser must re-validate the resource from the server. In some cases, the browser can validate the resource without downloading it again. Otherwise, the browser re-downloads the entire resource and caches the new version.</p>
348
349 <p>There are a couple ways this validation can happen, depending on which <em>HTTP Validation Headers</em> are sent with your resources.</p>
350
351 <h3 id="validating-with-the-etag-header">Validating With the <code class="language-plaintext highlighter-rouge">ETag</code> Header</h3>
352 <p>The <code class="language-plaintext highlighter-rouge">ETag</code> header allows the browser to tell the server what version it currently has. The header contains a string which uniquely identifies the content, usually a checksum of the file.</p>
353
354 <p>When a resource expires that had an ETag, the browser will send a validation request with a <code class="language-plaintext highlighter-rouge">If-None-Match</code> header containing the ETag value it already has. If the resource is unchanged, the server replies with an empty 304 (Not Modified) HTTP response. Otherwise, the server sends the resource like normal when the content has changed.</p>
355
356 <figure class="code " id="code-172">
357 <div class="code-wrap">
358 <pre class="prettyprint lang-bsh">
359 # In original resource response headers:
360 ETag: "123abc987654"
361
362 # Browser sends in the validation request headers:
363 If-None-Match: "123abc987654"
364 </pre>
365 <!-- <button type="button" class="btn copy-button yes-js">
366 <img src="/assets/images/copy.svg" alt="Copy" />
367 <span class="label">Copy</span>
368 </button> -->
369
370 <figcaption><a href="#code-172">Cache Validation Using ETag</a></figcaption>
371
372 </div>
373 </figure>
374
375 <h3 id="validating-with-the-modified-date-header">Validating With the <code class="language-plaintext highlighter-rouge">Modified-Date</code> Header</h3>
376 <p>When an ETag is unavailable, web servers may send a <code class="language-plaintext highlighter-rouge">Modified-Date</code> header, with the last modified date of the source file. Similar to ETags, the browser can send that date in a validation request with the <code class="language-plaintext highlighter-rouge">If-Modified-Since</code> header to tell the server which version it has.</p>
377
378 <p>The server returns an empty 304 (Not Modified) response if the content has not changed since the date specified.</p>
379
380 <figure class="code " id="code-224">
381 <div class="code-wrap">
382 <pre class="prettyprint lang-bsh">
383 # In original resource response headers:
384 Modified-Date: Tue, 09 Nov 2021 20:00:00 GMT
385
386 # Browser sends in the validation request headers:
387 If-Modified-Since: Tue, 09 Nov 2021 20:00:00 GMT
388 </pre>
389 <!-- <button type="button" class="btn copy-button yes-js">
390 <img src="/assets/images/copy.svg" alt="Copy" />
391 <span class="label">Copy</span>
392 </button> -->
393
394 <figcaption><a href="#code-224">Cache Validation Using Modified-Date</a></figcaption>
395
396 </div>
397 </figure>
398
399 <h3 id="no-validation">No Validation</h3>
400 <p>If the original resource had neither <code class="language-plaintext highlighter-rouge">ETag</code> or <code class="language-plaintext highlighter-rouge">Modified-Date</code> headers, then the browser simply requests the entire resource and uses the result.</p>
401
402 <h2 id="busting-the-browsers-cache">Busting the Browsers Cache</h2>
403 <p>When something changes, such as a new image, refreshed session, or an updated release of your code, you’ll want to invalidate (or bust!) the browser cache so that your users get the new stuff. If you’ve aggressively set caching headers, this can be challenging, but there are a couple ways to solve it.</p>
404
405 <h3 id="1-changing-the-url-to-the-resource">1. Changing the URL to the Resource</h3>
406
407 <p>The most common cache busting strategy is just to change the name of your resources when they change. This could be something like including a hash, version, or date in the filename when you build your site.</p>
408
409 <figure class="code " id="code-58">
410 <div class="code-wrap">
411 <pre class="prettyprint lang-bsh">scripts.e7686eaf.min.js</pre>
412 <!-- <button type="button" class="btn copy-button yes-js">
413 <img src="/assets/images/copy.svg" alt="Copy" />
414 <span class="label">Copy</span>
415 </button> -->
416
417 <figcaption><a href="#code-58">Example filename ready to be busted</a></figcaption>
418
419 </div>
420 </figure>
421
422 <h3 id="2-adding-a-query-parameter">2. Adding a Query Parameter</h3>
423
424 <p>If you can’t change the name of your resources, you can add a querystring parameter with a changeable key, like a version or date. When you change your site, or a resource, updating the querystring to a new value will invalidate all browser caches.</p>
425
426 <figure class="code " id="code-62">
427 <div class="code-wrap">
428 <pre class="prettyprint lang-bsh">/my/images.png?v=2021119</pre>
429 <!-- <button type="button" class="btn copy-button yes-js">
430 <img src="/assets/images/copy.svg" alt="Copy" />
431 <span class="label">Copy</span>
432 </button> -->
433
434 <figcaption><a href="#code-62">Example querystring ready to be busted</a></figcaption>
435
436 </div>
437 </figure>
438
439 <p>If you have a look at the source of our page here, you’ll see what we use this strategy, adding a date representation of the build time to all our scripts and styles.</p>
440
441 <h3 id="3-using-the-vary-header">3. Using the <code class="language-plaintext highlighter-rouge">Vary</code> Header</h3>
442
443 <p>The <code class="language-plaintext highlighter-rouge">Vary</code> header is can be returned in resource responses and tells the browser when a resource should be cached as a unique variation of the resource. It does this by specifying one or more headers to use as a unique key.</p>
444
445 <p>The browser will never be able to use its cached responses if the header values change on every request. <code class="language-plaintext highlighter-rouge">Vary</code> is often omitted entirely, and should be used carefully when needed.</p>
446
447 <figure class="code " id="code-251">
448 <div class="code-wrap">
449 <pre class="prettyprint lang-bsh">
450 # Good: A common value that should not impact caching
451 # Caches gzip vs non-gzip responses separately
452 Vary: Accept-Encoding
453
454 # Bad: Probably not what you want.
455 # Any change to X-App-Version will invalidate your cache!
456 Vary: X-App-Version
457 </pre>
458 <!-- <button type="button" class="btn copy-button yes-js">
459 <img src="/assets/images/copy.svg" alt="Copy" />
460 <span class="label">Copy</span>
461 </button> -->
462
463 <figcaption><a href="#code-251">Vary Examples</a></figcaption>
464
465 </div>
466 </figure>
467
468 <h2 id="http-caching-recipes">HTTP Caching Recipes</h2>
469 <p>Different resources are cached differently. Here’s how to accomplish a few common caching scenarios.</p>
470
471 <h3 id="1-never-cache-anything">1. Never Cache Anything!</h3>
472 <p>Some resources are dynamic or time sensitive and should never be cached. This will force the browser to re-download resources each and every time the user loads the page. Force the browser to always makes a request:</p>
473
474 <figure class="code oneliner" id="code-23">
475 <div class="code-wrap">
476 <pre class="prettyprint lang-bsh">Cache-Control: no-store</pre>
477 <!-- <button type="button" class="btn copy-button yes-js">
478 <img src="/assets/images/copy.svg" alt="Copy" />
479 <span class="label">Copy</span>
480 </button> -->
481
482 </div>
483 </figure>
484
485 <h3 id="2-cache-but-always-revalidate">2. Cache, But Always Revalidate</h3>
486 <p>Some resources are cacheable, but change often enough that they should be re-validated before use. We can accomplish this with the confusingly named <code class="language-plaintext highlighter-rouge">no-cache</code> directive. The browser will request an updated version of the resource, but will accept a 304 (Not Modified) response to save download bandwidth.</p>
487
488 <figure class="code oneliner" id="code-97">
489 <div class="code-wrap">
490 <pre class="prettyprint lang-bsh">
491 Cache-Control: no-cache
492
493 # no-cache is equivalent to:
494 Cache-Control: max-age=0, must-revalidate
495 </pre>
496 <!-- <button type="button" class="btn copy-button yes-js">
497 <img src="/assets/images/copy.svg" alt="Copy" />
498 <span class="label">Copy</span>
499 </button> -->
500
501 </div>
502 </figure>
503
504 <h3 id="3-cache-for-a-day">3. Cache For A Day</h3>
505 <p>Some resources change, but do so slowly. Setting a “just right” <code class="language-plaintext highlighter-rouge">max-age</code> on these allows them to be cached but updated in a timely manner when changed. Don’t depend on <code class="language-plaintext highlighter-rouge">max-age</code> alone if it’s critical that the browser immediately uses a new version, use a Cache-Buster!</p>
506
507 <figure class="code oneliner" id="code-28">
508 <div class="code-wrap">
509 <pre class="prettyprint lang-bsh">Cache-Control: max-age=86400</pre>
510 <!-- <button type="button" class="btn copy-button yes-js">
511 <img src="/assets/images/copy.svg" alt="Copy" />
512 <span class="label">Copy</span>
513 </button> -->
514
515 </div>
516 </figure>
517
518 <h3 id="4-cache-forever">4. Cache “Forever”</h3>
519 <p>You probably don’t want to do this unless you are using a cache-busting strategy. There isn’t actually a “forever” cache directive, but you can get close enough by specifying a very large <code class="language-plaintext highlighter-rouge">max-age</code>.</p>
520
521 <figure class="code oneliner" id="code-65">
522 <div class="code-wrap">
523 <pre class="prettyprint lang-bsh">
524 # Cache this resource for a year
525 Cache-Control: max-age=31536000</pre>
526 <!-- <button type="button" class="btn copy-button yes-js">
527 <img src="/assets/images/copy.svg" alt="Copy" />
528 <span class="label">Copy</span>
529 </button> -->
530
531 </div>
532 </figure>
533
534 <hr />
535
536 <h2 id="conclusion">Conclusion</h2>
537 <p>That’s it! You can use these headers and recipes to greatly accelerate your website and save a ton of redundant download bandwidth. Proper caching can improve the way customers perceive your site’s performance. But don’t take our word for it, you should be monitoring your website performance with <a href="https://requestmetrics.com">Request Metrics</a> to check and improve your website performance.</p>
538
539 ]]></content:encoded>
540 <pubDate>Fri, 19 Nov 2021 08:00:00 +0000</pubDate>
541 <author>hello@requestmetrics.com (Request Metrics)</author>
542 </item>
543
544
545 <item>
546 <title>Synthetic Testing and Real User Monitoring</title>
547 <link>https://requestmetrics.com/web-performance/synthetic-testing-and-real-user-monitoring</link>
548 <guid isPermaLink="true">https://requestmetrics.com/web-performance/synthetic-testing-and-real-user-monitoring</guid>
549 <description>
550 Synthetic Testing and Real User Monitoring are the most important tools in your performance toolbox. But they do different things and are useful at different times and many developers only spend time mastering one of these tools and only see a part of their performance problems, like trying to hammer in a screw.
551
552 </description>
553 <media:content url="https://requestmetrics.com/assets/images/webperf/synthetic-testing-and-real-user-monitoring/synthetic-testing-and-real-user-monitoring-2000.png" medium="image" type="image/png" height="350" width="700" />
554 <enclosure url="https://requestmetrics.com/assets/images/webperf/synthetic-testing-and-real-user-monitoring/synthetic-testing-and-real-user-monitoring-2000.png" type="image/png" />
555 <content:encoded><![CDATA[
556 <div><img src="https://requestmetrics.com/assets/images/webperf/synthetic-testing-and-real-user-monitoring/synthetic-testing-and-real-user-monitoring-2000.png" alt="Synthetic Testing and Real User Monitoring" class="webfeedsFeaturedVisual" /></div>
557
558 <p>Synthetic Testing and Real User Monitoring are the most important tools in your performance toolbox. But they do different things and are useful at different times and many developers only spend time mastering one of these tools and only see a part of their performance problems, like trying to hammer in a screw.</p>
559
560 <!--more-->
561
562 <p>Let’s look at these tools, what they measure, and when to use them.</p>
563
564 <h2 id="synthetic-testing">Synthetic Testing</h2>
565 <p><em>Synthetic Testing</em> measures the performance of a website under a controlled environment. Examples of this are Lighthouse audits from Chrome Devtools or Pagespeed Insights. The test simulates the location, latency, bandwidth, browser, and device in order to approximate the experience of a visitor to your website.</p>
566
567 <p>For a Synthetic Test to be accurate and valuable, you need to know things about your likely visitors: where they are, what kind of network they are on, and what device they are using. Then the test needs to accurately simulate these characteristics. Both of these things are difficult.</p>
568
569 <p>The internet is a big and diverse place, and developers don’t always know enough about our users. We can make guesses, but because we often run on fast networks with new laptops, we often overestimate the capability of our users because. <em>It’s fast on my machine.</em></p>
570
571 <figure class="">
572 <img src="https://requestmetrics.com/assets/images/webperf/synthetic-testing-and-real-user-monitoring/laptop_1000_apng.png" style="max-width: 400px" loading="lazy" class="lazyload" alt="Sloth on fast laptop" width="1000" height="1000" />
573 </figure>
574
575 <p>Plus, you likely have <em>more than one kind of user</em> that should be tested. Some of your users will visit from laptops at work. Others will try and login on a phone from the train while commuting, or on their tablet with flaky wi-fi from the coffee shop. Each user will have a different perspective on performance, and would need to be simulated with a different test.</p>
576
577 <p>The biggest benefit of a this kind of tool is that you can <a href="https://developers.google.com/speed/pagespeed/insights/">run a Synthetic Test on your website right now</a>, regardless of whether you have any users. And the results will probably tell you about your biggest performance problems.</p>
578
579 <p>The test will be flawed, and that’s okay because it will give you an idea of performance. Synthetic Testing will never tell you how fast your website really is—only how fast it <em>might</em> be right now.</p>
580
581 <h2 id="real-user-monitoring">Real User Monitoring</h2>
582 <p>Real User Monitoring is just that: <strong>real</strong>. Real User Monitoring (or RUM) records the <em>actual</em> performance from users that visited your website. RUM doesn’t guess or simulate a user, it just records the actual performance they experienced.</p>
583
584 <p>Real User Monitoring is more accurate than Synthetic Testing, but there is also more noise and more delay.</p>
585
586 <p>RUM data will inherently include data from <em>all users</em>, even that guy using a GameBoy to browse your website from Mongolia. You’ll have to apply <em>statistics</em> to the data to understand what it really means—things like medians, percentiles, and distributions. Used correctly, RUM data tells you how your fastest users, typical users, and worst users experience your website.</p>
587
588 <!-- class="wide">
589 <div class="wrap callout left flex">
590 <div class="picture" style="border: 1px solid #DDE4EB; border-radius: 6px;">
591 <img src="https://requestmetrics.com/assets/images/webperf/synthetic-testing-and-real-user-monitoring/rum-distribution-400.png" srcset="https://requestmetrics.com/assets/images/webperf/synthetic-testing-and-real-user-monitoring/rum-distribution-400.png 400w,
592 https://requestmetrics.com/assets/images/webperf/synthetic-testing-and-real-user-monitoring/rum-distribution-800.png 800w,
593 https://requestmetrics.com/assets/images/webperf/synthetic-testing-and-real-user-monitoring/rum-distribution-1600.png 1600w" sizes="(max-width: 900px) 100vw, 400px" loading="lazy" class="lazyload" alt="Request Metrics Performance Distribution" width="1600" height="800" />
594 </div>
595 <div class="blurb">
596 <p>
597 RUM tools like Request Metrics do the statistics for you! This distribution of the performance for our homepage, shows the load time of most users, 75% of users, and the slowest users. You can check out our live data and explore this chart in our interactive demo.
598 </p>
599 <div class="flex cta-buttons">
600 <a class="btn btn-big btn-grey" href="https://app.requestmetrics.com/demo">
601 Live Demo
602 </a>
603 </div>
604 </div>
605 </div>
606 -->
607
608 <p>The biggest limitation of RUM is the delay. RUM can’t tell you how fast your site will be until users start visiting it. You’ll have to release that change and measure the impact to see if your site sped up–or not. Synthetic Testing can make some guesses at the performance early, which help find obvious problems, but to really prove your site is fast, you have to use RUM.</p>
609
610 <p>Some folks at Google even looked at this, <a href="https://philipwalton.com/articles/my-challenge-to-the-web-performance-community/">comparing websites Synthetic performance with RUM</a>. Almost half of sites with perfect Synthetic Tests failed the minimum requirements for Core Web Vital scores! Half! Half of people bragging about their perfect Lighthouse score are being <a href="https://requestmetrics.com/web-performance/web-vitals">penalized by Google for poor performance</a>.</p>
611
612 <h2 id="signal-vs-noise">Signal vs Noise</h2>
613 <p>Synthetic Testing and Real User Monitoring is about <em>Signal vs Noise</em>. Synthetic Tests don’t have much noise—each Lighthouse test you run is a valid measurement of performance for those conditions. Run the test again with the same conditions and there will be very similar results.</p>
614
615 <p>But as the Google research showed, there is not a lot of signal in those synthetic results either. That Lighthouse report isn’t how any user will experience your page (unless they are browsing your website from your laptop on your network).</p>
616
617 <p>Real User Monitoring is the opposite. Each bit of data you get from RUM is how your website really performed for a visitor. But those visitors can be wildly different. Some will have an awesome experience on your website. Others will think they are still on AOL (read: old really slow internet).</p>
618
619 <p>The trick is, which users do you care about? If you are building a site for corporate users in the United States, then it doesn’t matter what the performance is for mobile users in Ukraine. RUM tools like Request Metrics help you filter out noise and aggregate the data to give you a clearer picture of your target user.</p>
620
621 <hr />
622
623 <p>Both Synthetic Testing and Real User Monitoring are valuable tools for any developer that wants to build fast websites. Use Synthetic Testing, like Lighthouse, to test your changes before release. It will help you catch obvious mistakes.</p>
624
625 <p>And use <a href="https://requestmetrics.com">Real User Monitoring tools like Request Metrics</a> to see if that change <em>really</em> sped things up. You don’t know how fast your website is until your visitors tell you.</p>
626
627 ]]></content:encoded>
628 <pubDate>Wed, 10 Nov 2021 09:00:00 +0000</pubDate>
629 <author>hello@requestmetrics.com (Request Metrics)</author>
630 </item>
631
632
633 <item>
634 <title>Advertising's Performance Tradeoffs</title>
635 <link>https://requestmetrics.com/web-performance/advertising-performance-tradeoffs</link>
636 <guid isPermaLink="true">https://requestmetrics.com/web-performance/advertising-performance-tradeoffs</guid>
637 <description>Advertising is everywhere on the web and users have noticed. More than 40% of internet users block ads. Are these users sticking it to the man or just tired of slow site performance? To find out, we measure advertising’s performance impact on a few popular sites.
638
639 </description>
640 <media:content url="https://requestmetrics.com/assets/images/webperf/perf-ads/advertising-performance-tradeoffs-2000.png" medium="image" type="image/png" height="350" width="700" />
641 <enclosure url="https://requestmetrics.com/assets/images/webperf/perf-ads/advertising-performance-tradeoffs-2000.png" type="image/png" />
642 <content:encoded><![CDATA[
643 <div><img src="https://requestmetrics.com/assets/images/webperf/perf-ads/advertising-performance-tradeoffs-2000.png" alt="Advertising's Performance Tradeoffs" class="webfeedsFeaturedVisual" /></div>
644 <p>Advertising is everywhere on the web and users have noticed. More than <a href="https://backlinko.com/ad-blockers-users">40% of internet users block ads</a>. Are these users sticking it to the man or just tired of slow site performance? To find out, we measure advertising’s performance impact on a few popular sites.</p>
645
646 <!--more-->
647
648 <h2 id="getting-real-measurements">Getting Real Measurements</h2>
649 <p>We picked <a href="https://www.yahoo.com/">Yahoo</a>, <a href="https://www.reddit.com/">Reddit</a>, <a href="https://www.bbc.com/">BBC</a>, <a href="https://www.cnn.com/">CNN</a>, and <a href="https://www.nytimes.com/">The New York Times</a> because they have ads and are popular according to <a href="https://www.alexa.com/topsites">Alexa Top Sites</a>. Measurements were captured out of Chrome after loading each site in a fresh incognito window. Closing Chrome between runs to ensures there are no cached assets. We then reran the tests with <a href="https://ublockorigin.com/">uBlock Origin</a> enabled.</p>
650
651 <h2 id="what-users-want">What Users Want</h2>
652 <p>Users expect pages to show something quickly, finish loading fast and not to change under them once loaded.</p>
653
654 <p>The user’s perception of page performance is influenced by many aspects of the page load, and no single metric can capture all of the performance experience. Because of this, we gathered Load Event timings along with core web vital metrics to get a better picture of each site’s performance and how it is impacted by advertisements.</p>
655
656 <h3 id="quick-main-content-paints">Quick Main Content Paints</h3>
657 <p>The more quickly a site can get main content pieces displayed to the user, the more snappy the site will feel. The <a href="https://requestmetrics.com/web-performance/first-contentful-paint-fcp">First Contentful Paint (FCP)</a> and <a href="https://requestmetrics.com/web-performance/largest-contentful-paint">Largest Contentful Paint (LCP)</a> Core Web Vitals are a good measurements for this.</p>
658
659 <p>Surprisingly, ads did not notably impact these first paints! To top it off, most sites fall into the “Good” range for these metrics. Clearly, a lot of effort is devoted to minimizing the time to render. Much of this is accomplished through deferring advertising loads till later in the life of the page, as we’ll see later.</p>
660
661 <figure class="border">
662 <img src="https://requestmetrics.com/assets/images/webperf/perf-ads/fcp-chart.png" loading="lazy" class="lazyload" alt="FCP is hardly impacted by ads" width="624" height="278" />
663 <figcaption>FCP is hardly impacted by ads</figcaption>
664 </figure>
665
666 <figure class="border">
667 <img src="https://requestmetrics.com/assets/images/webperf/perf-ads/lcp-chart.png" loading="lazy" class="lazyload" alt="LCP doesn't care about ads either" width="624" height="278" />
668 <figcaption>LCP doesn't care about ads either</figcaption>
669 </figure>
670
671 <h3 id="fast-page-loads">Fast Page Loads</h3>
672 <p>Pages with fast first paints still feel slow if the last piece of content takes a long time to load. Timing how long the page takes to fire the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event">load event</a> can tell us if this is happening.</p>
673
674 <p>Less surprisingly, loading the entire page does take longer when ads are being shown. Some sites were worse than others, but all showed a negative performance impact from ads.</p>
675
676 <figure class="border">
677 <img src="https://requestmetrics.com/assets/images/webperf/perf-ads/load-chart.png" loading="lazy" class="lazyload" alt="Load times are heavily impacted by Advertisements" width="624" height="278" />
678 <figcaption>Load times are heavily impacted by Advertisements </figcaption>
679 </figure>
680
681 <h3 id="no-jank">No Jank</h3>
682 <p>Fast loading pages can still feel slow to a user if content is asynchronously rendered after the load is complete. Layout shifts, often referred to as “jank”, are a common side effect of asynchronous loads.</p>
683
684 <figure>
685 <video controls="" muted="" preload="metadata">
686 <source src="/assets/images/webperf/perf-ads/bbc-jank.mp4" type="video/mp4" />
687 </video>
688 <figcaption>The BBC demonstrating some egregious layout shift.</figcaption>
689 </figure>
690
691 <p>All tested sites asynchronously loaded advertisements. This has the major advantage of keeping page loads and initial paints quick but comes at the expense of more jank. This is clearly reflected in <a href="https://requestmetrics.com/web-performance/cumulative-layout-shift">Cumulative Layout Shift (CLS)</a> measurements.</p>
692
693 <figure class="border">
694 <img src="https://requestmetrics.com/assets/images/webperf/perf-ads/cls-chart.png" loading="lazy" class="lazyload" alt="Cumulative Layout Shift shows the advert jank" width="624" height="278" />
695 <figcaption>Cumulative Layout Shift shows the advert jank</figcaption>
696 </figure>
697
698 <h2 id="no-metric-tells-the-whole-story">No Metric Tells the Whole Story</h2>
699 <p>Advertisements don’t impact all aspects of page performance equally. This emphasizes the importance of a holistic understanding of performance metrics and the tradeoffs needed to improve a given metric.</p>
700
701 <h2 id="performance-is-a-tradeoff">Performance Is a Tradeoff</h2>
702 <p>While initial content renders were not notably impacted by ads, total page load and layout shifts were negatively effected by them. The jank alone probably drives a large number of internet users to the cozy arms of ad blockers.</p>
703
704 <p>Many sites depend on the revenue from ads for their very survival. And yet, the tradeoff between first impression speed and jank is made by almost all sites containing ads. Have they made the right choice? Many users appear to think they have not.</p>
705
706 ]]></content:encoded>
707 <pubDate>Tue, 28 Sep 2021 00:00:00 +0000</pubDate>
708 <author>hello@requestmetrics.com (Request Metrics)</author>
709 </item>
710
711
712 <item>
713 <title>High Performance Images: 2021 Guide</title>
714 <link>https://requestmetrics.com/web-performance/high-performance-images</link>
715 <guid isPermaLink="true">https://requestmetrics.com/web-performance/high-performance-images</guid>
716 <description>
717 Images engage users, drive clicks, and generally make everything better–except performance. Images are giant blobs of bytes that are usually the slowest part of your website. This 2021 guide has everything you need to know for fast images on the web.
718
719
720
721 Images are big. Really big. The bytes required for an image dwarf most site’s CSS and JavaScript assets. Slow images will damage your Core Web Vitals, impacting your SEO and costing you traffic. Images are usually the element driving Largest ...</description>
722 <media:content url="https://requestmetrics.com/assets/images/webperf/high-performance-images/high-performance-images-2000.png" medium="image" type="image/png" height="350" width="700" />
723 <enclosure url="https://requestmetrics.com/assets/images/webperf/high-performance-images/high-performance-images-2000.png" type="image/png" />
724 <content:encoded><![CDATA[
725 <div><img src="https://requestmetrics.com/assets/images/webperf/high-performance-images/high-performance-images-2000.png" alt="High Performance Images: 2021 Guide" class="webfeedsFeaturedVisual" /></div>
726
727 <p>Images engage users, drive clicks, and generally make everything better–<em>except performance</em>. Images are giant blobs of bytes that are usually the slowest part of your website. This 2021 guide has everything you need to know for fast images on the web.</p>
728
729 <!-- more -->
730
731 <p>Images are big. Really big. The bytes required for an image dwarf most site’s CSS and JavaScript assets. Slow images will <strong>damage your Core Web Vitals</strong>, impacting your SEO and costing you traffic. Images are usually the element driving <a href="https://requestmetrics.com/web-performance/largest-contentful-paint">Largest Contentful Paint (LCP)</a> and load delays can increase your <a href="https://requestmetrics.com/web-performance/cumulative-layout-shift">Cumulative Layout Shift (CLS)</a>. If you’re not familiar with these metrics, check them out in the <strong><a href="https://requestmetrics.com/web-performance/measure-web-performance">Definitive Guide to Measuring Web Performance</a></strong>.</p>
732
733 <figure class="border">
734 <a href="https://requestmetrics.com/web-performance/largest-contentful-paint">
735 <img src="https://requestmetrics.com/assets/images/metrics/lcp_range_400.png" loading="lazy" class="lazyload" style="display:inline;" alt="Largest Contentful Paint" width="200" height="200" />
736 </a>
737 <a href="https://requestmetrics.com/web-performance/cumulative-layout-shift">
738 <img src="https://requestmetrics.com/assets/images/metrics/cls_range_400.png" loading="lazy" class="lazyload" style="display:inline;" alt="Cumulative Layout Shift" width="200" height="200" />
739 </a>
740 <figcaption>LCP and CLS metric ranges</figcaption>
741 </figure>
742
743 <p>This guide covers optimizing your <em>image format</em>, <em>resolution</em>, <em>quality</em>, as well as <em>embedded images</em> and <em>lazy-loading</em>. Let’s get started!</p>
744
745 <hr />
746
747 <h2 id="1-image-format">1. Image Format</h2>
748
749 <p>First and foremost, your images need to be in the correct format. Image formats are designed for a particular <em>kind</em> of image, so using the wrong format can make a big image even worse.</p>
750
751 <p>A good general rule is to <strong>use jpg for photographs</strong> and <strong>use pngs for graphics</strong>. Here’s a quick example:</p>
752
753 <figure class="border">
754 <img src="https://requestmetrics.com/assets/images/webperf/high-performance-images/sloth_photograph_200.jpg" loading="lazy" class="lazyload" alt="sloth photograph" width="200" height="200" style="display:inline;" />
755 <img src="https://requestmetrics.com/assets/images/webperf/high-performance-images/sloth_graphic_200.png" loading="lazy" class="lazyload" alt="sloth graphic" width="200" height="200" style="display:inline;" />
756 <figcaption>Sloth Photograph and Graphic</figcaption>
757 </figure>
758
759 <p>On the left is a photograph of our buddy Sam, the sloth. As a JPG, the file is only <strong>32.7 kilobytes</strong>. Convert the same file to a PNG, and it more than doubles to <strong>90.6 kilobytes</strong>!</p>
760
761 <p>The right is an illustration of Sam, and is better served as a PNG. It’s only <strong>5.5 kilobytes</strong>. But converting it to a JPG balloons it to <strong>11.3 kilobytes</strong>.</p>
762
763 <p>Note that graphic illustrations tend to be significantly smaller than photographs. Be sure to consider this when designing the look and feel of your pages.</p>
764
765 <p>There’s <a href="https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types">lots of other formats too</a>! If you have artwork as vectors (lines and paths), SVG is a perfect format. Newer browsers support newer formats as well, like AVIF and WebP, which might be even smaller.</p>
766
767 <h2 id="2-responsive-image-resolution">2. Responsive Image Resolution</h2>
768
769 <p>Your website will not be viewed the same way by everyone. Some of your users will have a huge 1600px wide display. Others may have a 900px tablet or a 600px phone. A 1200px wide image would need a lot of wasteful bytes for those smaller devices, where the image will get scaled down anyway.</p>
770
771 <figure class="border">
772 <img src="https://requestmetrics.com/assets/images/webperf/high-performance-images/responsive_images_370.png" srcset="https://requestmetrics.com/assets/images/webperf/high-performance-images/responsive_images_370.png 370w,
773 https://requestmetrics.com/assets/images/webperf/high-performance-images/responsive_images_740.png 740w,
774 https://requestmetrics.com/assets/images/webperf/high-performance-images/responsive_images_1480.png 1480w" sizes="(max-width: 700px) 100vw, 700px" loading="lazy" class="lazyload" alt="Responsive Image Resolution" height="832" width="1480" />
775 <figcaption>Responsive Image Resolution</figcaption>
776 </figure>
777
778 <p>Why not scale down the images <em>before</em> your users download them? Use <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">HTML responsive attributes</a> to describe the sizes available for an image, and when to use them.</p>
779
780 <figure class="code " id="code-259">
781 <div class="code-wrap">
782 <pre class="prettyprint lang-html">
783 <img src="picture-1200.jpg"
784 srcset="picture-600.jpg 600w,
785 picture-900.jpg 900w,
786 picture-1200.jpg 1200w"
787 sizes="(max-width: 900px) 100vw, 1200px"
788 alt="my awesome picture" height="900" width="1200" />
789 </pre>
790 <!-- <button type="button" class="btn copy-button yes-js">
791 <img src="/assets/images/copy.svg" alt="Copy" />
792 <span class="label">Copy</span>
793 </button> -->
794
795 <figcaption><a href="#code-259">Using Responsive Image Markup</a></figcaption>
796
797 </div>
798 </figure>
799
800 <p>In this case, the base image is 1200px wide, and that’s also the default <code class="language-plaintext highlighter-rouge">src</code>. The <code class="language-plaintext highlighter-rouge">srcset</code> defines 3 images at 600, 900, and 1200px wide. The <code class="language-plaintext highlighter-rouge">sizes</code> uses CSS media queries to hint the browser on the viewable size available for the image. If the window is less than 900px wide, the frame will be fullwidth, 100vw. Otherwise, the frame will never be bigger than 1200px wide.</p>
801
802 <p>Most image tools, like Photoshop, <a href="https://www.gimp.org/">Gimp</a>, and <a href="https://www.getpaint.net/">Paint.NET</a>, can export images at multiple resolutions. Your native image viewer can probably do some limited resizing as well. To automate this on a large scale, you may want to consider a command line tool like <a href="https://imagemagick.org/index.php">ImageMagick</a>.</p>
803
804 <h3 id="hiding-images-on-mobile">Hiding Images on Mobile</h3>
805
806 <p>For some websites, you may not want to show an image on mobile devices at all because they are simply too big. Setting a <code class="language-plaintext highlighter-rouge">display:none</code> style on the image isn’t very helpful because the browser will still waste time and bytes downloading the image. Instead, you can use <code class="language-plaintext highlighter-rouge">sizes</code> to tell the browser when the image will not be shown.</p>
807
808 <figure class="code " id="code-269">
809 <div class="code-wrap">
810 <pre class="prettyprint lang-html">
811 <img src="picture-1200.jpg"
812 srcset="picture-600.jpg 600w,
813 picture-900.jpg 900w,
814 picture-1200.jpg 1200w"
815 sizes="(max-width: 600px) 0, 600px"
816 alt="my awesome picture" height="900" width="1200" />
817 </pre>
818 <!-- <button type="button" class="btn copy-button yes-js">
819 <img src="/assets/images/copy.svg" alt="Copy" />
820 <span class="label">Copy</span>
821 </button> -->
822
823 <figcaption><a href="#code-269">Hiding images on mobile and saving bandwidth</a></figcaption>
824
825 </div>
826 </figure>
827
828 <p>For screen sizes less than 600px, the frame of the image is 0px wide. So the browser knows it doesn’t have to bother downloading anything because there is nothing to show.</p>
829
830 <h2 id="3-image-quality">3. Image Quality</h2>
831
832 <p>Aside from image format and resolution, there are often settings to adjust the <em>quality</em> of the image using <strong>lossy compression</strong>. These are algorithms that remove parts of an image that you wouldn’t notice, but still take up space. Check out this example:</p>
833
834 <figure class="border">
835 <img src="https://requestmetrics.com/assets/images/webperf/high-performance-images/image_optimize.png" loading="lazy" class="lazyload" alt="Image Optimization" width="740" height="334" />
836 <figcaption>Image Optimization</figcaption>
837 </figure>
838
839 <p>This reduction is accomplished by pulling out unused colors, or by combining colors and pixels that too similar to notice. But you don’t need to worry about that, most optimization tools can detect the appropriate level of quality for an image. <a href="https://tinypng.com/">TinyPNG</a> and <a href="https://github.com/imagemin/imagemin">ImageMin</a> are great for this.</p>
840
841 <!-- class="wide">
842 <div class="wrap callout left flex">
843 <div class="picture">
844 <img loading="lazy" class="lazyload" src="https://requestmetrics.com/assets/images/callouts/callout-webvitals-aside-600.min.png" srcset="https://requestmetrics.com/assets/images/callouts/callout-webvitals-aside-600.min.png 600w,
845 https://requestmetrics.com/assets/images/callouts/callout-webvitals-aside-900.min.png 900w,
846 https://requestmetrics.com/assets/images/callouts/callout-webvitals-aside-1200.min.png 1200w" sizes="(max-width: 900px) 100vw, 400px" alt="Core Web Vital Performance Metrics" width="600" height="450" />
847 </div>
848 <div class="blurb">
849 <h2>Core Web Vital Performance Monitoring</h2>
850 <p>
851 Let us handle your performance work. Monitor your real-user Core Web Vital metrics with
852 <strong>Request Metrics</strong>. The fastest, easiest, and cheapest way to build a faster website.
853 </p>
854 <div class="flex cta-buttons">
855 <a class="btn btn-big btn-grey" href="https://requestmetrics.com/core-web-vitals">
856 Learn about the Core Web Vitals
857 </a>
858 </div>
859 </div>
860 </div>
861 -->
862
863 <h2 id="4-embedding-images">4. Embedding Images</h2>
864
865 <p>Sometimes an image is essential for a webpage to be useful, such as a button, logo, or icon. Once you’ve optimized it as small as you can make it, the only way to go faster is to <em>embed the image on the page</em>. This will save a network request and show an image as soon as the document starts rendering.</p>
866
867 <p>You embed an image by converting it into a <em>base64 string</em> and putting it right in the html tag, like this:</p>
868
869 <figure class="code " id="code-210">
870 <div class="code-wrap">
871 <pre class="prettyprint lang-html">
872 <img src="data:image/png;base64; iVBORw0KGgoAAAANSUhEUgAAAAUA
873 AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
874 9TXL0Y4OHwAAAABJRU5ErkJggg=="
875 alt="my awesome picture" />
876 </pre>
877 <!-- <button type="button" class="btn copy-button yes-js">
878 <img src="/assets/images/copy.svg" alt="Copy" />
879 <span class="label">Copy</span>
880 </button> -->
881
882 <figcaption><a href="#code-210">Embedded image</a></figcaption>
883
884 </div>
885 </figure>
886
887 <p>This may look strange, but it’s 100% supported as a <em>data url</em>. The <code class="language-plaintext highlighter-rouge">src</code> defines the format as a PNG image thats base64 encoded. The remainder is the actual contents of the image, in this case a small red dot.</p>
888
889 <figure class="border">
codemadness.org:70 /git/sfeed_tests/file/input/sfeed/realworld/requestmetrics.com.rss.xml.gph:900: line too long