<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kevin Farrugia</title>
    <description>The latest articles on DEV Community by Kevin Farrugia (@imkevdev).</description>
    <link>https://dev.to/imkevdev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F427114%2F3463e668-144e-4ac9-ab03-0b2940999530.jpeg</url>
      <title>DEV Community: Kevin Farrugia</title>
      <link>https://dev.to/imkevdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/imkevdev"/>
    <language>en</language>
    <item>
      <title>Priority Hints and optimizing LCP</title>
      <dc:creator>Kevin Farrugia</dc:creator>
      <pubDate>Mon, 02 Jan 2023 22:35:25 +0000</pubDate>
      <link>https://dev.to/imkevdev/priority-hints-and-prioritizing-lcp-529d</link>
      <guid>https://dev.to/imkevdev/priority-hints-and-prioritizing-lcp-529d</guid>
      <description>&lt;p&gt;Cross-posted from &lt;a href="https://imkev.dev/fetchpriority-opportunity" rel="noopener noreferrer"&gt;https://imkev.dev/fetchpriority-opportunity&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Priority Hints are used to indicate to the browser the relative priority of a resource. You can set Priority Hints by adding the &lt;code&gt;fetchpriority&lt;/code&gt; attribute to &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; elements or through the &lt;code&gt;priority&lt;/code&gt; attribute on the &lt;a href="https://fetch.spec.whatwg.org/#fetch-method" rel="noopener noreferrer"&gt;&lt;code&gt;Fetch&lt;/code&gt;&lt;/a&gt; API.&lt;/p&gt;

&lt;p&gt;The browser's loading process is complex. Browsers determine a request's priority mostly by its type and its position in the document's markup. For example, a CSS file requested in the document's &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; will be assigned the &lt;code&gt;Highest&lt;/code&gt; priority, while a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; element with the &lt;code&gt;defer&lt;/code&gt; attribute will be assigned the &lt;code&gt;Low&lt;/code&gt; priority. The browser downloads resources with the same priority in the order in which they are discovered.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;fetchpriority&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://wicg.github.io/priority-hints/#definitions" rel="noopener noreferrer"&gt;&lt;code&gt;fetchpriority&lt;/code&gt;&lt;/a&gt; attribute can be used to hint the browser to increase or decrease the priority of a requested resource. The enumerated attribute can have one of three values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;high&lt;/code&gt; - The resource is more important relative to its default priority&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;low&lt;/code&gt; - The resource is less important relative to its default priority&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;auto&lt;/code&gt; - The default value
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/lcp.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"A dog"&lt;/span&gt; &lt;span class="na"&gt;fetchpriority=&lt;/span&gt;&lt;span class="s"&gt;"high"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we are hinting to the browser that the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; priority is more important than its default priority.&lt;/p&gt;

&lt;p&gt;The same values are supported for the &lt;a href="https://fetch.spec.whatwg.org/#dom-requestinit-priority" rel="noopener noreferrer"&gt;&lt;code&gt;priority&lt;/code&gt;&lt;/a&gt; attribute on the &lt;code&gt;fetch&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/data.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;high&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;fetch&lt;/code&gt; request above, we are indicating to the browser that the &lt;code&gt;fetch&lt;/code&gt; request has an increased priority compared to its default priority.&lt;/p&gt;

&lt;h2&gt;
  
  
  Default priority
&lt;/h2&gt;

&lt;p&gt;Priority Hints increase or decrease a resource's priority relative to its default priority. For example, images - by default - always start at a &lt;code&gt;Low&lt;/code&gt; priority. Assigning &lt;code&gt;fetchpriority="high"&lt;/code&gt; will increase their priority to &lt;code&gt;High&lt;/code&gt;. On the other hand, a render-blocking stylesheet is assigned a &lt;code&gt;Highest&lt;/code&gt; priority by default. Assigning it &lt;code&gt;fetchpriority="low"&lt;/code&gt; will lower its priority to &lt;code&gt;High&lt;/code&gt; - but not &lt;code&gt;Low&lt;/code&gt;. &lt;code&gt;fetchpriority&lt;/code&gt; is used to adjust a resource's priority relative to its default, rather than to explicitly set its value.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.google.com/document/d/1bCDuq9H1ih9iNjgzyAL0gpwNFiEP4TZS-YLRp_RuMlc/edit" rel="noopener noreferrer"&gt;influence of Priority Hints on resource prioritization in Chromium&lt;/a&gt; documents the different resource types, their default priority (◉), and the resultant priority when using &lt;code&gt;fetchpriority="high"&lt;/code&gt; (⬆) and &lt;code&gt;fetchpriority="low"&lt;/code&gt; (&lt;strong&gt;⬇&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that if an image is discovered to be within the viewport, then its priority is boosted to &lt;code&gt;High&lt;/code&gt;. However, this could be quite late in the loading process and may have little or no impact if the request was already sent. Using &lt;code&gt;fetchpriority="high"&lt;/code&gt; allows you to tell the browser to start in &lt;code&gt;High&lt;/code&gt; priority, rather than waiting for the browser to find out if it is in the viewport or not.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  "Tight mode"
&lt;/h2&gt;

&lt;p&gt;Most browsers download resources in two phases. During the initial phase (Chromium also refers to this as "Tight mode"), the browser does not download &lt;code&gt;Low&lt;/code&gt; priority resources unless there are less than two in-flight requests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwijp9tffp9q17n20j08k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwijp9tffp9q17n20j08k.png" alt="WebPageTest waterfall chart illustrating the initial phase" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the waterfall chart above, you could see that the resource &lt;code&gt;image-1.jpg&lt;/code&gt; does not start downloading until &lt;code&gt;style-2.css&lt;/code&gt; has finished downloading - even if it was discovered immediately. At this point, only one resource remains in-flight - &lt;code&gt;script.js&lt;/code&gt;, so the browser begins to download the &lt;code&gt;Low&lt;/code&gt; priority image.&lt;/p&gt;

&lt;p&gt;The initial phase is completed once all blocking scripts in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; have been downloaded and executed (scripts with &lt;code&gt;async&lt;/code&gt; or &lt;code&gt;defer&lt;/code&gt; are not render-blocking). Even if there are more than two in-flight requests, the browser can now proceed to download any remaining resources based on their priority and the order in which they appear in the markup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5t6nsc1wsz4lvdjoq6a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5t6nsc1wsz4lvdjoq6a.png" alt="WebPageTest waterfall chart illustrating DOM Interactive" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the chart above, once the render-blocking JavaScript is downloaded and executed (pink bar), the browser begins downloading the images, even if the two CSS files are still in-flight. The yellow vertical bar illustrates DOM Interactive - or when the &lt;code&gt;readystatechange&lt;/code&gt; event was fired.&lt;/p&gt;

&lt;h2&gt;
  
  
  preconnect
&lt;/h2&gt;

&lt;p&gt;If the images reside on a separate domain, the browser needs to open a connection to the domain before downloading the files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falzh3fbh0br2c4hgfit3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falzh3fbh0br2c4hgfit3.png" alt="WebPageTest waterfall chart illustrating crossorigin images" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is shown on the WebPageTest chart with the green, orange, and magenta bars preceding the downloading. We can start downloading the images earlier using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preconnect" rel="noopener noreferrer"&gt;&lt;code&gt;preconnect&lt;/code&gt;&lt;/a&gt; resource hint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn5s2fzdebrl14m4j4dcz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn5s2fzdebrl14m4j4dcz.png" alt="WebPageTest waterfall chart illustrating  raw `preconnect` endraw  resource hint" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the chart above, the connection to the &lt;code&gt;cdn.glitch.global&lt;/code&gt; domain is opened during the initial phase - before the browser is able to start downloading the files. Once the browser exits the initial phase (yellow vertical line) it begins downloading the images immediately - saving approximately 350ms.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;preload&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;If we were able to improve the download time using the &lt;code&gt;preconnect&lt;/code&gt; resource hint, are we able to improve it further using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload" rel="noopener noreferrer"&gt;&lt;code&gt;preload&lt;/code&gt;&lt;/a&gt; directive? Short answer: no. The &lt;code&gt;preload&lt;/code&gt; directive allows you to inform the browser about critical resources that are "late-discovered". This is especially useful for resources loaded inside stylesheets or scripts, such as background-images or fonts. In our example, the image is declared in the markup and discovered early, so preload has little effect.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhcr22h7jjzl5bq9tkyss.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhcr22h7jjzl5bq9tkyss.png" alt="WebPageTest waterfall chart illustrating  raw `preload` endraw  directive" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the chart above, we have replaced the &lt;code&gt;preconnect&lt;/code&gt; hint with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
  &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt;
  &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.glitch.global/.../image-1.jpg"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Despite the preload, the image still doesn’t begin downloading until there are less than two requests in-flight.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;fetchpriority&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;We can use Priority Hints to indicate to the browser that &lt;code&gt;image-1.jpg&lt;/code&gt; is more important than its default priority using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.glitch.global/.../image-1.jpg"&lt;/span&gt;
  &lt;span class="na"&gt;fetchpriority=&lt;/span&gt;&lt;span class="s"&gt;"high"&lt;/span&gt;
  &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should increase the initial priority of the image from &lt;code&gt;Low&lt;/code&gt; to &lt;code&gt;High&lt;/code&gt;, allowing the image to be picked up in the initial phase.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45i2oikpcfexbsv1y2ov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45i2oikpcfexbsv1y2ov.png" alt="WebPageTest waterfall chart illustrating  raw `fetchpriority=" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The waterfall chart above shows that &lt;code&gt;image-1.jpg&lt;/code&gt; is picked up during the initial phase, in parallel with the other critical resources. This gives us the greatest improvement so far.&lt;/p&gt;

&lt;h2&gt;
  
  
  Firefox
&lt;/h2&gt;

&lt;p&gt;Firefox uses similar heuristics to determine which resources should be loaded during the initial phase. However, differently from Chromium-based browsers, it does not begin downloading any &lt;code&gt;Low&lt;/code&gt; priority resources until all JavaScript in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; is downloaded and executed - even when there is only one &lt;code&gt;High&lt;/code&gt; priority request in-flight.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9q49ezpyc9lg9l0x8jwq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9q49ezpyc9lg9l0x8jwq.png" alt="Screenshot from Firefox Web Developer Tools illustrating the initial phase" width="800" height="165"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above screenshot is taken from Firefox Web Developer Tools and shows that the image resources (rows 5 - 8) are fetched after the script (row 2) is downloaded and executed and the page becomes &lt;code&gt;interactive&lt;/code&gt; - vertical, blue line.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;While Chrome waits for JavaScript declared in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; to be downloaded and executed, Firefox waits for all render-blocking JavaScript declared before the image elements - even if these are declared outside of the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Firefox does not &lt;a href="https://github.com/whatwg/html/issues/7150#issuecomment-1299923593" rel="noopener noreferrer"&gt;support &lt;code&gt;fetchpriority&lt;/code&gt;&lt;/a&gt; yet, however, we can increase the priority of &lt;code&gt;image-1.jpg&lt;/code&gt; using the &lt;code&gt;preload&lt;/code&gt; directive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hwd4tl8j647z1728pna.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hwd4tl8j647z1728pna.png" alt="Screenshot from Firefox Web Developer Tools illustrating the initial phase" width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the screenshot above, the file &lt;code&gt;image-1.jpg&lt;/code&gt; is fetched in parallel with the other resources. This is similar to the behavior we have seen when adding &lt;code&gt;fetchpriority="high"&lt;/code&gt; on Google Chrome.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safari
&lt;/h2&gt;

&lt;p&gt;Safari on iOS and macOS also has an initial phase although it behaves differently than Chrome and Firefox.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Low&lt;/code&gt; priority resources start being fetched when there are fewer than two in-flight requests. It is not dependent on the &lt;code&gt;readystatechange&lt;/code&gt; event and even on pages without any render-blocking JavaScript, the browser will wait until there is one in-flight request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwc27npsz8co4ifmxt8d3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwc27npsz8co4ifmxt8d3.png" alt="Screenshot showing Safari Web Inspector tight mode" width="800" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the screenshot above, taken from Safari's Web Inspector, the images do not start downloading until &lt;code&gt;style-1.css&lt;/code&gt; finishes downloading and there are less than two in-flight requests.&lt;/p&gt;

&lt;p&gt;On Safari, the initial phase only applies to resources from the same origin. If the &lt;code&gt;Low&lt;/code&gt; priority resources are loaded from a different domain they will be fetched as soon as they are discovered.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgmc4wrk3uy1flguwva85.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgmc4wrk3uy1flguwva85.png" alt="Screenshot showing Safari Web Inspector not restricting crossorigin  raw `Low` endraw  priority requests" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the screenshot above, the crossorigin images are fetched immediately without waiting for the &lt;code&gt;High&lt;/code&gt; priority resources to finish downloading.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;preload&lt;/code&gt; directive does not affect the resource's priority. However, placing the &lt;code&gt;&amp;lt;link rel="preload"&amp;gt;&lt;/code&gt; directive before &lt;code&gt;High&lt;/code&gt; priority requests will cause it to download earlier; since at the time it is discovered there are less than two requests in-flight. This is the same behavior seen on other browsers and in most cases, I would advise against placing &lt;code&gt;preload&lt;/code&gt; directives above &lt;code&gt;High&lt;/code&gt; priority resources as render-blocking CSS should take precedence.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhcpbjlqu91x0rnfn6xny.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhcpbjlqu91x0rnfn6xny.png" alt="Screenshot of Safari Web Inspector illustrating the  raw `preload` endraw  directive" width="800" height="149"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this screenshot, the &lt;code&gt;Low&lt;/code&gt; priority file &lt;code&gt;image-1.jpg&lt;/code&gt; begins downloading before the &lt;code&gt;High&lt;/code&gt; priority &lt;code&gt;style-1.css&lt;/code&gt; file because the &lt;code&gt;&amp;lt;link rel="preload"&amp;gt;&lt;/code&gt; is placed above it in the document markup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combining &lt;code&gt;preload&lt;/code&gt; with &lt;code&gt;fetchpriority&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Priority Hints are only &lt;a href="https://caniuse.com/?search=fetchpriority" rel="noopener noreferrer"&gt;supported on Chromium-based browsers&lt;/a&gt; so far, however, they fail gracefully on unsupported browsers that do not recognize the &lt;code&gt;fetchpriority&lt;/code&gt; attribute. This allows us to combine the &lt;code&gt;preload&lt;/code&gt; directive with Priority Hints.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
  &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt;
  &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt;
  &lt;span class="na"&gt;fetchpriority=&lt;/span&gt;&lt;span class="s"&gt;"high"&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.glitch.global/.../image-1.jpg"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Browsers that support Priority Hints will preload the resource using the assigned &lt;code&gt;fetchpriority&lt;/code&gt;, while browsers that do not will use the &lt;code&gt;preload&lt;/code&gt; directive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvei6eue4ldom42hthswz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvei6eue4ldom42hthswz.png" alt="WebPageTest waterfall chart showing  raw `preload` endraw  and  raw `fetchpriority` endraw " width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above chart shows similar results to the one earlier which included the &lt;code&gt;fetchpriority&lt;/code&gt; attribute on the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element. The advantage of this method is unifying an approach that prioritizes the resource on browsers that support Priority Hints and on those that do not.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;fetchpriority&lt;/code&gt; all the things
&lt;/h2&gt;

&lt;p&gt;In this section, we will look at the potential benefit of using &lt;code&gt;fetchpriority&lt;/code&gt;. All data is taken from the &lt;a href="https://httparchive.org" rel="noopener noreferrer"&gt;HTTP Archive&lt;/a&gt; and we are only considering pages that use HTTP/2 or HTTP/3 and where the &lt;a href="https://web.dev/lcp" rel="noopener noreferrer"&gt;Largest Contentful Paint&lt;/a&gt; (LCP) element is an image. All &lt;a href="https://github.com/kevinfarrugia/fetchpriority-opportunity" rel="noopener noreferrer"&gt;queries&lt;/a&gt; and &lt;a href="https://docs.google.com/spreadsheets/d/11QwVrr1zcFGBhOMNe25uFBD9VUfg4JP3AUkhWjod9RY/edit?usp=sharing" rel="noopener noreferrer"&gt;results&lt;/a&gt; are publicly available.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: The HTTP Archive data is collected using a private instance of WebPageTest using Chrome. You can learn more about their &lt;a href="https://httparchive.org/faq#how-is-the-data-gathered" rel="noopener noreferrer"&gt;methodology&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe9wz1rbzxw20v8t8utl7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe9wz1rbzxw20v8t8utl7.png" alt="WebPageTest waterfall chart illustrating the opportunity for the LCP image with a horizontal red line" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am assuming the benefit from &lt;code&gt;fetchpriority&lt;/code&gt; as the difference between the time the resource is discovered and the time it starts downloading. I refer to this as the &lt;em&gt;opportunity&lt;/em&gt;. Therefore if a resource is discovered early but the browser starts downloading it late, then the opportunity is greater.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that if the images are served from a different domain, I am including the time to open the connection in the opportunity.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fboeq6o0srcq28pytcny6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fboeq6o0srcq28pytcny6.png" alt="Combination chart showing *opportunity* vs LCP" width="600" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The chart above plots the &lt;em&gt;opportunity&lt;/em&gt; (in milliseconds) against the LCP. The &lt;em&gt;opportunity&lt;/em&gt; is bucketed in groups of 100ms, while anything greater than 1,000ms is grouped into a single bucket. The chart shows a strong correlation between the &lt;em&gt;opportunity&lt;/em&gt; and the LCP - the greater the &lt;em&gt;opportunity&lt;/em&gt;, the worse the LCP.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feask0hs4tpdtxfog3nk1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feask0hs4tpdtxfog3nk1.png" alt="Bar chart showing distribution of opportunity by initial priority" width="600" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above chart shows the distribution of the &lt;em&gt;opportunity&lt;/em&gt; for mobile devices for &lt;code&gt;Low&lt;/code&gt; and &lt;code&gt;High&lt;/code&gt; priority. At the median, an LCP image requested with &lt;code&gt;High&lt;/code&gt; priority starts to be downloaded 21ms after it is discovered, while an LCP image with &lt;code&gt;Low&lt;/code&gt; priority is downloaded after 102ms. The difference grows even further at the 75th and 90th percentile.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In addition to &lt;code&gt;fetchpriority="High"&lt;/code&gt;, an image may have an initial &lt;code&gt;High&lt;/code&gt; priority if the image is late-discovered, for example when using CSS &lt;code&gt;background-image&lt;/code&gt; or adding an image using JavaScript. In these cases, &lt;code&gt;fetchpriority&lt;/code&gt; would not help since the request already has a &lt;code&gt;High&lt;/code&gt; priority.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We can conclude that there is a clear benefit in prioritizing your LCP image. The opportunity varies depending on your page's composition. We have already covered that &lt;code&gt;Low&lt;/code&gt; priority resources are not fetched immediately when there is at least one render-blocking script and two or more in-flight requests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsp8klfsesbjn1d8cnfot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsp8klfsesbjn1d8cnfot.png" alt="Combination chart showing the number of render-blocking resources vs median *opportunity*" width="600" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above chart plots the number of render-blocking resources against the opportunity (in milliseconds). Intuitively, the more render-blocking resources your page has, the greater the delay in downloading the LCP image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There is a big opportunity available to prioritize your LCP image through Resource Hints and Priority Hints. Many pages have the LCP element queued and waiting, even when it is immediately discoverable in the main document.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fruq7yckdhoe5rsbrdf42.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fruq7yckdhoe5rsbrdf42.png" alt="Distribution of opportunity" width="600" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above chart shows that on the median mobile website, the LCP image is queued for 98ms until the browser starts downloading it. At the 90th percentile, the LCP image is queued for 810ms. Using Priority Hints could increase the priority of the LCP image and reduce this waiting time.&lt;/p&gt;

&lt;p&gt;There are also case studies showing an improvement to &lt;a href="https://web.dev/lcp" rel="noopener noreferrer"&gt;Largest Contentful Paint&lt;/a&gt; (LCP) after adding &lt;code&gt;fetchpriority="high"&lt;/code&gt; to the LCP image. &lt;a href="https://www.etsy.com/codeascraft/priority-hints-what-your-browser-doesnt-know-yet" rel="noopener noreferrer"&gt;Etsy saw a 4% improvement&lt;/a&gt;, some others reportedly saw 20-30% improvements.&lt;/p&gt;

&lt;p&gt;Increasing the priority of a resource usually comes at the cost of another resource, so Priority Hints should be used sparingly. However, if the browser is queuing your LCP image, I recommend you experiment with Priority Hints to see if you can reduce this waiting time and improve your LCP.&lt;/p&gt;

&lt;p&gt;In a nutshell,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Host your LCP image on the same domain as your HTML document. If this is not possible, use &lt;code&gt;preconnect&lt;/code&gt; to open an early connection.&lt;/li&gt;
&lt;li&gt;The LCP image should be part of the document markup. If you are unable to do this, use &lt;code&gt;preload&lt;/code&gt; to tell the browser to download the image before it is requested.&lt;/li&gt;
&lt;li&gt;Avoid blocking resources when possible. If your LCP image is downloaded with a &lt;code&gt;Low&lt;/code&gt; priority, use &lt;code&gt;fetchpriority&lt;/code&gt; to hint the browser to download your image earlier.&lt;/li&gt;
&lt;li&gt;You can use &lt;code&gt;preload&lt;/code&gt; to prioritize your LCP image on Firefox until &lt;code&gt;fetchpriority&lt;/code&gt; is supported. Safari does not download images earlier when using the &lt;code&gt;preload&lt;/code&gt; directive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me know what you think. Your feedback is welcome. ♥&lt;/p&gt;

&lt;h2&gt;
  
  
  Related links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://fetchpriority-opportunity.glitch.me/" rel="noopener noreferrer"&gt;Demos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/kevinfarrugia/fetchpriority-opportunity" rel="noopener noreferrer"&gt;Queries&lt;/a&gt; &amp;amp; &lt;a href="https://docs.google.com/spreadsheets/d/11QwVrr1zcFGBhOMNe25uFBD9VUfg4JP3AUkhWjod9RY/edit?usp=sharing" rel="noopener noreferrer"&gt;Results&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://web.dev/priority-hints/" rel="noopener noreferrer"&gt;Optimizing resource loading with Priority Hints&lt;/a&gt; (web.dev)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.debugbear.com/blog/priority-hints" rel="noopener noreferrer"&gt;Prioritizing Important Page Resources With Priority Hints&lt;/a&gt; (debugbear.com)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Special thanks
&lt;/h2&gt;

&lt;p&gt;Special thanks to &lt;a href="https://webperf.social/@tunetheweb" rel="noopener noreferrer"&gt;Barry Pollard&lt;/a&gt; for his advice and valuable feedback.&lt;/p&gt;




&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@dmjdenise?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Denise Jans&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/cycle-lane?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>emptystring</category>
    </item>
    <item>
      <title>Interaction to Next Paint</title>
      <dc:creator>Kevin Farrugia</dc:creator>
      <pubDate>Fri, 17 Jun 2022 14:32:38 +0000</pubDate>
      <link>https://dev.to/imkevdev/interaction-to-next-paint-2eam</link>
      <guid>https://dev.to/imkevdev/interaction-to-next-paint-2eam</guid>
      <description>&lt;p&gt;Cross-posted from &lt;a href="https://imkev.dev/inp"&gt;https://imkev.dev/inp&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In May 2022, Google added Time to First Byte (TTFB) and &lt;a href="https://web.dev/inp/"&gt;Interaction to Next Paint&lt;/a&gt; (INP) to their CrUX report. INP measures a website's responsiveness and might replace &lt;a href="https://web.dev/fid/"&gt;First Input Delay&lt;/a&gt; (FID) as a Core Web Vital in the future.&lt;/p&gt;

&lt;p&gt;Let's take a look at what Interaction to Next Paint is and how can you prepare your website to have a good INP.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Input Delay
&lt;/h2&gt;

&lt;p&gt;Before looking at INP, let's review First Input Delay, the Core Web Vital currently used to measure responsiveness to user interaction. FID measures the delay it takes the browser to begin processing the &lt;em&gt;first&lt;/em&gt; interaction on a page.&lt;/p&gt;

&lt;p&gt;In single-threaded JavaScript, if the main thread is busy processing a task, any user input is delayed until the call stack is clear and all tasks have been completed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qgoORC3X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ux259o6q1w155o1vxrcg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qgoORC3X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ux259o6q1w155o1vxrcg.gif" alt="Image description" width="640" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An example of poor responsiveness. The user key events do not update the screen until a long task has been completed and all characters are added at once.&lt;/p&gt;

&lt;p&gt;FID is directly correlated with JavaScript long tasks. The more long JavaScript tasks on your website, the more likely that the user input will be delayed as the browser must wait for the current long task to complete before processing input.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sQlNmKac--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/04unizyyp5j8l6qxwc1j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sQlNmKac--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/04unizyyp5j8l6qxwc1j.png" alt="The percentage of origins with good FID experiences, less than or equal to 100 ms" title="The percentage of origins with good FID experiences, less than or equal to 100 ms" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The number of websites achieving a &lt;a href="https://httparchive.org/reports/chrome-ux-report#cruxFastFid"&gt;good FID&lt;/a&gt; score has increased from 72.1% of origins in 2018 to 92.5% of origins in May 2022. FID on desktop was always &amp;gt; 98%.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interaction to Next Paint
&lt;/h2&gt;

&lt;p&gt;INP aims to build on FID but considers the responsiveness of &lt;em&gt;all&lt;/em&gt; user inputs. It also captures the entire duration of the interaction, until the next frame is painted onto the screen. Check out this &lt;a href="https://inp-demo.glitch.me/"&gt;demo&lt;/a&gt; to get a feel of how frustrating a high INP could be.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is an interaction?
&lt;/h3&gt;

&lt;p&gt;An &lt;a href="https://web.dev/inp/#what's-in-an-interaction"&gt;interaction&lt;/a&gt; is one of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clicking or tapping on an interactive element, such as a button or checkbox.&lt;/li&gt;
&lt;li&gt;Pressing a key, including text input fields.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It does not include hover or scroll events.&lt;/p&gt;

&lt;h3&gt;
  
  
  How is an interaction's duration measured?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qgp7hkq---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/edl8e3hkj4yupy1llptg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qgp7hkq---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/edl8e3hkj4yupy1llptg.png" alt="Breakdown of an interaction" title="Breakdown of an interaction" width="880" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The phases of a single interaction. The input delay occurs from the time an input is received and may be caused by factors such as blocking tasks on the main thread. The processing time is the time it takes for the interaction's event handlers to execute. When execution finishes, we then enter the presentation delay, which is the time it takes to render and paint the next frame. Source: &lt;a href="https://web.dev/inp/"&gt;https://web.dev/inp/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An interaction consists of three phases, the input delay, the processing time and the presentation delay. The duration of an interaction as measured by INP is the sum of the time for all three phases. In simpler words, it is the time it takes from when the user interacts with an element or input until the next frame is painted on the screen. This could be any visual cue that the user input has been received, such as displaying the character in a textbox or displaying a loading animation after clicking a button.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a good INP?
&lt;/h3&gt;

&lt;p&gt;In most cases, INP measures the &lt;em&gt;worst&lt;/em&gt; interaction on your page. For highly interactive pages with more than 50 interactions, then INP will pick the 98th percentile. A good INP is one under 200 milliseconds, while a poor INP is one over 500ms. Anything in between means that your page needs improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is INP important?
&lt;/h2&gt;

&lt;p&gt;Even if Google does not add INP as a Core Web Vital, INP is descriptive of your user's experience on your website. Having a good INP means that your website responds quickly to user input and provides your users with a delightful experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--atn_gp6H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5zwmlkau8071vtmnxc14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--atn_gp6H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5zwmlkau8071vtmnxc14.png" alt="Correlation between JS Long Tasks and Conversion Rate" title="Correlation between JS Long Tasks and Conversion Rate" width="880" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A chart demonstrating a negative correlation between JS Long Tasks and Conversion Rate. The more long tasks, the less likely a user is to convert.&lt;/p&gt;

&lt;p&gt;The above chart - taken from RUM data from a client of mine - shows a strong negative correlation between JavaScript long tasks and the conversion rate. The median conversion rate for users that experience &amp;lt; 500ms JS long tasks is 38.5%, while users that experience &amp;gt; 4000ms long tasks have a conversion rate of 11.8%. This has a tremendous business impact and is more strongly correlated than any of the Core Web Vitals!&lt;/p&gt;

&lt;p&gt;And with INP 2x &lt;a href="https://colab.research.google.com/drive/12lJmAABgyVjaUbmWvrbzj9BkkTxw6ay2?usp=sharing"&gt;more correlated&lt;/a&gt; to Total Blocking Time (TBT) than FID, we expect to see a similar negative correlation between INP and the conversion rate.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you optimize INP?
&lt;/h2&gt;

&lt;p&gt;As INP is correlated well with TBT, you could imply that reducing TBT will reduce your INP.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.debugbear.com/docs/performance/minimize-main-thread-work"&gt;Minimize main-thread work&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Optimize your JavaScript bundles by &lt;a href="https://web.dev/reduce-javascript-payloads-with-code-splitting/"&gt;code-splitting&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If you are working on a React app, you should minimize hydration and &lt;a href="https://imkev.dev/optimizing-rerenders"&gt;optimize your rerenders&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Audit your third-parties to ensure they aren't bloating your main thread on page load or affecting page responsiveness on user interaction, such as event handlers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tooling
&lt;/h2&gt;

&lt;p&gt;The best way to measure INP is to collect metrics from real users. If your website meets the criteria to be included in the &lt;a href="https://developers.google.com/web/tools/chrome-user-experience-report"&gt;CrUX&lt;/a&gt; dataset, then you can use the CrUX API's &lt;code&gt;experimental_interaction_to_next_paint&lt;/code&gt; field or via BigQuery.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3c71lAqL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ciw0r50bemv1kg04x3wq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3c71lAqL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ciw0r50bemv1kg04x3wq.png" alt="PageSpeed Insights" title="PageSpeed Insights" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;INP is now available on PageSpeed Insights.&lt;/p&gt;

&lt;p&gt;You may view INP data using &lt;a href="https://pagespeed.web.dev/"&gt;PageSpeed Insights&lt;/a&gt; or &lt;a href="https://treo.sh"&gt;Treo&lt;/a&gt;; however, these still rely on the CrUX dataset.&lt;/p&gt;

&lt;p&gt;You can measure the INP metric yourself by using the &lt;a href="https://github.com/GoogleChrome/web-vitals/tree/next"&gt;&lt;code&gt;web-vitals&lt;/code&gt; library&lt;/a&gt; and sending this data to Google Analytics or another analytics endpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;maxDuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;PerformanceObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEntries&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Comment this out to show ALL event entry types (useful e.g. on Firefox).&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interactionId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;maxDuration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// New longest Interaction to Next Paint (duration).&lt;/span&gt;
      &lt;span class="nx"&gt;maxDuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[INP] duration: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, type: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Not the longest Interaction, but uncomment the next line if you still want to see it.&lt;/span&gt;
      &lt;span class="c1"&gt;// console.log(`[Interaction] duration: ${entry.duration}, type: ${entry.name}`, entry);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;durationThreshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Minimum supported by the spec.&lt;/span&gt;
  &lt;span class="na"&gt;buffered&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're looking to debug INP on your website, you can create a PerformanceObserver and log the longest interaction. Note that this is a simplification of the INP metric and may vary.&lt;/p&gt;

&lt;h2&gt;
  
  
  INP in the wild
&lt;/h2&gt;

&lt;p&gt;According to the HTTP Archive, only 56.4% of all mobile origins have a good INP. While 95.7% of desktop origins have a good INP.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;th&gt;Origins&lt;/th&gt;
&lt;th&gt;Good INP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ALL&lt;/td&gt;
&lt;td&gt;6,754,899&lt;/td&gt;
&lt;td&gt;55%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;jQuery&lt;/td&gt;
&lt;td&gt;5,591,806&lt;/td&gt;
&lt;td&gt;57%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AngularJS&lt;/td&gt;
&lt;td&gt;85,049&lt;/td&gt;
&lt;td&gt;46%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vue.js&lt;/td&gt;
&lt;td&gt;211,468&lt;/td&gt;
&lt;td&gt;42%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React&lt;/td&gt;
&lt;td&gt;582,000&lt;/td&gt;
&lt;td&gt;35%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Preact&lt;/td&gt;
&lt;td&gt;183,771&lt;/td&gt;
&lt;td&gt;35%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Svelte&lt;/td&gt;
&lt;td&gt;8,062&lt;/td&gt;
&lt;td&gt;33%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;CWV technology report - INP data for May 2022&lt;/p&gt;

&lt;p&gt;The above table is extracted from the HTTP Archive as of May 2022, using the &lt;a href="https://cwvtech.report"&gt;CWV Technology Report&lt;/a&gt;. Most modern front-end frameworks do poorly in INP, which isn't surprising considering how much heavy-lifting is being done in JavaScript.&lt;/p&gt;

&lt;p&gt;Thank you for reading. I would love to hear your feedback and please reach out if you would like to see more correlations involving INP.&lt;/p&gt;

&lt;p&gt;Image credits: Photo by &lt;a href="https://unsplash.com/@davidpisnoy?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;David Pisnoy&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/paint?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt; &lt;/p&gt;

</description>
      <category>performance</category>
      <category>webperf</category>
      <category>javascript</category>
    </item>
    <item>
      <title>React Sticky Children</title>
      <dc:creator>Kevin Farrugia</dc:creator>
      <pubDate>Mon, 07 Mar 2022 11:07:29 +0000</pubDate>
      <link>https://dev.to/imkevdev/react-sticky-children-2808</link>
      <guid>https://dev.to/imkevdev/react-sticky-children-2808</guid>
      <description>&lt;p&gt;I created a simple ReactJS plugin &lt;a href="https://www.npmjs.com/package/react-sticky-children"&gt;&lt;code&gt;react-sticky-children&lt;/code&gt;&lt;/a&gt; to abstract away the complexities of the IntersectionObserver API and allow you to apply styles to a component as it approaches the top of the viewport. Useful for "Scroll to Top", complex "sticky" elements or animating components into view.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://react-sticky-children.vercel.app/"&gt;Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9Jz4lyt8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fd0glcyafqygd4ehj28z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9Jz4lyt8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fd0glcyafqygd4ehj28z.gif" alt="Demo" width="600" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { ReactStickyChildren } from 'react-sticky-children';

&amp;lt;ReactStickyChildren initialStyle={initialStyle} intersectingStyle={intersectingStyle}&amp;gt;
  &amp;lt;MyComponent /&amp;gt;
&amp;lt;/ReactStickyChildren&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking for feedback. 🙏&lt;/p&gt;

&lt;p&gt;NPM: &lt;a href="https://www.npmjs.com/package/react-sticky-children"&gt;https://www.npmjs.com/package/react-sticky-children&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/kevinfarrugia/react-sticky-children"&gt;https://github.com/kevinfarrugia/react-sticky-children&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Component Composition in React</title>
      <dc:creator>Kevin Farrugia</dc:creator>
      <pubDate>Wed, 23 Feb 2022 08:49:24 +0000</pubDate>
      <link>https://dev.to/imkevdev/component-composition-in-react-3mmk</link>
      <guid>https://dev.to/imkevdev/component-composition-in-react-3mmk</guid>
      <description>&lt;p&gt;Cross-posted from &lt;a href="https://imkev.dev/component-composition"&gt;https://imkev.dev/component-composition&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the most misunderstood design patterns in a React application is the render props pattern and component composition. While this isn't a new or novel approach and has been promoted since at least 2017, five years later I still encounter opportunities where it should have been used instead of an inheritance hierarchy. &lt;em&gt;Component composition&lt;/em&gt; is the technique of combining different modular components to construct another component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Render Props
&lt;/h2&gt;

&lt;p&gt;"But almost all components are made up of sub-components, so what's so special about component composition?" I hear you say. I distinguish between a regular component and component composition by passing one or more of the sub-components as props to the parent component. These props are known as &lt;em&gt;render props&lt;/em&gt; and the most commonly used render prop is the &lt;code&gt;children&lt;/code&gt; prop which is included in React by default.&lt;/p&gt;

&lt;p&gt;Let's take a look at an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Title&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Title&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&amp;gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Random title #1"&lt;/span&gt;
        &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Lorem ipsum..."&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://codesandbox.io/s/inheritance-j3s2s"&gt;Inheritance Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The component above might look fairly ordinary. A component &lt;code&gt;MyComponent&lt;/code&gt; renders a &lt;code&gt;div&lt;/code&gt; element and within it, there are two child elements. One being the &lt;code&gt;&amp;lt;Title&amp;gt;&lt;/code&gt; component and the other being a &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; element. &lt;code&gt;MyComponent&lt;/code&gt; receives two props, the &lt;code&gt;title&lt;/code&gt; and the &lt;code&gt;text&lt;/code&gt; component, which it outputs or passes onto the sub-component.&lt;/p&gt;

&lt;p&gt;Let's see the same component using the component composition pattern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Title&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Random title #1"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Lorem ipsum...
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://codesandbox.io/s/component-composition-jfo5l"&gt;Component Composition Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, the role of &lt;code&gt;MyComponent&lt;/code&gt; is reduced to creating a &lt;code&gt;div&lt;/code&gt; element and placing the &lt;code&gt;children&lt;/code&gt; prop within the &lt;code&gt;div&lt;/code&gt;. The parent component which calls &lt;code&gt;MyComponent&lt;/code&gt; is responsible for creating the &lt;code&gt;&amp;lt;Title&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; elements. The generated HTML in these two examples is identical.&lt;/p&gt;

&lt;h2&gt;
  
  
  Single-responsibility principle
&lt;/h2&gt;

&lt;p&gt;When I was still at University studying computer science, amongst the many practices we were taught, there were the &lt;a href="https://en.wikipedia.org/wiki/SOLID"&gt;SOLID principles&lt;/a&gt;. Without going into the merits of the SOLID principles, the S in SOLID stands for the Single-Responsibility principle and states (paraphrasing) that a class or function should only have one reason to change. A class or function should only have one role. I like that. It makes it easier to understand, easier to debug, and makes your code more portable.&lt;/p&gt;

&lt;p&gt;The component composition pattern helps enforce this practice as the role of &lt;code&gt;MyComponent&lt;/code&gt; in the example above is to only create the &lt;code&gt;div&lt;/code&gt; and place the &lt;code&gt;children&lt;/code&gt; in the correct place. The role of &lt;code&gt;App&lt;/code&gt; is to construct the composition of different components required to build the module. Contrary to the first example, &lt;code&gt;MyComponent&lt;/code&gt; is not responsible for choosing the order of the &lt;code&gt;&amp;lt;Title&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; elements, and if you would want to change their order, you would need to change &lt;code&gt;MyComponent&lt;/code&gt;. This violates the Single-Responsibility principle.&lt;/p&gt;

&lt;h2&gt;
  
  
  In practice
&lt;/h2&gt;

&lt;p&gt;The above example is very simple and you are unlikely to encounter this scenario in a real-world environment. But the concept could be applied to any component structure.&lt;/p&gt;

&lt;p&gt;In addition to displaying and outputting HTML, one of the more common tasks of a React component is to fetch data from a store or an API. Let's compare inheritance and component composition using an example where we are fetching a list of users and then displaying these in a &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;quantity&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUsers&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_URL&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;setUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserCard&lt;/span&gt;
                &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;profilePicture&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserList&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://codesandbox.io/s/inheritance-data-mim6kn"&gt;Inheritance Data Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;UserList&lt;/code&gt; component receives a &lt;code&gt;quantity&lt;/code&gt; prop indicating the number of items to retrieve from the API. Once the component is mounted, it will make a request, populate the result in the state, and then display a list of &lt;code&gt;UserCard&lt;/code&gt; sub-components inside a &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's take a look at the same application if it were following the component composition pattern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUsers&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_URL&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;setUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Users&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserCard&lt;/span&gt;
                      &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                      &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                      &lt;span class="na"&gt;profilePicture&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://codesandbox.io/s/component-composition-data-fxs4b7"&gt;Component Composition Data Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;App&lt;/code&gt; component now renders a &lt;code&gt;Users&lt;/code&gt; component. This component is solely responsible for fetching the users from the API and returning them as a prop to the &lt;code&gt;children&lt;/code&gt; using the return statement &lt;code&gt;return children({ users })&lt;/code&gt;. Any child component of &lt;code&gt;Users&lt;/code&gt; will have access to the &lt;code&gt;users&lt;/code&gt; as a prop. The &lt;code&gt;App&lt;/code&gt; component iterates through the users it receives and creates the &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The latter approach allows you to separate fetching data from displaying it. If a change request comes in that requires the data to be filtered before being displayed, you immediately know that you do not need to do any changes to the &lt;code&gt;Users&lt;/code&gt; component as the change request does not require changes to the fetching of data. &lt;a href="https://codesandbox.io/s/component-composition-grid-gs04o7"&gt;Demo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Multiple Render Props
&lt;/h2&gt;

&lt;p&gt;While in many cases you can use the &lt;code&gt;children&lt;/code&gt; prop included in React, in some cases you may need to place multiple sub-components that will not be rendered beside each other in the DOM. In these cases, you may define further &lt;em&gt;render props&lt;/em&gt; similarly to how you would assign an ordinary prop. The only difference is that you pass a component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;headerFn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;headerFn&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;hr&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Component Composition&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="na"&gt;headerFn&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Title&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Random title #1"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Lorem ipsum...
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this simple example, we have added &lt;code&gt;headerFn&lt;/code&gt; prop to &lt;code&gt;MyComponent&lt;/code&gt; and passed &lt;code&gt;&amp;lt;Title title="Random title #1" /&amp;gt;&lt;/code&gt; to it. &lt;code&gt;MyComponent&lt;/code&gt; is only responsible for the DOM structure and placing the correct CSS classes, while &lt;code&gt;App&lt;/code&gt; is responsible for defining the components to be rendered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The component composition pattern can simplify your applications, making the code more portable, maintainable, and &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY&lt;/a&gt;. Once you become accustomed to this pattern, it is easy to apply it in almost any situation you would have previously used inheritance.&lt;/p&gt;

&lt;p&gt;I hope this helped convince you to make use of component composition more often. If you're not yet convinced, ReactJS docs go as far as to say that they &lt;a href="https://reactjs.org/docs/composition-vs-inheritance.html#so-what-about-inheritance"&gt;haven’t found any use cases where they would recommend creating component inheritance hierarchies&lt;/a&gt; and &lt;a href="https://twitter.com/mjackson"&gt;Michael Jackson&lt;/a&gt; has a fantastic video (one of many) on this topic &lt;a href="https://www.youtube.com/watch?v=BcVAq3YFiuc"&gt;Never Write Another HoC&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thank you for reading. Have a good one! 👋&lt;/p&gt;

&lt;p&gt;Image credits: Photo by &lt;a href="https://unsplash.com/@rgaleria?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Ricardo Gomez Angel&lt;/a&gt; &lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>React Router and nested routes</title>
      <dc:creator>Kevin Farrugia</dc:creator>
      <pubDate>Wed, 02 Feb 2022 09:50:40 +0000</pubDate>
      <link>https://dev.to/imkevdev/react-router-and-nested-routes-fmn</link>
      <guid>https://dev.to/imkevdev/react-router-and-nested-routes-fmn</guid>
      <description>&lt;p&gt;Cross-posted from &lt;a href="https://imkev.dev/react-router-nested-routes" rel="noopener noreferrer"&gt;https://imkev.dev/react-router-nested-routes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Following the public launch of &lt;a href="https://remix.run" rel="noopener noreferrer"&gt;Remix v1&lt;/a&gt;, nested routes have become all the rage - at least within my &lt;a href="https://twitter.com/ryanflorence/status/1486900658556919810?s=20&amp;amp;t=MpFoZDKR528EGisPFQ2Qfg" rel="noopener noreferrer"&gt;tiny corner of cyberspace&lt;/a&gt;. But what are nested routes, why are they meaningful, and how can you use nested routes in your React app?&lt;/p&gt;

&lt;h2&gt;
  
  
  React Router
&lt;/h2&gt;

&lt;p&gt;Nested routes have existed in &lt;a href="https://reactrouter.com/" rel="noopener noreferrer"&gt;React Router&lt;/a&gt; since very early on - heck, it was initially named &lt;a href="https://www.npmjs.com/package/react-nested-router" rel="noopener noreferrer"&gt;&lt;code&gt;react-nested-router&lt;/code&gt;&lt;/a&gt;. Now on version 6, React Router is one of the most popular React packages and will be used throughout this post to demonstrate the concept of nested routes. I will also include React Router v5 code samples and demos but, I will refer to the v6 version when explaining the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nested routes
&lt;/h2&gt;

&lt;p&gt;In my own words, a nested route is a region within a page layout that responds to route changes. For example, in a single-page application, when navigating from one URL to another, you do not need to render the entire page, but only those regions within the page that are dependent on that URL change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7451ph1rm96lb1u5wvq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7451ph1rm96lb1u5wvq.png" alt="Wireframe showing page layout consisting of three sections: the main layout (1), the navigation menu (2) the page contents (3) and the header (4)."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the wireframe above, when clicking on a header link (4), the main content (1) will be rendered to show the content for this route, while the header remains unchanged. Similarly, when clicking on the left navigation links (2), the page's content section (3) will update to show the new content, but the header, footer, and navigation menu remain unchanged.&lt;/p&gt;

&lt;p&gt;This layout could be implemented in several ways.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BrowserRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/catalog/:id"&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Catalog&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/catalog"&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Catalog&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/welcome"&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Welcome&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;index&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Home&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;BrowserRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://codesandbox.io/s/v6-yeb63?file=/src/App.jsx" rel="noopener noreferrer"&gt;Flat routing structure - v6&lt;/a&gt; | &lt;a href="https://codesandbox.io/s/v5-j9b0n?file=/src/App.jsx" rel="noopener noreferrer"&gt;Flat routing structure - v5&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above flat structure, we have four routes declared in a single file. &lt;code&gt;/catalog/:id&lt;/code&gt; and &lt;code&gt;/catalog&lt;/code&gt; would render the &lt;code&gt;&amp;lt;Catalog&amp;gt;&lt;/code&gt; component which includes the left navigation and the content area. If the &lt;code&gt;:id&lt;/code&gt; param is present, then it would show the content for that &lt;code&gt;:id&lt;/code&gt;, if not it would show some default content. &lt;code&gt;/welcome&lt;/code&gt; shows a welcome message and the final catch-all route shows the home page, including the &lt;code&gt;&amp;lt;Header&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;Footer&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Navigating between the different routes would cause the main section (1) to render with the updated content. This includes the &lt;code&gt;&amp;lt;Header&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Footer&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;Nav&amp;gt;&lt;/code&gt; - even if they are not changing. If you play around with the demo, you will probably feel that it works well, is snappy and there are no glaring bugs. This routing structure is fairly common and I have personally encountered it numerous times on production. However, this structure is not optimized and when navigating from one URL to another, the CPU is doing a lot of work that it doesn't need to. In our example this overhead is negligible, but on a more complex application, it may result in visible jank &amp;amp; deteriorate the user experience.&lt;/p&gt;

&lt;p&gt;To make re-renderings more apparent, I have added the following code snippet but initially left it commented out. If you are sensitive to flashing images, please use caution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  React.useLayoutEffect(() =&amp;gt; {
    if (ref &amp;amp;&amp;amp; ref.current) {
      ref.current.style = "background-color: #fa9a9a;";

      setTimeout(() =&amp;gt; {
        ref.current.style = "background-color: none;";
      });
    }
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Let's get nested
&lt;/h2&gt;

&lt;p&gt;The above routing structure could be optimized by using nested routes to avoid rendering components that have not changed. As a default rule, we only want to render what has changed. When a user clicks on the left navigation links, the only component we want to render is the content section. Similarly, when a user clicks on a header link, we only render the main section.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BrowserRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/welcome"&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Welcome&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"*"&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Header&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/catalog/*"&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"two-column"&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Nav&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;":id"&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;
                        &lt;span class="na"&gt;index&lt;/span&gt;
                        &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Use the left nav to selet a catalog item&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;index&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Home&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Footer&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;BrowserRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://codesandbox.io/s/nested-routes-v6-i92ds?file=/src/App.jsx" rel="noopener noreferrer"&gt;Nested routes (v6)&lt;/a&gt; | &lt;a href="https://codesandbox.io/s/nested-routes-v5-xegd8?file=/src/App.jsx" rel="noopener noreferrer"&gt;Nested routes (v5)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of having three routes on a single level, we now have six routes spread over three levels. At the topmost level, we have two routes, &lt;code&gt;path="*"&lt;/code&gt; and &lt;code&gt;path="/welcome"&lt;/code&gt;. These two routes were separated because the &lt;code&gt;&amp;lt;Header&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;Footer&amp;gt;&lt;/code&gt; are not visible on the &lt;code&gt;&amp;lt;Welcome&amp;gt;&lt;/code&gt; page.&lt;/p&gt;

&lt;p&gt;On the second level, we have two routes, &lt;code&gt;path="/catalog/*"&lt;/code&gt; and &lt;code&gt;index&lt;/code&gt;. These are used to render the &lt;code&gt;&amp;lt;Catalog&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;Home&amp;gt;&lt;/code&gt; respectively. As you can see in the code snippet above, the &lt;code&gt;&amp;lt;Header&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;Footer&amp;gt;&lt;/code&gt; are included in the &lt;code&gt;element&lt;/code&gt; attribute for &lt;code&gt;path="*"&lt;/code&gt; instead of being declared within &lt;code&gt;&amp;lt;Catalog&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;Home&amp;gt;&lt;/code&gt; as we had done in the flat-structure.&lt;/p&gt;

&lt;p&gt;Finally, on the inner-most level, there are two more routes. The first path exposes the &lt;code&gt;:id&lt;/code&gt; param with &lt;code&gt;path=":id"&lt;/code&gt;. Since this route is a nested route of &lt;code&gt;path="/catalog/*"&lt;/code&gt;, then the path is built onto its parent's, matching in &lt;code&gt;/catalog/:id&lt;/code&gt;. The &lt;code&gt;index&lt;/code&gt; route is used when no &lt;code&gt;:id&lt;/code&gt; is present.&lt;/p&gt;

&lt;p&gt;If you experiment with the &lt;a href="https://codesandbox.io/s/nested-routes-v6-xegd8?file=/src/Welcome.jsx" rel="noopener noreferrer"&gt;demo&lt;/a&gt;, you will see that each component is only rendered when needed, making this solution much more optimized than the one we saw earlier. I love it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Nested routes aren't a new concept. If I remember correctly, I was using some form of nested routes way back in 2009 on C#'s MVC framework (it's been a while so let me know if I'm mixing things up). Yet I still encounter cases when developers opt for a flat structure when nested routes would be the better solution. While I believe that nested routes could help you today, I expect that nested routes would become even more important in the near future, with concepts such as &lt;a href="https://jasonformat.com/islands-architecture/" rel="noopener noreferrer"&gt;Islands Architecture&lt;/a&gt; and frameworks like &lt;a href="https://remix.run" rel="noopener noreferrer"&gt;Remix&lt;/a&gt; gaining traction. Give it a go and you won't turn back.&lt;/p&gt;

&lt;p&gt;Thank you for reading &amp;amp; have a good one!&lt;/p&gt;

&lt;p&gt;Image credits: Photo by &lt;a href="https://unsplash.com/@jamie_morrison?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Jamie Morrison&lt;/a&gt; &lt;/p&gt;

</description>
      <category>react</category>
      <category>webperf</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <item>
      <title>Should you optimize every re-render?</title>
      <dc:creator>Kevin Farrugia</dc:creator>
      <pubDate>Tue, 07 Dec 2021 10:35:35 +0000</pubDate>
      <link>https://dev.to/imkevdev/should-you-optimize-every-re-render-56me</link>
      <guid>https://dev.to/imkevdev/should-you-optimize-every-re-render-56me</guid>
      <description>&lt;p&gt;Cross-posted from &lt;a href="https://imkev.dev/optimizing-rerenders"&gt;https://imkev.dev/optimizing-rerenders&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the more frequent discussions I have with my colleagues is whether we should be investing the effort to optimize a React re-render (re-render).&lt;/p&gt;

&lt;p&gt;React determines which components need to be re-rendered during the &lt;code&gt;render&lt;/code&gt; phase. During this phase, React traverses the &lt;code&gt;current&lt;/code&gt; Fiber tree and creates a list of &lt;a href="https://reactjs.org/docs/hooks-overview.html#effect-hook"&gt;effects&lt;/a&gt; that need to be applied to the Fiber nodes. The &lt;code&gt;current&lt;/code&gt; tree reflects the state of the application that was used to render the UI. As React processes effects, it clones the current tree and performs these updates on the &lt;code&gt;current&lt;/code&gt; tree, resulting in a new &lt;code&gt;workInProgress&lt;/code&gt; tree. Once all updates are processed, React will flush the &lt;code&gt;workInProgress&lt;/code&gt; tree to the DOM and this will become the &lt;code&gt;current&lt;/code&gt; tree. If you're interested in more detail, I cover the &lt;a href="https://dev.to/react-reconciliation-performance-measures"&gt;React Reconciliation&lt;/a&gt; algorithm in a separate post.&lt;/p&gt;

&lt;p&gt;A render is usually required whenever your props or state change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, if &lt;code&gt;data&lt;/code&gt; changes, then we need to re-render the component with the latest values so these changes are reflected on the screen. Since we know that the component's output is dependent on &lt;code&gt;data&lt;/code&gt;, if &lt;code&gt;data&lt;/code&gt; does not change, then there is no need to recalculate the output as that is also unchanged. This allows us to use &lt;a href="https://reactjs.org/docs/react-api.html#reactmemo"&gt;&lt;code&gt;React.memo&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://reactjs.org/docs/react-api.html#reactpurecomponent"&gt;&lt;code&gt;React.PureComponent&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What we &lt;em&gt;do not&lt;/em&gt; want, is to re-render the component when &lt;code&gt;data&lt;/code&gt; does not change. This is what I refer to as an &lt;em&gt;unnecessary re-render&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not all re-renders are bad
&lt;/h2&gt;

&lt;p&gt;Not all re-renders are equal. Some re-renders are more CPU intensive than others. You may debug React re-rendering using the &lt;a href="https://reactjs.org/docs/optimizing-performance.html#profiling-components-with-the-chrome-performance-tab"&gt;React Profiler&lt;/a&gt; Chrome extension.&lt;/p&gt;

&lt;p&gt;&lt;a href="/media/blog/rerendering.png" class="article-body-image-wrapper"&gt;&lt;img src="/media/blog/rerendering.png" alt="Chrome DevTools React Profiler showing two panels. Left panel shows components which have been re-rendered. Right panel shows time spent on each re-render" title="React Profiler"&gt;&lt;/a&gt; {.centered}&lt;/p&gt;

&lt;p&gt;The left column shows which components have been re-rendered, while the right column shows you how many times the component has re-rendered. Each re-rendering also includes the component's self-time - the time it takes to execute the &lt;code&gt;render()&lt;/code&gt; method for that component.&lt;/p&gt;

&lt;p&gt;In most cases, the time spent rendering each component is a few milliseconds. This has led to the argument that &lt;a href="https://mobile.twitter.com/iamakulov/status/1362397452884717571"&gt;not all unnecessary re-renders are bad&lt;/a&gt;; a statement I have to disagree with*.&lt;/p&gt;

&lt;p&gt;While not all re-renders are equally important, I believe that &lt;em&gt;all&lt;/em&gt; unnecessary re-renders should be eliminated to improve your applications reliability.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ClickCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Update counter&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Demo: &lt;a href="https://codesandbox.io/s/re-rendering-demo-cpo2g?file=/src/ClickCounter.js"&gt;/src/ClickCounter.js&lt;/a&gt; {.caption}&lt;/p&gt;

&lt;p&gt;Whenever &lt;code&gt;count&lt;/code&gt; is updated, &lt;code&gt;MyComponent&lt;/code&gt; will be re-rendered, even if it is not dependent on &lt;code&gt;count&lt;/code&gt;. This is caused as you are passing a new array reference on each render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The correct solution would be to create a constant and place it outside of the &lt;code&gt;ClickCounter&lt;/code&gt; component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ClickCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Update counter&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Demo: &lt;a href="https://codesandbox.io/s/re-rendering-demo-solution-k6p0z?file=/src/ClickCounter.js"&gt;/src/ClickCounter.js&lt;/a&gt; {.caption}&lt;/p&gt;

&lt;p&gt;This no longer renders &lt;code&gt;MyComponent&lt;/code&gt; whenever the user clicks on the &lt;code&gt;button&lt;/code&gt; to update &lt;code&gt;count&lt;/code&gt;. But how much faster is our application following this optimization? Most likely, the improvements are negligible. So does this mean you shouldn't bother optimizing your re-renders?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Demo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useLocation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Demo: &lt;a href="https://codesandbox.io/s/re-rendering-demo-bug-tbkhm?file=/src/Demo.js"&gt;/src/Demo.js&lt;/a&gt; { .caption }&lt;/p&gt;

&lt;p&gt;In the example above, we have two instances of &lt;code&gt;MyComponent&lt;/code&gt;; one which re-renders on each render and one which is correctly optimized. The &lt;code&gt;Demo&lt;/code&gt; itself component will render whenever &lt;code&gt;location&lt;/code&gt; changes, using the &lt;code&gt;useLocation&lt;/code&gt; hook from &lt;a href="https://reactrouter.com/"&gt;React Router&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In most cases, these two components will behave identically. But in the first &lt;code&gt;MyComponent&lt;/code&gt;, there is the premise for obscure bugs which would be hidden by causing the component to needlessly re-render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Demo: &lt;a href="https://codesandbox.io/s/re-rendering-demo-bug-tbkhm?file=/src/MyComponent.js"&gt;/src/MyComponent.js&lt;/a&gt; { .caption }&lt;/p&gt;

&lt;p&gt;If the rendered output of a component is dependent on more than its props, then needlessly re-rendering the component may hide this issue. In &lt;code&gt;MyComponent&lt;/code&gt;, the rendered output includes the &lt;code&gt;location.pathname&lt;/code&gt;, which would change whenever the URL changes. If the component does not re-render, then the updated &lt;code&gt;location.pathname&lt;/code&gt; would not be visible on the screen. As a result, the &lt;code&gt;MyComponent&lt;/code&gt; which needlessly re-renders would reflect this change on the next render, while the optimized component would not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useLocation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course in this example, we are simplifying things greatly and the issue is both easy to find and fix. However, from my experience, sometimes these bugs could go unnoticed for a very long time, making them very difficult to debug and eventually resolve.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other unnecessary re-renders
&lt;/h3&gt;

&lt;p&gt;There are other forms of unnecessary renders. Similar to the new array reference, passing an object or a function will cause the component to re-render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This could be mitigated by either placing the object outside of the component's render method or memoizing the prop using &lt;a href="https://reactjs.org/docs/hooks-reference.html#usememo"&gt;&lt;code&gt;React.useMemo&lt;/code&gt;&lt;/a&gt;. The latter is usually required if the prop is dependent on other prop or state variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt;
    &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React includes &lt;a href="https://reactjs.org/docs/hooks-reference.html#usecallback"&gt;&lt;code&gt;React.useCallback&lt;/code&gt;&lt;/a&gt; which returns a memoized callback function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onClickHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClickHandler&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passing a React component as a prop will have a similar effect.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Demo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Header&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And once again, the recommended solution is similar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Header&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Demo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Header&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While the performance improvements from optimizing every render may not always be significant, maintaining a &lt;a href="https://en.wikipedia.org/wiki/Pure_function"&gt;pure&lt;/a&gt; codebase makes your work more predictable. If the output of every component is dependent on its inputs, then you minimize the risk of unwanted side effects. And you also get good performance "out-of-the-box".&lt;/p&gt;

&lt;p&gt;Let me know what you think. 🤙&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommended Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://indepth.dev/posts/1008/inside-fiber-in-depth-overview-of-the-new-reconciliation-algorithm-in-react"&gt;Inside Fiber: in-depth overview of the new reconciliation algorithm in React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://indepth.dev/posts/1009/in-depth-explanation-of-state-and-props-update-in-react"&gt;In-depth explanation of state and props update in React&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;*&lt;em&gt;&lt;a href="https://mobile.twitter.com/iamakulov"&gt;Ivan Akulov&lt;/a&gt; is an expert on web performance and I recommend reading &lt;a href="https://3perf.com/"&gt;his work&lt;/a&gt;. This is by no means an attempt at bashing a colleague's work.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@malcoo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Tomáš Malík&lt;/a&gt; on &lt;a href="https://unsplash.com/t/nature?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>performance</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Getting your HTTP Cache-Control headers right</title>
      <dc:creator>Kevin Farrugia</dc:creator>
      <pubDate>Mon, 29 Nov 2021 14:04:12 +0000</pubDate>
      <link>https://dev.to/imkevdev/getting-your-http-cache-control-headers-right-32m9</link>
      <guid>https://dev.to/imkevdev/getting-your-http-cache-control-headers-right-32m9</guid>
      <description>&lt;p&gt;Cross-posted from &lt;a href="https://imkev.dev/cache-control"&gt;https://imkev.dev/cache-control&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Caching plays a fundamental role in performance. What's quicker than a fast request? No request. Getting your caching strategy right can make a huge difference to your users - both repeat &lt;em&gt;and&lt;/em&gt; first time.&lt;/p&gt;

&lt;p&gt;"There are only two hard things in Computer Science: cache invalidation and naming things." (&lt;a href="http://www.tbray.org/ongoing/When/200x/2005/12/23/UPI"&gt;Phil Karlton&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;25 years later, this well-known saying still holds true and while I cannot help you with the naming, I want to share what I know about caching to make it easier for you to decide on a caching strategy. Disclaimer: The scope of this article isn't to serve as a comprehensive guide to all possible caching strategies and how they work - there's already plenty of content like that around. My goal is to provide you with a reference which you could use to answer the question, "How should I cache &lt;em&gt;this&lt;/em&gt; resource?"&lt;/p&gt;

&lt;h2&gt;
  
  
  What is caching?
&lt;/h2&gt;

&lt;p&gt;A cache is a store where you could put a resource. This could be done to avoid having to recalculate an expensive computation or to place the content closer to the user. In websites, this is dictated by the &lt;code&gt;Cache-Control&lt;/code&gt; header; which is defined in the &lt;a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13"&gt;HTTP/1.1 specification&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: The &lt;code&gt;Expires&lt;/code&gt; header is no longer needed as its behavior is covered by the &lt;code&gt;Cache-Control&lt;/code&gt; header.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Private and shared caches
&lt;/h2&gt;

&lt;p&gt;In addition to caching in your browser, if your content is behind a CDN then your &lt;code&gt;cache-control&lt;/code&gt; headers influence how the CDN caches your content on the edge. Browser cache is referred to as a &lt;em&gt;private&lt;/em&gt; cache, while a CDN cache is referred to as a &lt;em&gt;shared&lt;/em&gt; cache. The cacheability of a resource is set using the directives below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;public&lt;/code&gt; - Any cache may store the response, including a CDN.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;private&lt;/code&gt; - The response is intended for a single user and should only be stored by the browser cache.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;no-store&lt;/code&gt; - Should not be stored on any cache.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;To test the different &lt;code&gt;cache-control&lt;/code&gt; headers, I have created a repository containing a simple NodeJS server. Please feel free to explore the source code on &lt;a href="https://github.com/kevinfarrugia/cache-control/"&gt;GitHub&lt;/a&gt; and run the application locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static assets
&lt;/h2&gt;

&lt;p&gt;Static assets refer to files whose contents do not change and are not generated on request. This includes scripts, stylesheets, and images. As these files are generated at build time, most modern build tools can assign a unique hash to each file. This hash serves as a unique fingerprint for each version of the file and is included in the resource's URL. This could be in the form of a query string parameter (e.g. &lt;code&gt;app.js?v=c4d27698&lt;/code&gt;), or filename (e.g. &lt;code&gt;index-0e6a410d.js&lt;/code&gt;). Having a unique URL means that you can cache these assets for a very long time, even up to one year.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cache-control: max-age=31536000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the website is redeployed and the contents of one of the source files have changed, then it will be assigned a new URL and create a new cache entry. If the files are served through a CDN, then the CDN will cache this file. Most CDNs will purge the old files on each redeployment.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Freshness - Guaranteed.&lt;/li&gt;
&lt;li&gt;Performance - First user to request the file will receive it from the origin server. Every other user will receive a cached copy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Caching the HTML page
&lt;/h2&gt;

&lt;p&gt;One of the major headaches with caching is your HTML page. Generally speaking, your HTML page will make requests for other resources which are needed to render the page, such as CSS, images and JavaScript files. Whenever your website is redeployed, it will update the references to the static assets within the HTML document.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/style.v1.css"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;becomes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/style.v2.css"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So if the HTML document is cached, users with a cached copy will request the old stylesheet, &lt;code&gt;style.v1.css&lt;/code&gt;; which no longer exists on the origin server. So while &lt;code&gt;style.v1.css&lt;/code&gt; is likely to be cached on the user's browser because of its long expiry, it is possible that some users encounter a broken website too. If the cached resource &lt;code&gt;style.v1.css&lt;/code&gt; is removed from the cache before the cached HTML resource, the user will see a broken layout.&lt;/p&gt;

&lt;p&gt;To complicate matters, your HTML may also contain server-side rendered content retrieved from a CMS. If the content is updated on the CMS, the cached HTML is now stale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scenarios
&lt;/h2&gt;

&lt;p&gt;When deciding your caching strategy, it is usually a trade-off between performance and freshness. Instead of explaining the different &lt;code&gt;cache-control&lt;/code&gt; directives and their applications, I will be describing some real-life scenarios I worked with and how I would set my &lt;code&gt;cache-control&lt;/code&gt; headers for that type of website.&lt;/p&gt;

&lt;h3&gt;
  
  
  Blog
&lt;/h3&gt;

&lt;p&gt;If you are looking to cache your blog, the chances are that the content is not time-sensitive and you would prioritize performance over freshness. Users are more likely to go directly to the article page instead of navigating through the website. If they revisit your blog, they are likely to return when a new article is published - that is after the cache has expired. The CSS and JavaScript files probably do not change that often either.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cache-control: public, max-age=600, stale-while-revalidate=60
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The blog you're reading uses a &lt;code&gt;public&lt;/code&gt;, &lt;code&gt;max-age&lt;/code&gt;, and &lt;code&gt;stale-while-revalidate&lt;/code&gt; combination. By applying a &lt;code&gt;max-age&lt;/code&gt; of 600 (10 minutes), you can cache the page for the duration of the user's session. If they leave the page and return within 10 minutes, it would load instantly.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;public&lt;/code&gt; directive states that the resource may be cached on both private and shared caches. Therefore if the resource has expired in the user's browser cache, it would request it from the CDN. The CDN may have the resource cached and serve it instantly. If it has expired on the CDN, then it would fetch it from the origin and update the caches.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;stale-while-revalidate&lt;/code&gt; means that the resource can be served stale for an additional 60 seconds after it has expired while it is being revalidated.&lt;/p&gt;

&lt;p&gt;In my specific case I am able to cache the HTML file rather aggressively as I ship very little JavaScript - none of which is critical to the user experience - and the critical CSS is inlined in the HTML file. Depending on how important your subresources are to the user experience, you may want to cache for a shorter period. If your blog does not work at all without JavaScript, then you might want to reduce the &lt;code&gt;max-age&lt;/code&gt; to avoid the race condition described earlier.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Freshness - Users may receive a worst-case 11-minute old response.&lt;/li&gt;
&lt;li&gt;Performance - The first user to request the resource will wait for it to be fetched from the origin. If the user returns within 11 minutes, they will receive a cached response. If they return after 11 minutes, they will be served a cached copy from the CDN. If no users visit the website for 11 minutes, the first user to visit the website will wait for the resource to be fetched from the origin.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  News website
&lt;/h3&gt;

&lt;p&gt;A news website is updated frequently, with new articles being added to the home page and the content of some articles updated several times per day.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cache-control: public, max-age=30, stale-while-revalidate=30, stale-if-error=600
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By applying a combination of &lt;code&gt;max-age&lt;/code&gt;, &lt;code&gt;stale-while-revalidate&lt;/code&gt;, and &lt;code&gt;stale-if-error&lt;/code&gt; you can always serve content quickly while minimizing the risk of stale data. Resources will be cached on shared or private caches for 30 seconds. When the resource expires, the cache will serve the stale data for another 30 seconds. The &lt;code&gt;stale-if-error&lt;/code&gt; directive indicates that if the origin server does not respond when revalidating the resource, the cache may serve the stale data for another 10 minutes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: The &lt;code&gt;stale-if-error&lt;/code&gt; directive isn't widely &lt;a href="https://caniuse.com/mdn-http_headers_cache-control_stale-if-error"&gt;supported&lt;/a&gt; on the browser but is supported on most CDNs.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Freshness - In the worst case, the user may receive a 1-minute old response. The &lt;code&gt;max-age&lt;/code&gt; and &lt;code&gt;stale-while-revalidate&lt;/code&gt; values may be adjusted to calibrate this worst-case scenario.&lt;/li&gt;
&lt;li&gt;Performance - The first user to request the resource will wait for it to be fetched from the origin. If the same user or any other user revisits the page within 30 seconds, they would get a cached response. If they visit the page beyond 30 seconds but within 60 seconds, then they would get an instant (stale) response while the cache is revalidated. If they revisit the page beyond 60 seconds, then the resource is fetched from the CDN. If no user visits the page for 1 minute, the next user will fetch the resource from the origin.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Live event
&lt;/h3&gt;

&lt;p&gt;If your website is showing a live event and content is updated frequently, you want the data to be as fresh as possible. An example of a live event may be a sports match showing real-time scores or an election results page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cache-control: public, no-cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setting &lt;a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1"&gt;&lt;code&gt;no-cache&lt;/code&gt;&lt;/a&gt; indicates that a cache must not be used for a subsequent request without revalidating it with the origin server. This is the equivalent of &lt;code&gt;must-revalidate, max-age=0&lt;/code&gt;. Once again, setting &lt;code&gt;public&lt;/code&gt; will enable your CDN to cache the resource and avoid hitting your origin server for each user request.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Freshness - Users will always receive a fresh resource.&lt;/li&gt;
&lt;li&gt;Performance - Each request will incur a network call. If the resource has not changed, then the payload would only include the response headers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Logged-in pages
&lt;/h3&gt;

&lt;p&gt;Any page or resource which is only available for a logged-in user or contains data specific to a logged-in session should not be cached.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cache-control: no-store
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Freshness - Users will always receive a fresh resource.&lt;/li&gt;
&lt;li&gt;Performance - Each request will be fetched from the origin.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;HTTP Cache-Control headers remain a cornerstone for good performance. When choosing a caching strategy, take your time to consider the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not all resources are equal.&lt;/li&gt;
&lt;li&gt;Measure the performance gains a user would benefit from if you cache a resource.&lt;/li&gt;
&lt;li&gt;Can you get away with serving stale content?&lt;/li&gt;
&lt;li&gt;Identify how likely your cached resources may become out of sync and what your users would experience in that eventuality.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recommended reading
&lt;/h2&gt;

&lt;p&gt;There is a lot of content explaining how the different &lt;code&gt;cache-control&lt;/code&gt; directives work. Below are some of my favorite resources on the topic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jakearchibald.com/2016/caching-best-practices/"&gt;Caching best practices &amp;amp; max-age gotchas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/love-your-cache/"&gt;Love your cache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://csswizardry.com/2019/03/cache-control-for-civilians/"&gt;Cache-Control for Civilians&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=3XkU_DXcgl0"&gt;Remix Run - Introduction to HTTP Caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=bfLFHp7Sbkg"&gt;CDN Caching, Static Site Generation, and Server Side Rendering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching"&gt;HTTP caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.cloudflare.com/cache/about/cache-control"&gt;Origin Cache Control&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jakearchibald.com/2020/multiple-versions-same-time/"&gt;Different versions of your site can be running at the same time&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@rresenden?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Ricardo Resende&lt;/a&gt; on &lt;a href=""&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>performance</category>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Code-splitting is hard</title>
      <dc:creator>Kevin Farrugia</dc:creator>
      <pubDate>Tue, 17 Nov 2020 11:02:47 +0000</pubDate>
      <link>https://dev.to/imkevdev/code-splitting-is-hard-4hgc</link>
      <guid>https://dev.to/imkevdev/code-splitting-is-hard-4hgc</guid>
      <description>&lt;p&gt;Occasionally code-splitting and chunking is avoided as a performance optimisation because it is thought of as complex or "black-magic". I hope to address those fears, because in most cases code-splitting could be done with relative ease and may reward you with considerable gains; especially for apps which are heavily reliant on JavaScript.&lt;/p&gt;

&lt;p&gt;The hardest part about code-splitting may be deciding on &lt;em&gt;how&lt;/em&gt; to split your code &amp;amp; bundles. This is not convered in this article, but there is lots of material on this topic. You may want to read: &lt;a href="https://web.dev/granular-chunking-nextjs/"&gt;Improved Next.js and Gatsby page load performance with granular chunking&lt;/a&gt; or &lt;a href="https://medium.com/hackernoon/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758"&gt;The 100% correct way to split your chunks with Webpack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code for this demo is available on &lt;a href="https://github.com/kevinfarrugia/code-splitting-demo"&gt;GitHub&lt;/a&gt;. Contributions &amp;amp; feedback are always welcome.&lt;/p&gt;

&lt;p&gt;The demo is built using Webpack and ReactJS, using &lt;code&gt;React.lazy&lt;/code&gt; &lt;a href="https://reactjs.org/docs/code-splitting.html#route-based-code-splitting"&gt;route-based code-splitting&lt;/a&gt; and &lt;a href="https://reactrouter.com/web/guides/quick-start"&gt;react-router-dom&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Will stylesheets be bundled in separate chunks?
&lt;/h2&gt;

&lt;p&gt;If one or more stylesheets are imported in a single module or its dependencies, then a reference to the bundled stylesheet will only be included in that module's chunk. For clarity, a chunk may consist of more than one file (JS &amp;amp; CSS).&lt;/p&gt;

&lt;p&gt;In our example, &lt;a href="https://github.com/kevinfarrugia/code-splitting-demo/blob/master/src/js/components/page1/index.jsx"&gt;&lt;strong&gt;Page1&lt;/strong&gt;&lt;/a&gt; imports a stylesheet:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  import styles from "./style.scss";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As it is the only file which references this stylesheet, then it will be chunked. Additionally, &lt;strong&gt;Page1&lt;/strong&gt; is the only module which imports the &lt;a href="https://github.com/kevinfarrugia/code-splitting-demo/blob/master/src/js/components/glider/index.jsx"&gt;&lt;strong&gt;Glider&lt;/strong&gt;&lt;/a&gt; component; which in turn imports another two stylesheets and also has a dependency on the third-party &lt;a href="https://github.com/NickPiscitelli/Glider.js"&gt;glider-js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;src/js/components/glider/index.jsx&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  import "glider-js";
  import "glider-js/glider.min.css";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;All these will be included in a single chunk, together with the output of &lt;code&gt;style.scss&lt;/code&gt; above.&lt;/p&gt;

&lt;p&gt;On the contrary, if a stylesheet is imported in more than one module, then the bundler will output a single stylsheet referenced by both modules.&lt;/p&gt;

&lt;p&gt;In our example, &lt;a href="https://github.com/kevinfarrugia/code-splitting-demo/blob/master/src/js/components/page2/index.jsx"&gt;&lt;strong&gt;Page2&lt;/strong&gt;&lt;/a&gt; imports a shared stylesheet:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  import sharedStyles from "../home/style.scss";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This stylesheet is also imported in the &lt;a href="https://github.com/kevinfarrugia/code-splitting-demo/blob/master/src/js/components/home/index.jsx"&gt;&lt;strong&gt;Home&lt;/strong&gt;&lt;/a&gt; module and therefore is not included in the &lt;strong&gt;Page2&lt;/strong&gt; chunk.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about images?
&lt;/h2&gt;

&lt;p&gt;By design, images are only downloaded when needed and present in the DOM. This means that images should have no impact on your bundle sizes.&lt;/p&gt;

&lt;p&gt;If you are importing your images using file-loader's &lt;a href="https://webpack.js.org/loaders/file-loader/#esmodule"&gt;&lt;code&gt;esModule&lt;/code&gt;&lt;/a&gt; then you will also benefit from module concatenation and tree-shaking on your images; but this is not specifically code-splitting.&lt;/p&gt;

&lt;p&gt;However, if you are using &lt;a href="https://webpack.js.org/loaders/url-loader/"&gt;url-loader&lt;/a&gt; and your images are being encoded into Base64 or SVG strings, then they will be encoded into each chunk resulting in duplicate code.&lt;/p&gt;

&lt;h2&gt;
  
  
  May I use CommonJS imports?
&lt;/h2&gt;

&lt;p&gt;Yes, CommonJS &amp;amp; ES6 module imports work equally well.&lt;/p&gt;

&lt;p&gt;In our example, in &lt;strong&gt;Page2&lt;/strong&gt; the below two lines would result in equivalent chunks:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const styles = require("./style.scss");
  //import stylesfrom "./style.scss");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  When using route-based code-splitting, is it possible to have some routes lazy-loaded while others loaded regularly?
&lt;/h2&gt;

&lt;p&gt;Yes, definitely.&lt;/p&gt;

&lt;p&gt;In this demo, the &lt;strong&gt;Home&lt;/strong&gt; module is loaded regularly while the other pages are loaded lazily.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  import Home from "../home";
  const Page1 = React.lazy(() =&amp;gt; import("../page1"));
  const Page2 = React.lazy(() =&amp;gt; import("../page2"));

  &amp;lt;Suspense fallback={null}&amp;gt;
    &amp;lt;Switch&amp;gt;
      &amp;lt;Route path="/1" exact&amp;gt;
        &amp;lt;Page1 /&amp;gt;
      &amp;lt;/Route&amp;gt;
      &amp;lt;Route path="/2" exact&amp;gt;
        &amp;lt;Page2 /&amp;gt;
      &amp;lt;/Route&amp;gt;
      &amp;lt;Route&amp;gt;
        &amp;lt;Home /&amp;gt;
      &amp;lt;/Route&amp;gt;
    &amp;lt;/Switch&amp;gt;
  &amp;lt;/Suspense&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Does code-splitting work with named exports?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;React.lazy&lt;/code&gt; requires you to have a default export, however you may still use named exports for other components, even for those which are being referenced by the lazily loaded component.&lt;/p&gt;
&lt;h2&gt;
  
  
  What about re-exporting? Will &lt;code&gt;export * from "./my-module"&lt;/code&gt; be tree-shaken?
&lt;/h2&gt;

&lt;p&gt;Using &lt;code&gt;export * from "./my-module"&lt;/code&gt; means that any export in &lt;strong&gt;./my-module&lt;/strong&gt;, regardless of whether it is used or unused, would need to be evaluated and executed in case one of those exports has side-effects. As a result, you need to explicitly inform Webpack that the file has no side-effects using the &lt;code&gt;sideEffects&lt;/code&gt; &lt;strong&gt;package.json&lt;/strong&gt; property. Sean Larkin has an excellent explanation on &lt;a href="https://stackoverflow.com/a/49203452/2315681"&gt;Stack Overflow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The example code in our demo includes a component &lt;strong&gt;Page3&lt;/strong&gt; which exports an unused component &lt;strong&gt;../glider-named-export&lt;/strong&gt;. Without &lt;code&gt;sideEffects: false&lt;/code&gt;, the resultant chunk includes the contents of &lt;strong&gt;../glider-named-export&lt;/strong&gt;, even if it is never actually being used.&lt;/p&gt;
&lt;h2&gt;
  
  
  Does this work with critical (inlined) CSS?
&lt;/h2&gt;

&lt;p&gt;Yes it does.&lt;/p&gt;

&lt;p&gt;The configuration used in this demo inlines a single critical CSS file which includes all critical CSS defined across the project. This is done using the following code inside &lt;strong&gt;scripts/webpack.config.js&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;criticalStyles: {
  name: "critical",
  test: /critical\.(sa|sc|c)ss$/,
  chunks: "initial",
  enforce: true,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The output of this chunk is then inlined in &lt;strong&gt;src/templates/index.hbs&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;% if (/critical(\..*)?\.css$/.test(htmlWebpackPlugin.files.cssindex])) { %&amp;gt;
  &amp;lt;style&amp;gt;
    &amp;lt;%= compilation.assets[htmlWebpackPlugin.files.cssindex].substr(htmlWebpackPlugin.files.publicPath.length)].source() %&amp;gt;
  &amp;lt;/style&amp;gt;
&amp;lt;% } %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Will users have to wait to download the chunks on successive routes?
&lt;/h2&gt;

&lt;p&gt;In theory yes, because these files were not downloaded yet and will only be downloaded once the user requests them by visiting the page; but this could be mitigated through the use of a service-worker precache which will download the remaining chunks after the initial page load.&lt;/p&gt;

&lt;p&gt;In the demo I am using the highly recommended &lt;a href="https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin"&gt;WorkboxPlugin&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new WorkboxPlugin.InjectManifest({
  swSrc: `${ROOT_DIR}/src/sw.js`,
  swDest: "sw.js",
  include: [/\.js$/, /\.css$/],
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;Thank you for reading and please leave me your feedback. As always, it would be very welcome &amp;amp; appreciated. If you want to get in touch, you could reach me on Twitter &lt;a href="https://twitter.com/imkevdev"&gt;@imkevdev&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webperf</category>
      <category>react</category>
      <category>codenewbie</category>
      <category>webpack</category>
    </item>
    <item>
      <title>Loading CSS - Web Performance Cheatsheet</title>
      <dc:creator>Kevin Farrugia</dc:creator>
      <pubDate>Fri, 25 Sep 2020 12:23:04 +0000</pubDate>
      <link>https://dev.to/imkevdev/loading-css-web-performance-cheatsheet-2kgc</link>
      <guid>https://dev.to/imkevdev/loading-css-web-performance-cheatsheet-2kgc</guid>
      <description>&lt;p&gt;As part of my role as a web performance consultant, I constantly need to test two (or more) versions of a website and compare the resultant performance. Since performance isn't a single clearly defined metric and is comprised of a host of other metrics, each measuring different aspects of the loading experience, including page load, start render, &lt;a href="https://web.dev/lcp"&gt;LCP&lt;/a&gt; (largest contenful paint), &lt;a href="https://web.dev/fcp"&gt;FCP&lt;/a&gt; (first contentful paint), &lt;a href="https://web.dev/fid"&gt;FID&lt;/a&gt; (first input delay), &lt;a href="https://web.dev/cls"&gt;CLS&lt;/a&gt; (cumulative layout shift)...etc; very often the tests don't have a clear and absolute winner, &lt;strong&gt;"This is the fastest!"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is not a &lt;a href="https://medium.com/firebase-developers/how-fast-should-your-site-load-cfb14be48e8b"&gt;unique problem&lt;/a&gt; to the website I am working on. As your users are likely to be distributed over a wide range of devices &amp;amp; varying network conditions, what might improve the performance for one user may degrade it for another. There are other factors too, for example some websites may have a larger segment of users visiting the website in Incognito or Private Browsing. Ultimately, to get the most accurate picture of your users' experience, you should make use of RUM (Real User Metrics). If your website receives enough visitors, you can access this data on &lt;a href="https://web.dev/chrome-ux-report-data-studio-dashboard/"&gt;Chrome UX Report&lt;/a&gt;. If not, you would need to collect this data yourself using tools such as &lt;a href="https://speedcurve.com/"&gt;SpeedCurve&lt;/a&gt; (paid) or Google Analytics.&lt;/p&gt;

&lt;p&gt;This does not discard the importance of lab tests and very often, well-prepared tests can give a good indication of the expected behaviour for real-users once the changes are deployed to the production environment. On occassion, I also need to re-evaluate some decisions which were taken weeks or months earlier; sometimes due to the evolution of business requirements but more commonly due to changes to the website's code (ex: shipping more JavaScript, less images...etc). I therefore felt the need to create a reference which helps address my two needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Remind me how each test compares to another.&lt;/li&gt;
&lt;li&gt;  Helps me explain why one solution was preferred over another and why the preferred solution may have or have not changed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Loading CSS
&lt;/h2&gt;

&lt;p&gt;I created a &lt;a href="https://github.com/kevinfarrugia/performance-test-results-cheatsheet"&gt;GitHub repository&lt;/a&gt; where I will be adding different test cases together with sample code &amp;amp; test results from &lt;a href="https://webpagetest.org/"&gt;WebPageTest&lt;/a&gt;. Please feel free to contribute &amp;amp; leave feedback. The repository is also deployed on &lt;a href="https://kevinfarrugia.github.io/performance-test-results-cheatsheet/"&gt;kevinfarrugia.github.io/performance-test-results-cheatsheet&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Initially I only have a number of test cases where I compare the performance of different strategies to load CSS assets.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Inline CSS&lt;/strong&gt; - Instead of only inlining the critical CSS, all the webpage's CSS is combined into a single CSS file of 22.0KB. Consequently, there are no requests for external CSS files.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Render-blocking CSS&lt;/strong&gt; - Possibly the most "old school" way of loading CSS from the test cases. The CSS is combined into a single 22.0KB file and downloaded using an ordinary &lt;code&gt;&amp;lt;link rel="stylesheet" type="text/css" href="main.css" /&amp;gt;&lt;/code&gt; placed inside the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Inline critical CSS&lt;/strong&gt; - Only 1.4KB of critical CSS (used above-the-fold) is inlined inside the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; while the remaining 21.4KB of CSS (&lt;code&gt;bottom.css&lt;/code&gt;) is downloaded asynchronously using the &lt;a href="https://www.filamentgroup.com/lab/load-css-simpler/"&gt;media="print"&lt;/a&gt; trick. The remaining CSS also contains some minor styling which marginally impacts the view above the fold.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Inline critical CSS &amp;amp; preload&lt;/strong&gt; - Similarly to above, except the remaining 21.4KB of CSS are preloaded using the resource hint &lt;code&gt;&amp;lt;link rel="preload" href="bottom.css" as="style" /&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;preload to render-blocking CSS&lt;/strong&gt; - Similarly to the render-blocking test case above, except the CSS file &lt;code&gt;main.css&lt;/code&gt; is preloaded using &lt;code&gt;&amp;lt;link rel="preload" href="main.css" as="style" /&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Test Results
&lt;/h2&gt;

&lt;p&gt;All tests were done using the Moto G4 - Chrome - 3G Fast browser preset on WPT. You may follow this &lt;a href="https://webpagetest.org/video/compare.php?tests=200917_A5_5a1f37b7504016d8d68544993c45725f,200917_G4_e26b6bc976d5b7597a8d96e330e0a398,200917_Q0_6a9acb4c84a916ebf638e84c1ae4121c,200917_GZ_b3173efc8d50e22ff7f70319516ea930,200917_14_9e296ac27507f0d75281b11859c869dc"&gt;link&lt;/a&gt; to access the data behind the test results described below.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/461826673" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;As seen in the video above, the first pages to show any content are the &lt;em&gt;inline-critical-css&lt;/em&gt; and &lt;em&gt;inline-css&lt;/em&gt; and as a result they are the quickest to Start Render.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u277Rw3b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dk90p8fgv6nbr.cloudfront.net/media/blog/css-loading-time-to-start-render.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u277Rw3b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dk90p8fgv6nbr.cloudfront.net/media/blog/css-loading-time-to-start-render.png" alt="Time to Start Render"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Interestingly, the page which inlines all the webpage's CSS still performs at-par with the one which only inlines the critical CSS, even if it needs to download more HTML (24.6KB). It is recommended to keep the initial HTML file under 14KB because of TCP's &lt;a href="https://hpbn.co/building-blocks-of-tcp/#slow-start"&gt;slow start&lt;/a&gt;, however we do not see that as holding true for our tests. 🤷&lt;/p&gt;

&lt;p&gt;The next page to start rendering content to screen is the preload-inline-critical-css, slightly behind the equivalent without preloading &lt;code&gt;bottom.css&lt;/code&gt;. Taking a look at the waterfall, it is clear that the cause for this delay is the preloaded file taking priority over critical resources, in this case the JavaScript file &lt;code&gt;critical.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pai4YxJ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dk90p8fgv6nbr.cloudfront.net/media/blog/loading-css-preload-inline-critical-css-waterfall.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pai4YxJ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dk90p8fgv6nbr.cloudfront.net/media/blog/loading-css-preload-inline-critical-css-waterfall.png" alt="Waterfall for inline critical CSS &amp;amp; preload"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the meantime, the first page with all CSS inlined has downloaded the image and is visually complete. A few milliseconds later, render-blocking-css paints to the screen for the first and last time. Therefore, when compared to inlining CSS (critical or all), it takes significantly longer to begin painting to screen and as a result the user is unaware if the page is loading and cannot see any content until all HTML &amp;amp; CSS is downloaded &amp;amp; parsed (images may still load afterwards).&lt;/p&gt;

&lt;p&gt;The identical same results are observed for the preload-render-blocking-css page because the CSS file is already located in the head and treated with HIGHEST priority, therefore preloading it will not give you and performance improvements. In the video, it is coincidentally slightly slower because of a slower TTFB of the server; which is unrelated to the test itself. Successive tests registered identical results as without the &lt;code&gt;preload&lt;/code&gt; hint.&lt;/p&gt;

&lt;p&gt;And finally the inline-critical-css page is visually complete once the &lt;code&gt;bottom.css&lt;/code&gt; is downloaded and applied. As a result, this page is the one which incurs the largest (albeit not significant) layout shift and scores the highest (lower is better) score for CLS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope you found these tests interesting and perhaps learnt something new. Personally I always like to test any hypothesis, even if it is something that I have been doing almost instinctively and then use the test results to understand why the page is faster or slower. Feel free to get in touch if you would like to contribute or suggest new tests, have feedback on the above or anything else web performance related really. Thank you for reading and stay safe.&lt;/p&gt;

</description>
      <category>webperf</category>
      <category>css</category>
    </item>
    <item>
      <title>Should I host two websites on a single domain?</title>
      <dc:creator>Kevin Farrugia</dc:creator>
      <pubDate>Wed, 05 Aug 2020 08:57:09 +0000</pubDate>
      <link>https://dev.to/imkevdev/should-i-host-two-websites-on-a-single-domain-53i1</link>
      <guid>https://dev.to/imkevdev/should-i-host-two-websites-on-a-single-domain-53i1</guid>
      <description>&lt;p&gt;I have two websites, one for mobile and one for desktop (i.e. this is not a responsive website). Both websites show similar (not identical) content for the same routes, so going to &lt;code&gt;/about-us&lt;/code&gt; for each site would show the same content (80-90% similar, main content identical but peripheral content might change) within a different HTML structure. &lt;/p&gt;

&lt;p&gt;Ordinarily, I would setup one website on &lt;code&gt;m.mydomain.com&lt;/code&gt; and the other on &lt;code&gt;mydomain.com&lt;/code&gt;. However we have been looking into using the same domain (no subdomains) for both websites.&lt;/p&gt;

&lt;p&gt;A load-balancer would send the traffic to the respective server based on the user-agent (to recognise mobile/desktop traffic). This might seem similar to what Amazon.com does (not aware of the internal workings)&lt;/p&gt;

&lt;p&gt;Is this setup a good idea or is it going to lead to problems? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An improved user experience (debatable)&lt;/li&gt;
&lt;li&gt;Possibly improved SEO as only a single website is indexed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Questions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Will there be caching issues since assets are different? What about service-workers?&lt;/li&gt;
&lt;li&gt;What about redirects? If one of the websites has a 301/302 redirect that is cached.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>webdev</category>
      <category>discuss</category>
    </item>
    <item>
      <title>React Reconciliation Rendering Order</title>
      <dc:creator>Kevin Farrugia</dc:creator>
      <pubDate>Mon, 03 Aug 2020 11:14:42 +0000</pubDate>
      <link>https://dev.to/imkevdev/react-reconciliation-rendering-order-6g0</link>
      <guid>https://dev.to/imkevdev/react-reconciliation-rendering-order-6g0</guid>
      <description>&lt;p&gt;Cross-posted from &lt;a href="https://imkev.dev/react-rendering-order"&gt;https://imkev.dev/react-rendering-order&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was recently asked to measure &amp;amp; track the performance of a React component (and all its sub-components) as part of a huge refactoring project the company had undertaken. In a nutshell, we wanted to track how long the component takes until its rendering is complete. Since the component was made up of a number of smaller sub-components, many of these connected to the Redux store and fetching data asynchronously, it was important to understand &lt;a href="https://dev.to/react-reconciliation-performance-measures"&gt;how the React rendering algorithm works&lt;/a&gt;. I have already written about my learning experience when measuring the time each component takes to render which goes into greater detail about the algorithm itself; while this blog post takes a very simplified and high-level overview of the order in which components are rendered and re-rendered using examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;To demonstrate the order in which React components are rendered, we have created a simple component tree and tagged each component with a unique ID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Component id="A0"&amp;gt;
  &amp;lt;Component id="B0" /&amp;gt;
  &amp;lt;Component id="B1"&amp;gt;
    &amp;lt;Component id="C0" /&amp;gt;
    &amp;lt;Component id="C1" /&amp;gt;
  &amp;lt;/Component&amp;gt;
  &amp;lt;Component id="B2" /&amp;gt;
&amp;lt;/Component&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By adding a &lt;code&gt;React.Profiler&lt;/code&gt; component to each &lt;code&gt;Component&lt;/code&gt; we are able to measure when each component renders. The sequence for the above component tree is&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; B0&lt;/li&gt;
&lt;li&gt; C0&lt;/li&gt;
&lt;li&gt; C1&lt;/li&gt;
&lt;li&gt; B1&lt;/li&gt;
&lt;li&gt; B2&lt;/li&gt;
&lt;li&gt; A0&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is because the React reconciliation algorithm follows a depth-first traversal to &lt;code&gt;beginWork&lt;/code&gt; and a component's rendering is complete (&lt;code&gt;completeWork&lt;/code&gt;) only once all its children's rendering is complete. As a result, the root component in your tree will always be the last one to complete render.&lt;/p&gt;

&lt;p&gt;You may experiment with the &lt;a href="https://codesandbox.io/s/react-rendering-bxguf"&gt;source code&lt;/a&gt; if you wish.&lt;/p&gt;

&lt;h2&gt;
  
  
  But what about connected components &amp;amp; async rendering?
&lt;/h2&gt;

&lt;p&gt;Very often (as was our case) components and sub-components are connected to Redux store or asynchronously fetching data from an API. In some cases, we are also using the &lt;a href="https://reactjs.org/docs/render-props.html"&gt;render prop&lt;/a&gt; technique, in which case data is fetched by a parent component and then passed down to its children. In these cases, how does the React reconciliation algorithm behave?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Component id="A0"&amp;gt;
  &amp;lt;Component id="B0" /&amp;gt;
  &amp;lt;Component id="B1"&amp;gt;
    &amp;lt;Component id="C0" /&amp;gt;
    &amp;lt;Component id="C1" /&amp;gt;
    &amp;lt;RenderProps id="C2" timeout={2000}&amp;gt;
      {prefix =&amp;gt; (
        &amp;lt;&amp;gt;
          {prefix &amp;amp;&amp;amp; (
            &amp;lt;Component id={`${prefix}D0`}&amp;gt;
              &amp;lt;Component id={`${prefix}E0`} /&amp;gt;
              &amp;lt;Component id={`${prefix}E1`} /&amp;gt;
            &amp;lt;/Component&amp;gt;
          )}
          &amp;lt;Component id={`${prefix}D1`} /&amp;gt;
        &amp;lt;/&amp;gt;
      )}
    &amp;lt;/RenderProps&amp;gt;
    &amp;lt;Container id="C3" timeout={1000}&amp;gt;
      &amp;lt;Component id="D2" /&amp;gt;
    &amp;lt;/Container&amp;gt;
  &amp;lt;/Component&amp;gt;
  &amp;lt;Component id="B2" /&amp;gt;
&amp;lt;/Component&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the above example, &lt;code&gt;Container&lt;/code&gt; simulates a component which fetches data asynchronously, while &lt;code&gt;RenderProps&lt;/code&gt; simulates a component which fetches data asynchronously and then passes this to its children as a prop (&lt;code&gt;prefix&lt;/code&gt;); some of which render conditionally based on its value (initially false). In both cases, the &lt;code&gt;timeout&lt;/code&gt; prop is used to define how long the asynchronous event would take until the data is "fetched" and it is only there for demonstration purposes as it has no impact on our test.&lt;/p&gt;

&lt;p&gt;Similarly to the previous example, we are able to determine when each component finishes rendering thorugh the use of &lt;code&gt;React.Profiler&lt;/code&gt;. Initially, the components will render based on the same rules as above, depth-first traversal and all children must complete render.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; B0&lt;/li&gt;
&lt;li&gt; C0&lt;/li&gt;
&lt;li&gt; C1&lt;/li&gt;
&lt;li&gt; D1&lt;/li&gt;
&lt;li&gt; C2&lt;/li&gt;
&lt;li&gt; D2&lt;/li&gt;
&lt;li&gt; C3&lt;/li&gt;
&lt;li&gt; B1&lt;/li&gt;
&lt;li&gt; B2&lt;/li&gt;
&lt;li&gt; A0&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After 1000ms, the component C3 should resolve its asynchronous event as its data is fetched. As a result, it is re-rendered, together with its parents nodes until A0. Therefore, the order of this re-render is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; C3&lt;/li&gt;
&lt;li&gt; B1&lt;/li&gt;
&lt;li&gt; A0&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note that only the parents of C3 are rendered, while its siblings and children do not re-render.&lt;/p&gt;

&lt;p&gt;Another 1000ms later and component C2 now resolves. Similarly to C3, its data is fetch and re-rendered. Additionally, it will also pass the render prop &lt;code&gt;prefix&lt;/code&gt; to its children and the conditional render is now truthy. The resultant render complete order is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; E0&lt;/li&gt;
&lt;li&gt; E1&lt;/li&gt;
&lt;li&gt; D0&lt;/li&gt;
&lt;li&gt; D1&lt;/li&gt;
&lt;li&gt; C2&lt;/li&gt;
&lt;li&gt; B1&lt;/li&gt;
&lt;li&gt; A0&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As can be seen, when using render props, in addition to having the parent components render, all children are re-rendered - with same rules as the each render, depth-first traversal and all children need to complete for the parent to complete.&lt;/p&gt;

&lt;p&gt;You may experiment with the &lt;a href="https://codesandbox.io/s/react-rendering-tr59s"&gt;source code&lt;/a&gt; for the above example too.&lt;/p&gt;

&lt;h2&gt;
  
  
  So which is the last render?
&lt;/h2&gt;

&lt;p&gt;Using the above information, we were able to confidently say that the entire component tree is ready from rendering when our root node (A0 in the example above) has rendered for the last time. Unless within a finite amount of time, measuring the "last" of anything is difficult as on each iteration you do not know if there will be a successive one. To solve this, we looked and imitated how &lt;a href="https://web.dev/lcp"&gt;Largest Contentful Paint&lt;/a&gt; works, as it has a similar challenge (how do you know an element is the largest if you don't know what's coming next?). Ultimately, the solution was relatively straightforward as we created a &lt;code&gt;performance.mark&lt;/code&gt; for each render of our root component. The last mark is the last render and each previous mark was the last render until that point.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;window.addEventListener("unload", () =&amp;gt; {
  // get the last performance.mark entry
  const data = performance.getEntriesByName("lastRender")[performance.getEntriesByName("lastRender").length - 1];
  // Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
  (navigator.sendBeacon &amp;amp;&amp;amp; navigator.sendBeacon('/analytics', data)) ||
      fetch('/analytics', {data, method: 'POST', keepalive: true});
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The final piece of the puzzle was to send this data to the performance monitoring tool we were using. In our case it is &lt;a href="https://speedcurve.com"&gt;SpeedCurve&lt;/a&gt;, which provides an API; but the same approach used by SpeedCurve works for Google Analytics or other RUM tools. Using the non-blocking &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon"&gt;sendBeacon()&lt;/a&gt; API on &lt;code&gt;unload&lt;/code&gt; and on history change (if your app is a SPA); you could POST the timings of the last &lt;code&gt;performance.mark&lt;/code&gt; to an endpoint.&lt;/p&gt;

&lt;p&gt;And that's a wrap 🌯. Thank you for reading and shout out to &lt;a href="https://twitter.com/@maxkoretskyi"&gt;@maxkoretskyi&lt;/a&gt; for his fantastic articles on the topic.&lt;/p&gt;

</description>
      <category>webperf</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Inlining Critical CSS</title>
      <dc:creator>Kevin Farrugia</dc:creator>
      <pubDate>Wed, 29 Jul 2020 10:12:11 +0000</pubDate>
      <link>https://dev.to/imkevdev/inlining-critical-css-415p</link>
      <guid>https://dev.to/imkevdev/inlining-critical-css-415p</guid>
      <description>&lt;p&gt;Cross-posted from: &lt;a href="https://imkev.dev/inlining-critical-css"&gt;https://imkev.dev/inlining-critical-css&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During a recent (highly recommended) talk by Addy Osmani as part of Chrome's &lt;a href="https://web.dev/live"&gt;web.dev/live&lt;/a&gt; event, Addy explains how Chloé optimised their website for performance and Google's core &lt;a href="https://web.dev/vitals"&gt;web vitals&lt;/a&gt;. There are a lot of great takeaways from the talk, some of which could be implemented into your own project relatively easily; however one technique stuck out slightly for me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To dynamically generate the critical CSS we developed a script that runs at build-time extracting all the CSS blocks containing the custom &lt;code&gt;critical: this&lt;/code&gt; property and inlining them in the head of the page. The inlined CSS rules are removed from the original CSS files, which are loaded with low priority using the media=’print’ technique.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The above is taken from the &lt;a href="https://medium.com/ynap-tech/optimizing-cls-and-lcp-on-chloe-com-8280a036122a"&gt;case study&lt;/a&gt; from Chloé’s engineering blog.&lt;/p&gt;

&lt;p&gt;The goal of inlining critical CSS is to prevent a flash of unstyled content (FOUC). CSS is a render-blocking resource, meaning that it needs to be downloaded and parsed to create the CSSOM. This is then combined with the DOM to create the render tree, which is used to layout the different elements and feed the paint process which ultimately outputs the pixels to the screen. Having a single large CSS file will delay the start render, as all CSS, regardless of whether it will be used or not will have to be downloaded. Inlining the CSS, will also avoid a network request to download the CSS file.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So can I inline all my CSS?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nope. You should try to keep your initial HTML + CSS under 14KB. &lt;a href="https://hpbn.co/building-blocks-of-tcp/#slow-start"&gt;Why?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, stylesheets do not support the &lt;code&gt;async&lt;/code&gt; attribute, as &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; do and a variety of different approaches to asynchronously downloading the stylesheets have been implemented. The simplest and widely supported approach is the &lt;a href="https://www.filamentgroup.com/lab/load-css-simpler/"&gt;&lt;code&gt;media="print"&lt;/code&gt;&lt;/a&gt; technique quoted earlier. It might seem ugly, but it works well.&lt;/p&gt;

&lt;p&gt;Therefore, given the following SCSS file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* this bit is critical */
.list {
  width: 100%;
  padding: 0;
  margin: 0;
}

/* this bit is not critical as it only shows after user interaction or is below the fold */
.list-item {
  position: relative;
  display: block;
  padding: 1em;
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);

  &amp;amp;:hover .remove {
    opacity: 1;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We would expect it to output critical CSS and a &lt;code&gt;media="print"&lt;/code&gt; link to the remaining stylesheet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;head&amp;gt;
  ...
  &amp;lt;style&amp;gt;.list {width: 100%; padding: 0; margin: 0;}&amp;lt;/style&amp;gt;
  &amp;lt;link rel="stylesheet" href="/style.css" media="print" onload="this.media='all'"&amp;gt;
&amp;lt;/head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  What's this magic?
&lt;/h2&gt;

&lt;p&gt;The Chloé engineering team developed a script that extract the CSS blocks marked with &lt;code&gt;critical: this&lt;/code&gt;. I have seen similar scripts which worked by extracting blocks prefixed by &lt;code&gt;// !critical&lt;/code&gt; or extracting CSS which is generated on the server-side as critical (in the case of universal applications). There are also npm modules which generate the critical CSS using &lt;a href="https://github.com/GoogleChrome/puppeteer"&gt;puppeteer&lt;/a&gt;, such as &lt;a href="https://github.com/pocketjoso/penthouse"&gt;penthouse&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But in most cases, I prefer something simpler and I am able to achieve the similarly good results through a simple &lt;a href="https://webpack.js.org/"&gt;webpack&lt;/a&gt;configuration using chunking and &lt;a href="https://github.com/jantimon/html-webpack-plugin"&gt;HtmlWebpackPlugin&lt;/a&gt;. For starters, I separate critical and non-critical CSS into two SCSS files. From experience, a module would either be critical or not (for example a hero banner may be treated as critical) and all its SCSS should belong in one file anyway. Webpack is then configured to extract all SCSS from files named &lt;code&gt;critical.scss&lt;/code&gt; into a separate chunk.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  optimization: {
    // ...
    splitChunks: {
      // ...
      cacheGroups: {
        criticalStyles: {
          name: "critical",
          test: /critical\.(sa|sc|c)ss$/,
          chunks: "initial",
          enforce: true,
        },
        // ...
      },
    },
    // ...
  }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The resultant CSS file (using &lt;a href="https://github.com/webpack-contrib/mini-css-extract-plugin"&gt;MiniCssExtractPlugin&lt;/a&gt;) then needs to be injected into our HTML using HtmlWebpackPlugin. This requires that HtmlWebpackPlugin is configured with the option &lt;code&gt;inject: false&lt;/code&gt; so that we can create our own HTML output. We then add a condition to output the contents of the chunk and thus inline our critical CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;% for (let index in htmlWebpackPlugin.files.css) { %&amp;gt;
  &amp;lt;% if (/critical(\..*)?\.css$/.test(htmlWebpackPlugin.files.css[index])) { %&amp;gt;
    &amp;lt;style&amp;gt;
        &amp;lt;%= compilation.assets[htmlWebpackPlugin.files.css[index].substr(htmlWebpackPlugin.files.publicPath.length)].source() %&amp;gt;
    &amp;lt;/style&amp;gt;
  &amp;lt;% } else { %&amp;gt;
    &amp;lt;link rel="stylesheet" href=&amp;lt;%= `${process.env.CDN_URL}${htmlWebpackPlugin.files.css[index]}` %&amp;gt; media="print" onload="this.media='all'"&amp;gt;
  &amp;lt;% } %&amp;gt;
&amp;lt;% } %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With relatively little effort, we are able to inline our critical CSS. This technique works both with CSS modules and not and can be easily added to an existent project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance-First React Template
&lt;/h2&gt;

&lt;p&gt;While writing this blog, I decided to clean up my Webpack configurations and build scripts to make them more accessible. This work is available in &lt;a href="https://github.com/kevinfarrugia/performance-first-react-template"&gt;Performance-first React Template&lt;/a&gt; and includes the critical CSS configuration described in this blog and much more if you would be interested in taking a look. Feedback is highly welcome, so feel free to reach out to me on &lt;a href="https://twitter.com/imkevdev/"&gt;@imkevdev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thank you for reading.&lt;/p&gt;

</description>
      <category>webperf</category>
      <category>webdev</category>
      <category>webpack</category>
    </item>
  </channel>
</rss>
