{"componentChunkName":"component---src-templates-tags-js","path":"/tags/performance/","result":{"data":{"allMarkdownRemark":{"totalCount":10,"edges":[{"node":{"id":"5a075de4-36f3-5743-b35b-23b50c63ac5f","html":"<p>You’ve spent many hours trying to improve your web performance and have got it to a good speed. What happens next? How do you ensure it remains in good shape especially if you’re working in a team with diverse backgrounds and level of coding.</p>\n<!--more-->\n<h2 id=\"web-performance-must-be-monitored\" style=\"position:relative;\"><a href=\"#web-performance-must-be-monitored\" aria-label=\"web performance must be monitored permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Web performance must be monitored</h2>\n<p>I truly believe web performance shouldn’t be an item in your backlog, rather part of acceptance criteria on each story. That said, having discipline is hard when it comes to web performance. Each member of the team should be aware of dos and don’ts so that they can right code which doesn’t add a few seconds to current page load time, or user’s interactivity with the page.</p>\n<p>In order to do so, you need to constantly monitor the performance of your application and when is a better time to do it than your CI/CD pipeline or when creating a pull request to get the code merged in (it’s worth mentioning having a CI/CD pipeline is not necessary to have a high quality, well written and performing site).</p>\n<p>In addition to all of that, your site performs differently from your localhost, so you need to ensure you’re testing close to your actual environment.</p>\n<h2 id=\"lighthouse-ci\" style=\"position:relative;\"><a href=\"#lighthouse-ci\" aria-label=\"lighthouse ci permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Lighthouse CI</h2>\n<p><a href=\"https://github.com/GoogleChrome/lighthouse-ci\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Lighthouse CI</a> is a set of commands that make continuously running, asserting, saving, and retrieving Lighthouse results as easy as possible.</p>\n<p>This is a great tool which allows you to run audits on your code base using command line, and raise an alert when someone unintentionally downgrades the performance.</p>\n<h2 id=\"what-to-measure\" style=\"position:relative;\"><a href=\"#what-to-measure\" aria-label=\"what to measure permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What to measure?</h2>\n<p>There are countless metrics on which we could focus on. Some are user centric like time to interact, some are resource centric such as the size of your <em>JavaScript</em> or <em>CSS</em> files. Lighthouse CI allows us to easily focus on the size of the files. You can create two types of budgets:</p>\n<p>1- <strong>Number of given resource</strong>: This will help you to for example enforce having only <code class=\"language-text\">3</code> <em>JavaScript</em> and <code class=\"language-text\">1</code> <em>CSS</em> file.\r\n2- <strong>Size of a given resource</strong>: This budget will enforce that a given resource is of certain size, e.g. only <code class=\"language-text\">500kb</code>.</p>\n<h2 id=\"how-does-it-know\" style=\"position:relative;\"><a href=\"#how-does-it-know\" aria-label=\"how does it know permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How does it know?</h2>\n<p>You’re probably wondering how does <strong>Lighthouse CI</strong> know what to measure and when to raise an alert. This **||is done via a <code class=\"language-text\">JSON</code> file which is usually named <code class=\"language-text\">budget.json</code>, but you can choose any name you prefer.</p>\n<h2 id=\"performance-budget\" style=\"position:relative;\"><a href=\"#performance-budget\" aria-label=\"performance budget permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Performance budget</h2>\n<p>The content of this file is an array of objects representing the budgets for a path. The content will look like below if you only have one path to assert:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"25649810326442734000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`[\r\n  {\r\n    &quot;resourceSizes&quot;: [\r\n      ...\r\n    ],\r\n    &quot;resourceCounts&quot;: [\r\n      ...\r\n    ]\r\n  }\r\n]`, `25649810326442734000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-json line-numbers\"><code class=\"language-json\"><span class=\"token punctuation\">[</span>\r\n  <span class=\"token punctuation\">{</span>\r\n    <span class=\"token property\">\"resourceSizes\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\r\n      ...\r\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token property\">\"resourceCounts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\r\n      ...\r\n    <span class=\"token punctuation\">]</span>\r\n  <span class=\"token punctuation\">}</span>\r\n<span class=\"token punctuation\">]</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>Within the <code class=\"language-text\">resourceSizes</code> and <code class=\"language-text\">resourceCounts</code> arrays, you can add individual objects that specify the <code class=\"language-text\">resourceType</code> and its budget. The budget can be any positive integer and the <code class=\"language-text\">resourceType</code> can be any of the following:</p>\n<table>\n<thead>\n<tr>\n<th><strong>Resource type</strong></th>\n<th><strong>Description</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>script</strong></td>\n<td>JavaScript files</td>\n</tr>\n<tr>\n<td><strong>document</strong></td>\n<td>HTML documents</td>\n</tr>\n<tr>\n<td><strong>image</strong></td>\n<td>Images</td>\n</tr>\n<tr>\n<td><strong>stylesheet</strong></td>\n<td>CSS files</td>\n</tr>\n<tr>\n<td><strong>font</strong></td>\n<td>Webfonts</td>\n</tr>\n<tr>\n<td><strong>media</strong></td>\n<td>Other media</td>\n</tr>\n<tr>\n<td><strong>other</strong></td>\n<td>Any other resource which doesn’t match the above, e.g. data transfers over Websocket connections</td>\n</tr>\n<tr>\n<td><strong>third-party</strong></td>\n<td>All resources from a third-party domain</td>\n</tr>\n<tr>\n<td><strong>total</strong></td>\n<td>All resources combined</td>\n</tr>\n</tbody>\n</table>\n<p>For example, the following file will set a 200Kb budget for all scripts, a 500Kb for all images, and a 500Kb for all other resources. Then it sets the total network requests to be 25.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"11276160670835433000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`[\r\n  {\r\n    &quot;resourceSizes&quot;: [\r\n      {\r\n        &quot;resourceType&quot;: &quot;script&quot;,\r\n        &quot;budget&quot;: 200\r\n      },\r\n      {\r\n        &quot;resourceType&quot;: &quot;image&quot;,\r\n        &quot;budget&quot;: 500\r\n      },\r\n      {\r\n        &quot;resourceType&quot;: &quot;total&quot;,\r\n        &quot;budget&quot;: 500\r\n      }\r\n    ],\r\n    &quot;resourceCounts&quot;: [\r\n      {\r\n        &quot;resourceType&quot;: &quot;total&quot;,\r\n        &quot;budget&quot;: 25\r\n      }\r\n    ]\r\n  }\r\n]`, `11276160670835433000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-json line-numbers\"><code class=\"language-json\"><span class=\"token punctuation\">[</span>\r\n  <span class=\"token punctuation\">{</span>\r\n    <span class=\"token property\">\"resourceSizes\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\r\n      <span class=\"token punctuation\">{</span>\r\n        <span class=\"token property\">\"resourceType\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"script\"</span><span class=\"token punctuation\">,</span>\r\n        <span class=\"token property\">\"budget\"</span><span class=\"token operator\">:</span> <span class=\"token number\">200</span>\r\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\r\n      <span class=\"token punctuation\">{</span>\r\n        <span class=\"token property\">\"resourceType\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"image\"</span><span class=\"token punctuation\">,</span>\r\n        <span class=\"token property\">\"budget\"</span><span class=\"token operator\">:</span> <span class=\"token number\">500</span>\r\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\r\n      <span class=\"token punctuation\">{</span>\r\n        <span class=\"token property\">\"resourceType\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"total\"</span><span class=\"token punctuation\">,</span>\r\n        <span class=\"token property\">\"budget\"</span><span class=\"token operator\">:</span> <span class=\"token number\">500</span>\r\n      <span class=\"token punctuation\">}</span>\r\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token property\">\"resourceCounts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\r\n      <span class=\"token punctuation\">{</span>\r\n        <span class=\"token property\">\"resourceType\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"total\"</span><span class=\"token punctuation\">,</span>\r\n        <span class=\"token property\">\"budget\"</span><span class=\"token operator\">:</span> <span class=\"token number\">25</span>\r\n      <span class=\"token punctuation\">}</span>\r\n    <span class=\"token punctuation\">]</span>\r\n  <span class=\"token punctuation\">}</span>\r\n<span class=\"token punctuation\">]</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>As of <strong>Lighthouse</strong> 5.3 you can add a <code class=\"language-text\">path</code> property to select which pages the budget should apply to. This is very handy because it allows you to have a centralised budget file for all your pages.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"37148249262368060000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`[\r\n  {\r\n    &quot;path&quot;:&quot;/*&quot;,\r\n    &quot;resourceSizes&quot;: [\r\n      ...\r\n    ],\r\n    &quot;resourceCounts&quot;: [\r\n      ...\r\n    ]\r\n  },\r\n  {\r\n    &quot;path&quot;:&quot;/blog&quot;,\r\n    &quot;resourceSizes&quot;: [\r\n      ...\r\n    ],\r\n    &quot;resourceCounts&quot;: [\r\n      ...\r\n    ]\r\n  },\r\n  {\r\n    &quot;path&quot;:&quot;/contact&quot;,\r\n    &quot;resourceSizes&quot;: [\r\n      ...\r\n    ],\r\n    &quot;resourceCounts&quot;: [\r\n      ...\r\n    ]\r\n  }\r\n]`, `37148249262368060000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-json line-numbers\"><code class=\"language-json\"><span class=\"token punctuation\">[</span>\r\n  <span class=\"token punctuation\">{</span>\r\n    <span class=\"token property\">\"path\"</span><span class=\"token operator\">:</span><span class=\"token string\">\"/*\"</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token property\">\"resourceSizes\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\r\n      ...\r\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token property\">\"resourceCounts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\r\n      ...\r\n    <span class=\"token punctuation\">]</span>\r\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\r\n  <span class=\"token punctuation\">{</span>\r\n    <span class=\"token property\">\"path\"</span><span class=\"token operator\">:</span><span class=\"token string\">\"/blog\"</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token property\">\"resourceSizes\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\r\n      ...\r\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token property\">\"resourceCounts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\r\n      ...\r\n    <span class=\"token punctuation\">]</span>\r\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\r\n  <span class=\"token punctuation\">{</span>\r\n    <span class=\"token property\">\"path\"</span><span class=\"token operator\">:</span><span class=\"token string\">\"/contact\"</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token property\">\"resourceSizes\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\r\n      ...\r\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token property\">\"resourceCounts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\r\n      ...\r\n    <span class=\"token punctuation\">]</span>\r\n  <span class=\"token punctuation\">}</span>\r\n<span class=\"token punctuation\">]</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<h2 id=\"how-should-you-choose-your-numbers\" style=\"position:relative;\"><a href=\"#how-should-you-choose-your-numbers\" aria-label=\"how should you choose your numbers permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How should you choose your numbers?</h2>\n<p>Finding the performance budget is not an easy task since it will depend on your application’s structure and bundling style. However, you can use this useful tool called <a href=\"https://perf-budget-calculator.firebaseapp.com/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><strong>Performance Budget Calculator</strong></a> to have a starting point. You might have to run the tool multiple time to each to a point where you’d be happy with the result. You don’t want to be too aggressive and also too complacent either.</p>\n<h2 id=\"using-the-ci-locally\" style=\"position:relative;\"><a href=\"#using-the-ci-locally\" aria-label=\"using the ci locally permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Using the CI locally</h2>\n<p>You can install the CI locally with:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"28686428566898446000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`npm install -g @lhci/cli`, `28686428566898446000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-bash line-numbers\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> <span class=\"token parameter variable\">-g</span> @lhci/cli</code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>It also has a dashboard which shows you the historical runs, compares reports and store their results.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"24203219055803093000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`npm install @lhci/server`, `24203219055803093000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-bash line-numbers\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> @lhci/server</code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>Before running the CI, you need to have a configuration file to tell the tool what to test and where to find the budget file (you could also pass those individually without a config file, but it’d be a pain):</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"97885388790054930000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// lighthouserc.json\r\n{\r\n  &quot;ci&quot;: {\r\n    &quot;collect&quot;: {\r\n      &quot;numberOfRuns&quot;: 2,\r\n      &quot;startServerCommand&quot;: &quot;yarn serve&quot;,\r\n      &quot;url&quot;: &quot;http://localhost:8080&quot;\r\n    },\r\n    &quot;preset&quot;: &quot;lighthouse:recommended&quot;\r\n  }\r\n}`, `97885388790054930000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-json line-numbers\"><code class=\"language-json\"><span class=\"token comment\">// lighthouserc.json</span>\r\n<span class=\"token punctuation\">{</span>\r\n  <span class=\"token property\">\"ci\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\r\n    <span class=\"token property\">\"collect\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\r\n      <span class=\"token property\">\"numberOfRuns\"</span><span class=\"token operator\">:</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span>\r\n      <span class=\"token property\">\"startServerCommand\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"yarn serve\"</span><span class=\"token punctuation\">,</span>\r\n      <span class=\"token property\">\"url\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"http://localhost:8080\"</span>\r\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token property\">\"preset\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"lighthouse:recommended\"</span>\r\n  <span class=\"token punctuation\">}</span>\r\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>Then you can run the tool on your local web server by first running:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"63879864146989030000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`lhci autorun --config=./lighthouserc.json`, `63879864146989030000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-bash line-numbers\"><code class=\"language-bash\">lhci autorun <span class=\"token parameter variable\">--config</span><span class=\"token operator\">=</span>./lighthouserc.json</code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>and then:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"77111024990371600000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`lhci assert --no-lighthouserc --budgetsFile=budget.json`, `77111024990371600000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-bash line-numbers\"><code class=\"language-bash\">lhci assert --no-lighthouserc <span class=\"token parameter variable\">--budgetsFile</span><span class=\"token operator\">=</span>budget.json</code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>And you will get a result similar to below based on your app’s performance:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"32366766976500716000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`2 result(s) for http://localhost:8080/\r\n\r\n  ×  resource-summary.script.size failure for maxNumericValue assertion\r\n     Keep request counts low and transfer sizes small\r\n     Documentation: https://developers.google.com/web/tools/lighthouse/audits/budgets\r\n\r\n        expected: <=102400\r\n           found: 2416174\r\n      all values: 2416174, 2416174\r\n\r\n\r\n  ×  resource-summary.total.size failure for maxNumericValue assertion\r\n     Keep request counts low and transfer sizes small\r\n     Documentation: https://developers.google.com/web/tools/lighthouse/audits/budgets\r\n\r\n        expected: <=512000\r\n           found: 2437694\r\n      all values: 2437694, 2437694\r\n\r\nAssertion failed. Exiting with status code 1.`, `32366766976500716000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-bash line-numbers\"><code class=\"language-bash\"><span class=\"token number\">2</span> result<span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">)</span> <span class=\"token keyword\">for</span> http://localhost:8080/\r\n\r\n  ×  resource-summary.script.size failure <span class=\"token keyword\">for</span> maxNumericValue assertion\r\n     Keep request counts low and transfer sizes small\r\n     Documentation: https://developers.google.com/web/tools/lighthouse/audits/budgets\r\n\r\n        expected: <span class=\"token operator\">&lt;=</span><span class=\"token number\">102400</span>\r\n           found: <span class=\"token number\">2416174</span>\r\n      all values: <span class=\"token number\">2416174</span>, <span class=\"token number\">2416174</span>\r\n\r\n\r\n  ×  resource-summary.total.size failure <span class=\"token keyword\">for</span> maxNumericValue assertion\r\n     Keep request counts low and transfer sizes small\r\n     Documentation: https://developers.google.com/web/tools/lighthouse/audits/budgets\r\n\r\n        expected: <span class=\"token operator\">&lt;=</span><span class=\"token number\">512000</span>\r\n           found: <span class=\"token number\">2437694</span>\r\n      all values: <span class=\"token number\">2437694</span>, <span class=\"token number\">2437694</span>\r\n\r\nAssertion failed. Exiting with status code <span class=\"token number\">1</span>.</code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<h2 id=\"using-the-tool-on-your-prs\" style=\"position:relative;\"><a href=\"#using-the-tool-on-your-prs\" aria-label=\"using the tool on your prs permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Using the tool on your PRs</h2>\n<p>I am focusing on <a href=\"https://github.com/features/actions\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">GitHub</a> using actions here. But you can apply this technique to <a href=\"https://azure.microsoft.com/en-au/services/devops/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Azure DevOps</a>, <a href=\"https://circleci.com/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">CircleCI</a>, <a href=\"https://www.jetbrains.com/teamcity/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">TeamCity</a>, or any other tool you’re using. For this to work you will need to have a <a href=\"https://guides.github.com/introduction/flow/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">GitHub flow</a> in your <code class=\"language-text\">git</code> repository defined.</p>\n<p>This article’s focus is not to teach you how to create a workflow, but here is the bare minimum you will need to have. Create a <code class=\"language-text\">.yaml</code>/<code class=\"language-text\">.yml</code> file in the <code class=\"language-text\">.github/workflows</code> folder, you can name it whatever you want. I usually name them after what’s their purpose, e.g. <code class=\"language-text\">lighthouse.yml</code> or <code class=\"language-text\">lhci-performance-bot.yml</code>.</p>\n<p>But before we get to the content of our <code class=\"language-text\">yaml</code> file, let’s see what we need to do on each PR:</p>\n<ol>\n<li>Pull down the code</li>\n<li>Build the app</li>\n<li>Deploy to a temporary site (I am using Netlify Preview here, but you can use others like staging slots on Azure App Service, etc)</li>\n<li>Run Lighthouse CI on the site</li>\n<li>Fail if the conditions are not met</li>\n</ol>\n<p>For this to work, we need an application. So I just spun up a new <a href=\"https://vuejs.org/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Vue</a> application using <a href=\"https://cli.vuejs.org/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Vue CLI</a>, then added my workflow to it and pushed it to <a href=\"https://github.com/yashints/lighthouse-ci-pr-action\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">a new GitHub repo</a>.</p>\n<p>Here is how my workflow looks like:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"99288361220041770000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`name: Lighthouse CI\r\n\r\non:\r\n  pull_request:\r\n    branches: [master]\r\n\r\njobs:\r\n  lighthouse:\r\n    runs-on: ubuntu-latest\r\n\r\n    steps:\r\n      - uses: actions/checkout@v2\r\n      - name: Setup Node 12\r\n        uses: actions/setup-node@v1\r\n        with:\r\n          node-version: 12.x\r\n      - name: Yarn Install and Build\r\n        run: |\r\n          yarn\r\n          yarn build\r\n      \r\n      - name: Waiting for 200 from the Netlify Preview\r\n        uses: jakepartusch/wait-for-netlify-action@v1\r\n        id: waitFor200\r\n        with:\r\n          site_name: &quot;lighthouse-ci-pr&quot;\r\n\r\n      - name: Audit URLs using Lighthouse\r\n        uses: treosh/lighthouse-ci-action@v2\r\n        with:\r\n          urls: |\r\n            \\$DEPLOY_URL/\r\n            \\$DEPLOY_URL/about\r\n          runs: 3\r\n          budgetPath: ./budget.json\r\n        env:\r\n          DEPLOY_URL: \\${{ steps.waitFor200.outputs.url }}`, `99288361220041770000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"yml\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-yml line-numbers\"><code class=\"language-yml\"><span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Lighthouse CI\r\n\r\n<span class=\"token key atrule\">on</span><span class=\"token punctuation\">:</span>\r\n  <span class=\"token key atrule\">pull_request</span><span class=\"token punctuation\">:</span>\r\n    <span class=\"token key atrule\">branches</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span>master<span class=\"token punctuation\">]</span>\r\n\r\n<span class=\"token key atrule\">jobs</span><span class=\"token punctuation\">:</span>\r\n  <span class=\"token key atrule\">lighthouse</span><span class=\"token punctuation\">:</span>\r\n    <span class=\"token key atrule\">runs-on</span><span class=\"token punctuation\">:</span> ubuntu<span class=\"token punctuation\">-</span>latest\r\n\r\n    <span class=\"token key atrule\">steps</span><span class=\"token punctuation\">:</span>\r\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> actions/checkout@v2\r\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Setup Node 12\r\n        <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> actions/setup<span class=\"token punctuation\">-</span>node@v1\r\n        <span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\r\n          <span class=\"token key atrule\">node-version</span><span class=\"token punctuation\">:</span> 12.x\r\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Yarn Install and Build\r\n        <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">|</span><span class=\"token scalar string\">\r\n          yarn\r\n          yarn build</span>\r\n      \r\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Waiting for 200 from the Netlify Preview\r\n        <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> jakepartusch/wait<span class=\"token punctuation\">-</span>for<span class=\"token punctuation\">-</span>netlify<span class=\"token punctuation\">-</span>action@v1\r\n        <span class=\"token key atrule\">id</span><span class=\"token punctuation\">:</span> waitFor200\r\n        <span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\r\n          <span class=\"token key atrule\">site_name</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"lighthouse-ci-pr\"</span>\r\n\r\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Audit URLs using Lighthouse\r\n        <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> treosh/lighthouse<span class=\"token punctuation\">-</span>ci<span class=\"token punctuation\">-</span>action@v2\r\n        <span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\r\n          <span class=\"token key atrule\">urls</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">|</span><span class=\"token scalar string\">\r\n            $DEPLOY_URL/\r\n            $DEPLOY_URL/about</span>\r\n          <span class=\"token key atrule\">runs</span><span class=\"token punctuation\">:</span> <span class=\"token number\">3</span>\r\n          <span class=\"token key atrule\">budgetPath</span><span class=\"token punctuation\">:</span> ./budget.json\r\n        <span class=\"token key atrule\">env</span><span class=\"token punctuation\">:</span>\r\n          <span class=\"token key atrule\">DEPLOY_URL</span><span class=\"token punctuation\">:</span> $<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> steps.waitFor200.outputs.url <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>What is happening is that I am just creating an action on each PR. In this action, we need to pull down the code, install node, run <code class=\"language-text\">yarn</code> and <code class=\"language-text\">yarn build</code> to build the application, wait for Netlify to deploy our PR into a preview site, then get the URL and inject it into the next step.</p>\n<p>I’m just using <a href=\"https://github.com/marketplace/actions/wait-for-netlify\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">wait-for-netlify-action</code></a>, but it’s not that hard to implement this part. Then we will be using the <a href=\"https://github.com/treosh/lighthouse-ci-action/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">lighthouse-ci-action</code></a> to run our audit on the paths we have specified.</p>\n<p>Notice I am not using a <strong>Lighthouse</strong> configuration file in this workflow because it’s not needed. You can pass the parameters directly to the action like I’ve done above. I am just auditing the home and about pages since I’ve only got these two pages.</p>\n<p>You can pass as many URL’s to this as you like, but if there are many of the, it makes more sense to add the config file back.</p>\n<blockquote>\n<p>💡 Remember to setup Netlify for your site and set it to create a deployment for every PR. Then get the site id and pass it to the <code class=\"language-text\">wait-for-netlify-action</code> action.</p>\n</blockquote>\n<p><strong>Pro tip</strong>: When you setup your Vue CLI generated application which is using Vue Router, the non default routes won’t work if the user types them in the browser URL bar and hits enter. That’s because that route is handled on the client side and server doesn’t know about it. To fix that you need to add a URL rewrite rule to return your <code class=\"language-text\">index.html</code> for all legitimate routes.</p>\n<p>In case of Netlify, just create a file named <code class=\"language-text\">_redirects</code> inside your <em>public</em> and add the following line to it.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"56249322138618200000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`/*    /index.html   200`, `56249322138618200000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-bash line-numbers\"><code class=\"language-bash\">/*    /index.html   <span class=\"token number\">200</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<h2 id=\"result\" style=\"position:relative;\"><a href=\"#result\" aria-label=\"result permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Result</h2>\n<p>I created a branch and pushed it up. Then created a PR and voila, the action kicked in and failed, since I have a large image on the about page.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1080px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/6d8fde67ffb5d7e17f0cfe9e2c0d8100/4e663/ci-results.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 44.074074074074076%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAJABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMFBP/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHTHrQkeID/xAAcEAAABgMAAAAAAAAAAAAAAAAAAQIDBBMFEDL/2gAIAQEAAQUCmmpBWui5wZDnX//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABoQAAIDAQEAAAAAAAAAAAAAAAACATOREBL/2gAIAQEABj8CXy0wWNpY2id//8QAGBABAQADAAAAAAAAAAAAAAAAARAhMaH/2gAIAQEAAT8hymy6bJXQ3//aAAwDAQACAAMAAAAQbD//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAdEAACAQQDAAAAAAAAAAAAAAABEQAQIVHRMZHw/9oACAEBAAE/EGaztl2GFCDZ3CTnsz1cCv8A/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"PR validation failed on GitHub action using lighthouse CI&#39;s audit\"\n        title=\"\"\n        src=\"/static/6d8fde67ffb5d7e17f0cfe9e2c0d8100/47311/ci-results.jpg\"\n        srcset=\"/static/6d8fde67ffb5d7e17f0cfe9e2c0d8100/6f81f/ci-results.jpg 270w,\n/static/6d8fde67ffb5d7e17f0cfe9e2c0d8100/09d21/ci-results.jpg 540w,\n/static/6d8fde67ffb5d7e17f0cfe9e2c0d8100/47311/ci-results.jpg 1080w,\n/static/6d8fde67ffb5d7e17f0cfe9e2c0d8100/0047d/ci-results.jpg 1620w,\n/static/6d8fde67ffb5d7e17f0cfe9e2c0d8100/4e663/ci-results.jpg 1893w\"\n        sizes=\"(max-width: 1080px) 100vw, 1080px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<p>I then reduced the size of the image and pushed the changes up. This time it passed.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1080px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/63e3628409b060661f7e8007c50a4a98/98d66/auditsuccess.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 41.11111111111111%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAQF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAbMsQD//xAAZEAACAwEAAAAAAAAAAAAAAAAAAwECFAT/2gAIAQEAAQUC62XVGtxrcf/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABoQAAICAwAAAAAAAAAAAAAAAAACMqESMWH/2gAIAQEABj8CXFt8JUSo/8QAGBAAAwEBAAAAAAAAAAAAAAAAAAFhkRH/2gAIAQEAAT8hbyF0xPgmwf/aAAwDAQACAAMAAAAQf/8A/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGxAAAQQDAAAAAAAAAAAAAAAAAQARUfBBYcH/2gAIAQEAAT8QKagCWYAl1cuLV2hf/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"PR validation passing on GitHub action using lighthouse CI\"\n        title=\"\"\n        src=\"/static/63e3628409b060661f7e8007c50a4a98/47311/auditsuccess.jpg\"\n        srcset=\"/static/63e3628409b060661f7e8007c50a4a98/6f81f/auditsuccess.jpg 270w,\n/static/63e3628409b060661f7e8007c50a4a98/09d21/auditsuccess.jpg 540w,\n/static/63e3628409b060661f7e8007c50a4a98/47311/auditsuccess.jpg 1080w,\n/static/63e3628409b060661f7e8007c50a4a98/0047d/auditsuccess.jpg 1620w,\n/static/63e3628409b060661f7e8007c50a4a98/98d66/auditsuccess.jpg 1905w\"\n        sizes=\"(max-width: 1080px) 100vw, 1080px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<h2 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h2>\n<p>We learned together how to use Lighthouse CI, a tool which allows you to run audits on your sites from command line in our CI/CD pipeline to make sure no one is downgrading the performance when they work on the application.</p>\n<p>This way, we’re always on top of our game rather than creating backlog items to find the issues and fix them later.</p>\n<p>In addition to that, your users are going to be happy and remain happy with their experience which is worth all the effort.</p>\n<p>Hope you’ve enjoyed reading this and happy performance enforcement 👋🏽.</p>","timeToRead":6,"frontmatter":{"title":"Stay on top of performance with Lighthouse CI 🚦","unformattedDate":"2020-04-13T00:00:00.000Z","date":"Apr 13, 2020","path":"/lighthouse-ci/","author":"Yaser Adel Mehraban","tags":["webdev","showdev","performance","lighthouse"],"thumbnail":null}}},{"node":{"id":"228f1e50-083c-5323-9dcc-88f0f0b9f962","html":"<p>Most of the times, we write code which is being copy pasted from all over internet. <a href=\"https://stackoverflow.com/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">StackOverflow</a> is the main source these days for finding solutions to all sort of problems. But is it OK to blindly copy paste code without really knowing what’s happening behind the scenes?</p>\n<!--more-->\n<h1 id=\"a-bit-of-context\" style=\"position:relative;\"><a href=\"#a-bit-of-context\" aria-label=\"a bit of context permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>A bit of context</h1>\n<p>Don’t get me wrong when I say <strong>StackOverflow</strong> should not be used blindly. It’s a great source of information for most of the day to day issues and bugs developers face all around the world. It’s just that we should be a bit more proactive and decide the best way out of all the available options out there.</p>\n<p>Let me show you some examples where a piece of code can be written in multiple ways, and the most obvious choice is not necessarily the best one.</p>\n<h2 id=\"chaining-array-loop-chaining\" style=\"position:relative;\"><a href=\"#chaining-array-loop-chaining\" aria-label=\"chaining array loop chaining permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Chaining array loop chaining</h2>\n<p>Let’s assume we have an array with <code class=\"language-text\">200,000</code> objects which include name and age properties. We want to have the name of all people under age of 22 (assume we have <code class=\"language-text\">100,000</code> of them). This the solution most people might use:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"30833100955319103000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const under22People = originalList\r\n  .filter(x => x.age < 22)\r\n  .map(x => x.name)`, `30833100955319103000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">const</span> under22People <span class=\"token operator\">=</span> originalList\r\n  <span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">x</span> <span class=\"token operator\">=></span> x<span class=\"token punctuation\">.</span>age <span class=\"token operator\">&lt;</span> <span class=\"token number\">22</span><span class=\"token punctuation\">)</span>\r\n  <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">x</span> <span class=\"token operator\">=></span> x<span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span></span></pre></div>\n<p>Since <code class=\"language-text\">ES5</code> and <code class=\"language-text\">ES6</code> were introduced, a nice set of array methods emerged. <code class=\"language-text\">ES6s</code> cleaner syntax makes it painless to chain methods in order to produce our desired results. The problem lies in how we use these nice methods without realising how they’re performed.</p>\n<p>In the first glance, this looks to be a really nice code, but if we look closer, we have a loop which runs <code class=\"language-text\">200,000</code> times when doing the filtering, and another <code class=\"language-text\">100,000</code> times when selecting the name.</p>\n<p>This is where we just need to loop through these items once. So let’s have a look at how can we rewrite this code:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"46772345653027635000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const under22People = []\r\noriginalList.forEach(({ age, name }) => {\r\n  age >= 18 && under22People.push(name)\r\n})`, `46772345653027635000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">const</span> under22People <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\r\noriginalList<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> age<span class=\"token punctuation\">,</span> name <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\r\n  age <span class=\"token operator\">>=</span> <span class=\"token number\">18</span> <span class=\"token operator\">&amp;&amp;</span> under22People<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">)</span>\r\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span></span></pre></div>\n<p>Now this code runs only <code class=\"language-text\">200,000</code> times. It doesn’t look as nice as the chained methods, but it sure has much better performance.</p>\n<p>You can even use the <code class=\"language-text\">reduce</code> method to do the same:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"41948536885506770000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const under22People = originalList.reduce(\r\n  (acc, { age, name }) => {\r\n    return age >= 18 ? [...ac, name] : acc\r\n  },\r\n  []\r\n)`, `41948536885506770000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">const</span> under22People <span class=\"token operator\">=</span> originalList<span class=\"token punctuation\">.</span><span class=\"token function\">reduce</span><span class=\"token punctuation\">(</span>\r\n  <span class=\"token punctuation\">(</span><span class=\"token parameter\">acc<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> age<span class=\"token punctuation\">,</span> name <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\r\n    <span class=\"token keyword\">return</span> age <span class=\"token operator\">>=</span> <span class=\"token number\">18</span> <span class=\"token operator\">?</span> <span class=\"token punctuation\">[</span><span class=\"token operator\">...</span>ac<span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">]</span> <span class=\"token operator\">:</span> acc\r\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\r\n  <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\r\n<span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>It sure looks much less readable, but it does the exact same job for us.</p>\n<h2 id=\"abusing-arrow-functions\" style=\"position:relative;\"><a href=\"#abusing-arrow-functions\" aria-label=\"abusing arrow functions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Abusing arrow functions</h2>\n<p>One of the good questions you could ask yourself when writing <code class=\"language-text\">JavaScript</code> is whether you know the difference between a traditional function and an arrow function (aka fat function).</p>\n<p>From MDN Web Docs:</p>\n<blockquote>\n<p>An arrow function expression is a syntactically compact alternative to a <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">regular function expression</a>, although without its own bindings to the <code class=\"language-text\">this</code>, <code class=\"language-text\">arguments</code>, <code class=\"language-text\">super</code>, or <code class=\"language-text\">new.target</code> keywords. Arrow function expressions are ill suited as methods, and they cannot be used as constructors.</p>\n</blockquote>\n<p>Before you ask, no they are not JavaScript equivalent of anonymous functions in languages like <code class=\"language-text\">C#</code>. But for now the only thing you need to care about is that they don’t have scope.</p>\n<p>Once of the many of their use cases is using them in class field. Consider in <code class=\"language-text\">React</code> you don’t need to manually bind your functions anymore like:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"53621859364338700000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`this.handleClick = this.handleClick.bind(this)`, `53621859364338700000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleClick <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">handleClick</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>Instead you will write your class like:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"54545765068467070000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`class MyComponent extends Component {\r\n  handleClick = () => {\r\n    // ...\r\n  }\r\n\r\n  render() {\r\n    // ...\r\n  }\r\n}`, `54545765068467070000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">MyComponent</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Component</span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token function-variable function\">handleClick</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\r\n    <span class=\"token comment\">// ...</span>\r\n  <span class=\"token punctuation\">}</span>\r\n\r\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n    <span class=\"token comment\">// ...</span>\r\n  <span class=\"token punctuation\">}</span>\r\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>As you might know, usual functions are defined in the prototype and will be shared across all instances. If we have a list of <code class=\"language-text\">N</code> components, these components will share the same method. So, if our components get clicked we still call our method <code class=\"language-text\">N</code> times, but it will call the same prototype. As we’re calling the same method multiple times across the prototype, the <code class=\"language-text\">JavaScript</code> engine can optimize it.</p>\n<p>On the other hand, for the arrow functions in class properties, if we’re creating <code class=\"language-text\">N</code> components, these <code class=\"language-text\">N</code> components will also create <code class=\"language-text\">N</code> functions. You can see by looking at the transpiled version, that class properties are initialised in the constructor. Which means if we click on <code class=\"language-text\">N</code> components, <code class=\"language-text\">N</code> different functions will be called.</p>\n<p>So consider this approach next time you are writing your new shiny <code class=\"language-text\">React</code> component.</p>\n<h2 id=\"nested-functions-vs-iifes\" style=\"position:relative;\"><a href=\"#nested-functions-vs-iifes\" aria-label=\"nested functions vs iifes permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Nested functions VS IIFEs</h2>\n<p>Nesting a function inside another function seems like a good idea to isolate some logic from outside world. Consider below code:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"84719191213493940000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`function doSomething(arg1, arg2) {\r\n  function nestedHelper(arg) {\r\n    return process(arg)\r\n  }\r\n\r\n  return nestedHelper(arg1) + nestedHelper(arg2)\r\n}`, `84719191213493940000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">function</span> <span class=\"token function\">doSomething</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">arg1<span class=\"token punctuation\">,</span> arg2</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token keyword\">function</span> <span class=\"token function\">nestedHelper</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">arg</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n    <span class=\"token keyword\">return</span> <span class=\"token function\">process</span><span class=\"token punctuation\">(</span>arg<span class=\"token punctuation\">)</span>\r\n  <span class=\"token punctuation\">}</span>\r\n\r\n  <span class=\"token keyword\">return</span> <span class=\"token function\">nestedHelper</span><span class=\"token punctuation\">(</span>arg1<span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span> <span class=\"token function\">nestedHelper</span><span class=\"token punctuation\">(</span>arg2<span class=\"token punctuation\">)</span>\r\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>The problem with above code is that every time you call <code class=\"language-text\">doSomething</code>, the <code class=\"language-text\">nestedHeler</code> is recreated. In order to prevent that you can use an <code class=\"language-text\">IIFE</code> (Immediately invoked function):</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"52245996472864915000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const result = (function() {\r\n  function privateHelper(arg) {\r\n    var result = process(arg)\r\n    return result\r\n  }\r\n\r\n  return function(arg1, arg2) {\r\n    return (\r\n      privateHelper(arg1) + privateHelper(arg2)\r\n    )\r\n  }\r\n})()`, `52245996472864915000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">const</span> result <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token keyword\">function</span> <span class=\"token function\">privateHelper</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">arg</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n    <span class=\"token keyword\">var</span> result <span class=\"token operator\">=</span> <span class=\"token function\">process</span><span class=\"token punctuation\">(</span>arg<span class=\"token punctuation\">)</span>\r\n    <span class=\"token keyword\">return</span> result\r\n  <span class=\"token punctuation\">}</span>\r\n\r\n  <span class=\"token keyword\">return</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">arg1<span class=\"token punctuation\">,</span> arg2</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\r\n      <span class=\"token function\">privateHelper</span><span class=\"token punctuation\">(</span>arg1<span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span> <span class=\"token function\">privateHelper</span><span class=\"token punctuation\">(</span>arg2<span class=\"token punctuation\">)</span>\r\n    <span class=\"token punctuation\">)</span>\r\n  <span class=\"token punctuation\">}</span>\r\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>When this code gets executed, the nested method will be created only once 🤷‍♂️.</p>\n<h1 id=\"use-sets-over-arrays-where-possible\" style=\"position:relative;\"><a href=\"#use-sets-over-arrays-where-possible\" aria-label=\"use sets over arrays where possible permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Use Sets over Arrays where possible</h1>\n<p>The most obvious difference between an <code class=\"language-text\">array</code> and a <code class=\"language-text\">Set</code> is that <code class=\"language-text\">array</code> is an <em>indexed</em> collection, whereas, a <code class=\"language-text\">Set</code> is key based.</p>\n<p>So why you should be using a <code class=\"language-text\">Set</code>?</p>\n<h3 id=\"searching-for-an-item\" style=\"position:relative;\"><a href=\"#searching-for-an-item\" aria-label=\"searching for an item permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Searching for an Item</h3>\n<p>Using <code class=\"language-text\">indexOf()</code> or <code class=\"language-text\">includes()</code> to check whether an item exists in an array is slow. In a <code class=\"language-text\">Set</code> you can find an item really easy using <code class=\"language-text\">has()</code>:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"22751717612982493000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const mySet = new Set([1, 1, 2])\r\n\r\nconsole.log(mySet.has(2)) // true`, `22751717612982493000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">const</span> mySet <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\r\n\r\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>mySet<span class=\"token punctuation\">.</span><span class=\"token function\">has</span><span class=\"token punctuation\">(</span><span class=\"token number\">2</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">// true</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span></span></pre></div>\n<h3 id=\"deleting-an-item\" style=\"position:relative;\"><a href=\"#deleting-an-item\" aria-label=\"deleting an item permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Deleting an Item</h3>\n<p>In a <code class=\"language-text\">Set</code>, you can delete an item by its value. In an array, the equivalent is using <code class=\"language-text\">splice()</code> based on an element’s <code class=\"language-text\">index</code>. As in the previous point, depending on indices is slow.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"76196783621243700000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const mySet = new Set([1, 2, 3, 4, 5])\r\n\r\nmySet.delete(1)`, `76196783621243700000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">const</span> mySet <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\r\n\r\nmySet<span class=\"token punctuation\">.</span><span class=\"token function\">delete</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span></span></pre></div>\n<h3 id=\"insert-an-item\" style=\"position:relative;\"><a href=\"#insert-an-item\" aria-label=\"insert an item permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Insert an Item</h3>\n<p>It is much faster to add an item to a <code class=\"language-text\">Set</code> than to an array using <code class=\"language-text\">push()</code> or <code class=\"language-text\">unshift()</code>.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"59078805804048980000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const mySet = new Set([1, 2])\r\n\r\nmySet.add(3) // Successfully added`, `59078805804048980000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">const</span> mySet <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\r\n\r\nmySet<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token number\">3</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">// Successfully added</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span></span></pre></div>\n<h3 id=\"storing-nan\" style=\"position:relative;\"><a href=\"#storing-nan\" aria-label=\"storing nan permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Storing NaN</h3>\n<p>You cannot use <code class=\"language-text\">indexOf()</code> or <code class=\"language-text\">includes()</code> to find the value <code class=\"language-text\">NaN</code>, while a <code class=\"language-text\">Set</code> is able to store this value.</p>\n<h3 id=\"removing-duplicates\" style=\"position:relative;\"><a href=\"#removing-duplicates\" aria-label=\"removing duplicates permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Removing Duplicates</h3>\n<p><code class=\"language-text\">Set</code> objects only store unique values. If you want to avoid storing duplicates, this is a significant advantage over arrays, where additional code would be required to deal with duplicates.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"74226843293734930000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const mySet = new Set([1, 1, 2])\r\n\r\nmySet.add(3) // Successfully added\r\n\r\nconsole.log(mySet.values()) // 1,2,3`, `74226843293734930000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">const</span> mySet <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\r\n\r\nmySet<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token number\">3</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">// Successfully added</span>\r\n\r\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>mySet<span class=\"token punctuation\">.</span><span class=\"token function\">values</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">// 1,2,3</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<h1 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h1>\n<p>There are many of these examples where you might want to be careful when writing code in a real world business application. Speed is one of the most important part of every web application and considering some items like above points, will increase your code’s performance which can result in happier users 😊.</p>\n<p>Hope this has helped you to start thinking about what other ways there are to solve the same issue rather than the first solution you’ll find on the web.</p>","timeToRead":4,"frontmatter":{"title":"Write faster JavaScript","unformattedDate":"2019-05-20T00:00:00.000Z","date":"May 20, 2019","path":"/write-faster-js/","author":"Yaser Adel Mehraban","tags":["webdev","showdev","javascript","performance"],"thumbnail":null}}},{"node":{"id":"9efab8e4-5642-5602-a559-9bce35aec489","html":"<p>Rendering images on a web page can be a very compute heavy operation. This makes it harder to run these kind of operations on the main thread since it might slow down the rendering or affect the user experience.</p>\n<!--more-->\n<h1 id=\"background\" style=\"position:relative;\"><a href=\"#background\" aria-label=\"background permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Background</h1>\n<p><a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Canvas</a> is one of the most interesting HTML elements in my opinion. The most popular reasons of using it are drawing graphics or animations.</p>\n<p>From Google Developers site:</p>\n<blockquote>\n<p>It is often used to create beautiful user experiences in media-rich web applications and online games.</p>\n</blockquote>\n<p>The fact that you can script it, raises the bar even higher and makes the element even more interesting. This gives you great flexibility in so many situations, but we’re going to focus on animations or rendering in general today.</p>\n<h1 id=\"problem\" style=\"position:relative;\"><a href=\"#problem\" aria-label=\"problem permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Problem</h1>\n<p>At the same time, executing JavaScript is one of the most frequent <a href=\"https://yashints.dev/blog/2018/10/12/web-perf-3\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">sources of user experience</a> issues. Because all the JavaScript code <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">runs on the same thread</a> as user interaction, these sort of heavy compute operations can affect the user experience in addition to real and perceived performance.</p>\n<h1 id=\"example\" style=\"position:relative;\"><a href=\"#example\" aria-label=\"example permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Example</h1>\n<p>To give you an example of how easy it is to use canvas, consider the following code:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"37567934852761620000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<canvas id=&quot;canvas&quot; width=&quot;300&quot; height=&quot;300&quot;>\r\n  An alternative text describing what your canvas\r\n  displays.\r\n</canvas>`, `37567934852761620000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>canvas</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>canvas<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">width</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>300<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">height</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>300<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\r\n  An alternative text describing what your canvas\r\n  displays.\r\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>canvas</span><span class=\"token punctuation\">></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span></span></pre></div>\n<p>And in your JavaScript file:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"50714513625323954000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`var mainCanvas = document.getElementById(\r\n  'myCanvas'\r\n)\r\nvar mainContext = mainCanvas.getContext('2d')\r\n\r\nvar canvasWidth = mainCanvas.width\r\nvar canvasHeight = mainCanvas.height\r\n\r\nvar angle = 0\r\n\r\nvar requestAnimationFrame =\r\n  window.requestAnimationFrame ||\r\n  window.mozRequestAnimationFrame ||\r\n  window.webkitRequestAnimationFrame ||\r\n  window.msRequestAnimationFrame\r\n\r\nfunction drawCircle() {\r\n  mainContext.clearRect(\r\n    0,\r\n    0,\r\n    canvasWidth,\r\n    canvasHeight\r\n  )\r\n\r\n  // color in the background\r\n  mainContext.fillStyle = '#EEEEEE'\r\n  mainContext.fillRect(\r\n    0,\r\n    0,\r\n    canvasWidth,\r\n    canvasHeight\r\n  )\r\n\r\n  // draw the circle\r\n  mainContext.beginPath()\r\n\r\n  var radius =\r\n    25 + 150 * Math.abs(Math.cos(angle))\r\n  mainContext.arc(\r\n    225,\r\n    225,\r\n    radius,\r\n    0,\r\n    Math.PI * 2,\r\n    false\r\n  )\r\n  mainContext.closePath()\r\n\r\n  // color in the circle\r\n  mainContext.fillStyle = '#006699'\r\n  mainContext.fill()\r\n\r\n  angle += Math.PI / 64\r\n\r\n  requestAnimationFrame(drawCircle)\r\n}\r\n\r\ndrawCircle()`, `50714513625323954000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">var</span> mainCanvas <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span>\r\n  <span class=\"token string\">'myCanvas'</span>\r\n<span class=\"token punctuation\">)</span>\r\n<span class=\"token keyword\">var</span> mainContext <span class=\"token operator\">=</span> mainCanvas<span class=\"token punctuation\">.</span><span class=\"token function\">getContext</span><span class=\"token punctuation\">(</span><span class=\"token string\">'2d'</span><span class=\"token punctuation\">)</span>\r\n\r\n<span class=\"token keyword\">var</span> canvasWidth <span class=\"token operator\">=</span> mainCanvas<span class=\"token punctuation\">.</span>width\r\n<span class=\"token keyword\">var</span> canvasHeight <span class=\"token operator\">=</span> mainCanvas<span class=\"token punctuation\">.</span>height\r\n\r\n<span class=\"token keyword\">var</span> angle <span class=\"token operator\">=</span> <span class=\"token number\">0</span>\r\n\r\n<span class=\"token keyword\">var</span> requestAnimationFrame <span class=\"token operator\">=</span>\r\n  window<span class=\"token punctuation\">.</span>requestAnimationFrame <span class=\"token operator\">||</span>\r\n  window<span class=\"token punctuation\">.</span>mozRequestAnimationFrame <span class=\"token operator\">||</span>\r\n  window<span class=\"token punctuation\">.</span>webkitRequestAnimationFrame <span class=\"token operator\">||</span>\r\n  window<span class=\"token punctuation\">.</span>msRequestAnimationFrame\r\n\r\n<span class=\"token keyword\">function</span> <span class=\"token function\">drawCircle</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n  mainContext<span class=\"token punctuation\">.</span><span class=\"token function\">clearRect</span><span class=\"token punctuation\">(</span>\r\n    <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\r\n    canvasWidth<span class=\"token punctuation\">,</span>\r\n    canvasHeight\r\n  <span class=\"token punctuation\">)</span>\r\n\r\n  <span class=\"token comment\">// color in the background</span>\r\n  mainContext<span class=\"token punctuation\">.</span>fillStyle <span class=\"token operator\">=</span> <span class=\"token string\">'#EEEEEE'</span>\r\n  mainContext<span class=\"token punctuation\">.</span><span class=\"token function\">fillRect</span><span class=\"token punctuation\">(</span>\r\n    <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\r\n    canvasWidth<span class=\"token punctuation\">,</span>\r\n    canvasHeight\r\n  <span class=\"token punctuation\">)</span>\r\n\r\n  <span class=\"token comment\">// draw the circle</span>\r\n  mainContext<span class=\"token punctuation\">.</span><span class=\"token function\">beginPath</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\r\n\r\n  <span class=\"token keyword\">var</span> radius <span class=\"token operator\">=</span>\r\n    <span class=\"token number\">25</span> <span class=\"token operator\">+</span> <span class=\"token number\">150</span> <span class=\"token operator\">*</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">abs</span><span class=\"token punctuation\">(</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">cos</span><span class=\"token punctuation\">(</span>angle<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\r\n  mainContext<span class=\"token punctuation\">.</span><span class=\"token function\">arc</span><span class=\"token punctuation\">(</span>\r\n    <span class=\"token number\">225</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token number\">225</span><span class=\"token punctuation\">,</span>\r\n    radius<span class=\"token punctuation\">,</span>\r\n    <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\r\n    Math<span class=\"token punctuation\">.</span><span class=\"token constant\">PI</span> <span class=\"token operator\">*</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token boolean\">false</span>\r\n  <span class=\"token punctuation\">)</span>\r\n  mainContext<span class=\"token punctuation\">.</span><span class=\"token function\">closePath</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\r\n\r\n  <span class=\"token comment\">// color in the circle</span>\r\n  mainContext<span class=\"token punctuation\">.</span>fillStyle <span class=\"token operator\">=</span> <span class=\"token string\">'#006699'</span>\r\n  mainContext<span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\r\n\r\n  angle <span class=\"token operator\">+=</span> Math<span class=\"token punctuation\">.</span><span class=\"token constant\">PI</span> <span class=\"token operator\">/</span> <span class=\"token number\">64</span>\r\n\r\n  <span class=\"token function\">requestAnimationFrame</span><span class=\"token punctuation\">(</span>drawCircle<span class=\"token punctuation\">)</span>\r\n<span class=\"token punctuation\">}</span>\r\n\r\n<span class=\"token function\">drawCircle</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>This is how it looks like:</p>\n<iframe height=\"220\" style=\"width: 100%;\" scrolling=\"no\" title=\"CanvasAnimation\" src=\"//codepen.io/yashints/embed/wbWppN/?height=265&theme-id=0&default-tab=result\" frameborder=\"no\" allowtransparency=\"true\" allowfullscreen=\"true\">\r\n  See the Pen <a href='https://codepen.io/yashints/pen/wbWppN/'>CanvasAnimation</a> by Yaser Adel Mehraban\r\n  (<a href='https://codepen.io/yashints'>@yashints</a>) on <a href='https://codepen.io'>CodePen</a>.\r\n</iframe>\n<p>Now let’s add a twist to this code. Let’s run a bit of code at the same time as the animation is running. We add a button and a handler that calls a function to calculate the Fibonacci number sequence 🤷‍♂️. So let’s get into it and add the button:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"39755970437328770000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<button type=&quot;button&quot; id=&quot;make-busy&quot;>\r\n  Hit the main thread!\r\n</button>`, `39755970437328770000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>button</span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>button<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>make-busy<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\r\n  Hit the main thread!\r\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>button</span><span class=\"token punctuation\">></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span></span></pre></div>\n<p>And let’s implement the Fibonacci series with a recursive function. Then we will use the <code class=\"language-text\">requestAnimationFrame</code> to make sure this code is run on the next available repaint. For more info on <code class=\"language-text\">requestAnimationFrame</code>, make sure to check out <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">the documentation</a>.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"78188588294850250000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`function fibonacci(num) {\r\n  if (num <= 1) return 1\r\n\r\n  return fibonacci(num - 1) + fibonacci(num - 2)\r\n}\r\n\r\ndocument\r\n  .querySelector('#make-busy')\r\n  .addEventListener('click', () => {\r\n    document.querySelector('#busy').innerText =\r\n      'Main thread working...'\r\n    requestAnimationFrame(() => {\r\n      requestAnimationFrame(() => {\r\n        fibonacci(40)\r\n        document.querySelector(\r\n          '#busy'\r\n        ).innerText = 'Done!'\r\n      })\r\n    })\r\n  })`, `78188588294850250000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">function</span> <span class=\"token function\">fibonacci</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">num</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>num <span class=\"token operator\">&lt;=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token number\">1</span>\r\n\r\n  <span class=\"token keyword\">return</span> <span class=\"token function\">fibonacci</span><span class=\"token punctuation\">(</span>num <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span> <span class=\"token function\">fibonacci</span><span class=\"token punctuation\">(</span>num <span class=\"token operator\">-</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span>\r\n<span class=\"token punctuation\">}</span>\r\n\r\ndocument\r\n  <span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#make-busy'</span><span class=\"token punctuation\">)</span>\r\n  <span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">'click'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\r\n    document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#busy'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>innerText <span class=\"token operator\">=</span>\r\n      <span class=\"token string\">'Main thread working...'</span>\r\n    <span class=\"token function\">requestAnimationFrame</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\r\n      <span class=\"token function\">requestAnimationFrame</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\r\n        <span class=\"token function\">fibonacci</span><span class=\"token punctuation\">(</span><span class=\"token number\">40</span><span class=\"token punctuation\">)</span>\r\n        document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span>\r\n          <span class=\"token string\">'#busy'</span>\r\n        <span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>innerText <span class=\"token operator\">=</span> <span class=\"token string\">'Done!'</span>\r\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\r\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\r\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>Now if you click on the button, you will see that the animation will stop and resume after the call to <code class=\"language-text\">fibonacci</code> function is returned.</p>\n<iframe height=\"265\" style=\"width: 100%;\" scrolling=\"no\" title=\"CanvasAnimation\" src=\"//codepen.io/yashints/embed/QREBrx/?height=265&theme-id=0&default-tab=result\" frameborder=\"no\" allowtransparency=\"true\" allowfullscreen=\"true\">\r\n  See the Pen <a href='https://codepen.io/yashints/pen/QREBrx/'>CanvasAnimation</a> by Yaser Adel Mehraban\r\n  (<a href='https://codepen.io/yashints'>@yashints</a>) on <a href='https://codepen.io'>CodePen</a>.\r\n</iframe>\n<p>You can clearly see how users might feel if they face a similar situation on your web application. And this is when the <code class=\"language-text\">OffscreenCanvas</code> can help.</p>\n<h1 id=\"offscreencanvas\" style=\"position:relative;\"><a href=\"#offscreencanvas\" aria-label=\"offscreencanvas permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>OffscreenCanvas</h1>\n<p>Up until recently, the drawing capabilities of canvas was directly dependent on the <code class=\"language-text\">&lt;canvas></code> element which meant it would depend on DOM (Document Object Model). <code class=\"language-text\">OffscreenCanvas</code> on the other hand, decouples DOM and Canvas API by moving it’s operations off screen.</p>\n<p>To make it even more interesting, the rendering operations can now be run inside a worker, thanks to the aforementioned decoupling. This alone opens the doors of possibilities to all sorts of performance improvements.</p>\n<h2 id=\"using-it-in-a-worker\" style=\"position:relative;\"><a href=\"#using-it-in-a-worker\" aria-label=\"using it in a worker permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Using it in a worker</h2>\n<p><a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Web Workers</a> are the web’s version of multi threading. They allow you to run code/tasks in a separate thread (aka background 😁). Now that the decoupling between DOM and Canvas API has landed, we can run it inside a worker.</p>\n<p>By expanding our previous example, we will add another copy of the same animation, but this time we’ll do the rendering in an <code class=\"language-text\">OffscreenCanvas</code> in a web worker.</p>\n<p>We need to setup our worker code in a script (I’ve named <code class=\"language-text\">animation.js</code>) which we can use later. First we need to move our animation code to its own file. Then let’s create our worker code:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"59928085865610090000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`let animationWorker = null\r\nself.onmessage = function(e) {\r\n  switch (e.data.msg) {\r\n    case 'start':\r\n      if (!animationWorker) {\r\n        importScripts(\r\n          e.data.origin + '/animation.js'\r\n        )\r\n        animationWorker = new ThemedAnimation(\r\n          e.data.canvas.getContext('2d')\r\n        )\r\n      }\r\n      animationWorker.start()\r\n      break\r\n    case 'stop':\r\n      if (!animationWorker) {\r\n        return\r\n      }\r\n      animationWorker.stop()\r\n      break\r\n  }\r\n}`, `59928085865610090000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">let</span> animationWorker <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span>\r\nself<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">onmessage</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">.</span>msg<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n    <span class=\"token keyword\">case</span> <span class=\"token string\">'start'</span><span class=\"token operator\">:</span>\r\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>animationWorker<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n        <span class=\"token function\">importScripts</span><span class=\"token punctuation\">(</span>\r\n          e<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">.</span>origin <span class=\"token operator\">+</span> <span class=\"token string\">'/animation.js'</span>\r\n        <span class=\"token punctuation\">)</span>\r\n        animationWorker <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ThemedAnimation</span><span class=\"token punctuation\">(</span>\r\n          e<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">.</span>canvas<span class=\"token punctuation\">.</span><span class=\"token function\">getContext</span><span class=\"token punctuation\">(</span><span class=\"token string\">'2d'</span><span class=\"token punctuation\">)</span>\r\n        <span class=\"token punctuation\">)</span>\r\n      <span class=\"token punctuation\">}</span>\r\n      animationWorker<span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\r\n      <span class=\"token keyword\">break</span>\r\n    <span class=\"token keyword\">case</span> <span class=\"token string\">'stop'</span><span class=\"token operator\">:</span>\r\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>animationWorker<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n        <span class=\"token keyword\">return</span>\r\n      <span class=\"token punctuation\">}</span>\r\n      animationWorker<span class=\"token punctuation\">.</span><span class=\"token function\">stop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\r\n      <span class=\"token keyword\">break</span>\r\n  <span class=\"token punctuation\">}</span>\r\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>No you can create two canvas elements side by side:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"71360026669115560000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<main>\r\n  <section class=&quot;support&quot;>\r\n    Your browser does not support OffscreenCanvas.\r\n  </section>\r\n  <div>\r\n    <h1>Canvas on main thread</h1>\r\n    <p>\r\n      Interaction is blocked when a theme is\r\n      loading\r\n    </p>\r\n    <canvas\r\n      id=&quot;canvas-window&quot;\r\n      width=&quot;400&quot;\r\n      height=&quot;400&quot;\r\n    ></canvas>\r\n  </div>\r\n  <div>\r\n    <h1>Canvas on worker thread</h1>\r\n    <p>\r\n      Interaction works even if a theme is loading\r\n    </p>\r\n    <canvas\r\n      id=&quot;canvas-worker&quot;\r\n      width=&quot;400&quot;\r\n      height=&quot;400&quot;\r\n    ></canvas>\r\n  </div>\r\n</main>`, `71360026669115560000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>main</span><span class=\"token punctuation\">></span></span>\r\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>section</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>support<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\r\n    Your browser does not support OffscreenCanvas.\r\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>section</span><span class=\"token punctuation\">></span></span>\r\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span>\r\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h1</span><span class=\"token punctuation\">></span></span>Canvas on main thread<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h1</span><span class=\"token punctuation\">></span></span>\r\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span><span class=\"token punctuation\">></span></span>\r\n      Interaction is blocked when a theme is\r\n      loading\r\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span>\r\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>canvas</span>\r\n      <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>canvas-window<span class=\"token punctuation\">\"</span></span>\r\n      <span class=\"token attr-name\">width</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>400<span class=\"token punctuation\">\"</span></span>\r\n      <span class=\"token attr-name\">height</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>400<span class=\"token punctuation\">\"</span></span>\r\n    <span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>canvas</span><span class=\"token punctuation\">></span></span>\r\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\r\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span>\r\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h1</span><span class=\"token punctuation\">></span></span>Canvas on worker thread<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h1</span><span class=\"token punctuation\">></span></span>\r\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span><span class=\"token punctuation\">></span></span>\r\n      Interaction works even if a theme is loading\r\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span>\r\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>canvas</span>\r\n      <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>canvas-worker<span class=\"token punctuation\">\"</span></span>\r\n      <span class=\"token attr-name\">width</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>400<span class=\"token punctuation\">\"</span></span>\r\n      <span class=\"token attr-name\">height</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>400<span class=\"token punctuation\">\"</span></span>\r\n    <span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>canvas</span><span class=\"token punctuation\">></span></span>\r\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\r\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>main</span><span class=\"token punctuation\">></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>And finally create the worker from the script tag above, request an animation frame (we used <code class=\"language-text\">setTimeOut</code> previously), and run the animation in both canvases at the same time.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"39417473002013260000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`document\r\n  .querySelector('main')\r\n  .classList.toggle(\r\n    'supported',\r\n    'OffscreenCanvas' in window\r\n  )\r\ndocument\r\n  .querySelector('#make-busy')\r\n  .addEventListener('click', () => {\r\n    document.querySelector('#busy').innerText =\r\n      'Main thread working...'\r\n    requestAnimationFrame(() => {\r\n      requestAnimationFrame(() => {\r\n        Animation.fibonacci(40)\r\n        document.querySelector(\r\n          '#busy'\r\n        ).innerText = 'Done!'\r\n      })\r\n    })\r\n  })\r\n\r\nconst canvas = document.querySelector('#case1')\r\nconst animationWindow = new Animation(\r\n  document\r\n    .querySelector('#canvas-window')\r\n    .getContext('2d')\r\n)\r\nanimationWindow.start()\r\nconst workerCode = document.querySelector(\r\n  '#workerCode'\r\n).textContent\r\nconst blob = new Blob([workerCode], {\r\n  type: 'text/javascript',\r\n})\r\nconst url = URL.createObjectURL(blob)\r\nconst worker = new Worker(url)\r\nconst offscreen = document\r\n  .querySelector('#canvas-worker')\r\n  .transferControlToOffscreen()\r\nconst urlParts = location.href.split('/')\r\nif (\r\n  urlParts[urlParts.length - 1].indexOf('.') !==\r\n  -1\r\n) {\r\n  urlParts.pop()\r\n}\r\nworker.postMessage(\r\n  {\r\n    msg: 'start',\r\n    origin: urlParts.join('/'),\r\n    canvas: offscreen,\r\n  },\r\n  [offscreen]\r\n)\r\nURL.revokeObjectURL(url) // cleanup`, `39417473002013260000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\">document\r\n  <span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'main'</span><span class=\"token punctuation\">)</span>\r\n  <span class=\"token punctuation\">.</span>classList<span class=\"token punctuation\">.</span><span class=\"token function\">toggle</span><span class=\"token punctuation\">(</span>\r\n    <span class=\"token string\">'supported'</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token string\">'OffscreenCanvas'</span> <span class=\"token keyword\">in</span> window\r\n  <span class=\"token punctuation\">)</span>\r\ndocument\r\n  <span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#make-busy'</span><span class=\"token punctuation\">)</span>\r\n  <span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">'click'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\r\n    document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#busy'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>innerText <span class=\"token operator\">=</span>\r\n      <span class=\"token string\">'Main thread working...'</span>\r\n    <span class=\"token function\">requestAnimationFrame</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\r\n      <span class=\"token function\">requestAnimationFrame</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\r\n        Animation<span class=\"token punctuation\">.</span><span class=\"token function\">fibonacci</span><span class=\"token punctuation\">(</span><span class=\"token number\">40</span><span class=\"token punctuation\">)</span>\r\n        document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span>\r\n          <span class=\"token string\">'#busy'</span>\r\n        <span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>innerText <span class=\"token operator\">=</span> <span class=\"token string\">'Done!'</span>\r\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\r\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\r\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\r\n\r\n<span class=\"token keyword\">const</span> canvas <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#case1'</span><span class=\"token punctuation\">)</span>\r\n<span class=\"token keyword\">const</span> animationWindow <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Animation</span><span class=\"token punctuation\">(</span>\r\n  document\r\n    <span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#canvas-window'</span><span class=\"token punctuation\">)</span>\r\n    <span class=\"token punctuation\">.</span><span class=\"token function\">getContext</span><span class=\"token punctuation\">(</span><span class=\"token string\">'2d'</span><span class=\"token punctuation\">)</span>\r\n<span class=\"token punctuation\">)</span>\r\nanimationWindow<span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\r\n<span class=\"token keyword\">const</span> workerCode <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span>\r\n  <span class=\"token string\">'#workerCode'</span>\r\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>textContent\r\n<span class=\"token keyword\">const</span> blob <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Blob</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span>workerCode<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token literal-property property\">type</span><span class=\"token operator\">:</span> <span class=\"token string\">'text/javascript'</span><span class=\"token punctuation\">,</span>\r\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\r\n<span class=\"token keyword\">const</span> url <span class=\"token operator\">=</span> <span class=\"token constant\">URL</span><span class=\"token punctuation\">.</span><span class=\"token function\">createObjectURL</span><span class=\"token punctuation\">(</span>blob<span class=\"token punctuation\">)</span>\r\n<span class=\"token keyword\">const</span> worker <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Worker</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span>\r\n<span class=\"token keyword\">const</span> offscreen <span class=\"token operator\">=</span> document\r\n  <span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#canvas-worker'</span><span class=\"token punctuation\">)</span>\r\n  <span class=\"token punctuation\">.</span><span class=\"token function\">transferControlToOffscreen</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\r\n<span class=\"token keyword\">const</span> urlParts <span class=\"token operator\">=</span> location<span class=\"token punctuation\">.</span>href<span class=\"token punctuation\">.</span><span class=\"token function\">split</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/'</span><span class=\"token punctuation\">)</span>\r\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>\r\n  urlParts<span class=\"token punctuation\">[</span>urlParts<span class=\"token punctuation\">.</span>length <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">indexOf</span><span class=\"token punctuation\">(</span><span class=\"token string\">'.'</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">!==</span>\r\n  <span class=\"token operator\">-</span><span class=\"token number\">1</span>\r\n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n  urlParts<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\r\n<span class=\"token punctuation\">}</span>\r\nworker<span class=\"token punctuation\">.</span><span class=\"token function\">postMessage</span><span class=\"token punctuation\">(</span>\r\n  <span class=\"token punctuation\">{</span>\r\n    <span class=\"token literal-property property\">msg</span><span class=\"token operator\">:</span> <span class=\"token string\">'start'</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token literal-property property\">origin</span><span class=\"token operator\">:</span> urlParts<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token literal-property property\">canvas</span><span class=\"token operator\">:</span> offscreen<span class=\"token punctuation\">,</span>\r\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\r\n  <span class=\"token punctuation\">[</span>offscreen<span class=\"token punctuation\">]</span>\r\n<span class=\"token punctuation\">)</span>\r\n<span class=\"token constant\">URL</span><span class=\"token punctuation\">.</span><span class=\"token function\">revokeObjectURL</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span> <span class=\"token comment\">// cleanup</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>Let’s see what’s happening here. First we need to detect the feature (OffscreenCanvas is not fully supported yet). Next we hook an event handler for our button to put some load on the main thread. This will put some stress on our animation rendering in the main thread.</p>\n<p>Afterwards, we get our canvas and run the animation code in the main thread, after which, we do the same in our worker. Except that we have to send a message to our worker to get that started (pay attention to the switch case in the worker code).</p>\n<p>And last but not least, make sure you don’t miss the most important part of the code which is call to <code class=\"language-text\">transferControlToOffscreen</code> on the canvas. This is where the magic of <code class=\"language-text\">OffscreenCanvas</code> happens. This method converts our regular canvas into an OffscreenCanvas instance.</p>\n<p>Below you can see the whole code in action:</p>\n<iframe height=\"500\" style=\"width: 100%;\" scrolling=\"no\" title=\"CanvasAnimation\" src=\"https://yashints.github.io/offscreencanvas/\" frameborder=\"no\" allowtransparency=\"false\" allowfullscreen=\"false\">\r\n  See the full code <a href='https://github.com/yashints/offscreencanvas/'>OffscreenCanvas</a> by Yaser Adel Mehraban\r\n  (<a href='https://yashints.dev'>@yashints</a>) on <a href='https://yashints.github.io/offscreencanvas/'>GitHub Pages</a>.\r\n</iframe>\n<h1 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h1>\n<p>We saw the difference in rendering smoothness when using an <code class=\"language-text\">OffscreenCanvas</code> in comparison with running the same on the main thread. This amazing feature can be used alongside all of the other techniques in <a href=\"https://yashints.dev/blog/2018/09/29/web-perf-1\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">my previous posts on web performance</a> to help you have a faster website and happier customers 😊.</p>","timeToRead":5,"frontmatter":{"title":"OffscreenCanvas - Render your graphics off the main thread","unformattedDate":"2019-05-11T00:00:00.000Z","date":"May 11, 2019","path":"/offscreen-canvas/","author":"Yaser Adel Mehraban","tags":["webdev","tips","frontend","canvas","performance"],"thumbnail":null}}},{"node":{"id":"4f37ec7c-8216-5ad8-ae0d-5e0282ed22fd","html":"<p>A while back, Nick Galov from <a href=\"https://hostingtribunal.com\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Hostingtribunal.com</a> contacted me to let me know they had created an inforgraphic photo for web performance statistics.</p>\n<!--more-->\n<p>This infographic contains some very useful statistics regarding page load time and some advice on where to focus for improvements.</p>\n<p>This was after I’d given my talk on web performance at <a href=\"https://ndcsydney.com/talk/need-for-speed-8-performance-tuning-of-your-web-application/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">NDC Sydney</a>, so the timing was really good.</p>\n<h1 id=\"what-happened\" style=\"position:relative;\"><a href=\"#what-happened\" aria-label=\"what happened permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What happened</h1>\n<p>I got so busy during the last couple of months that I rarely blogged and more was focused on my talk for <a href=\"https://ndcporto.com/talk/need-for-speed-8-performance-tuning-of-your-web-application/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">NDC Porto</a>.</p>\n<h1 id=\"what-next\" style=\"position:relative;\"><a href=\"#what-next\" aria-label=\"what next permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What next</h1>\n<p>Here you go, this is the infographic promised to be published on my blog. Hope this helps people find their motive to move towards a faster web.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 800px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/ef4ac175a9a0d7e91e2bb79356ddb6a6/4b190/Website-Speed-IG.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 1916.296296296296%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAF/ABQDASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAAAAQBAgMFBv/EABgBAAMBAQAAAAAAAAAAAAAAAAABAgME/9oADAMBAAIQAxAAAAG2VJ6OVgVHLmc5p6AOVyZLggZrDNYMi5cq111VrlhpuWtebpVHRNEy2qXjjk0nVfTSKC4P1NrWzpceATvawpLknm2Oa7qlCoy9/RWk8eeqB74TMjBYT5c8xXSe6edA6mzjsvyI2WtzsZSucdsHQmMtbklTnE1itiC55llp2wYECpd0rpFIkm2MxYmqgVN4I597lQWUrVjVwUJaufUNp5J0wP/EACIQAAICAgIDAAMBAAAAAAAAAAECAAMREgQTFDEyBRAhM//aAAgBAQABBQJtAoK5wk7BOxZ2iBC011aMczOAPnZoWabNABF9TE1ms1rIIWHAgExMQNGsBBOS1FNZ6UYeHTC4NuMQerQqW98HpeRS0bk1GWc7U101mmpa5d1h0UEaJD71SpdqZbxK7Wa1FcnDiWpXt2qSNgGTdupM5CyvlMiDmWS92tcqQvGuZBcdrUGVwkPsddK9tct41dzH6RiwHq1mUC1Mzuqshs44h5tSwV19OY2M0cew19FubqzU/GI6P5PyH+5wYuBMiOu0Fa4X0YPhPkwfK/Jg+U+TF+U+e22Cx4bnBSlCoprj1oGStSorEsGrI6BVZJb/AFwqmarlhgj9GE7TOJ2Cf2atNRGVxALCNLIeS08pp5bQeiP14dwHh2meBdP/xAAfEQACAQMFAQAAAAAAAAAAAAAAEQECECEDEhMgMUH/2gAIAQMBAT8BFJj5dG3HSM9HFnbIroQ7sUW4zYR4SR4SMmohFXoyTmqOesmjT+GzSv8A/8QAHxEAAgIBBQEBAAAAAAAAAAAAAAEQESECAxITMRRB/9oACAECAQE/AYzDccozFlxUpFmCjEWcipouOw5D9EP0Q0LTgdmnyEdGk+fbFq3v05b5ZZ//xAAuEAACAAQEBQMCBwAAAAAAAAAAAQIRITEQEjKRAyJRcYEgM0ITgiM0QVJhcpL/2gAIAQEABj8CsmL8NFJGh7Gh7GmLYoSwl0KCm5+i5+heeFcKxksyKPGqwopE2aU+8ZTgw+Iyz3MjKYfUyxOIrw3go4nKPpU1vwjkWZGZ8WT6TJ8SJ9pnKnuVZqwhh5fuLwGaq7GVtT7kpTnhnjNRafkvC4ehpJNpeRQyhopFIYdmZolKhC6VMqcKImczZdrzgoc0ukz3EZopzP4Ip0rheFF69sE3xIcv7WicOWZKr7Gb63NKxd7lDNClU+O5KKXWhw72Li/qezGvtPZif2n5eP8AyVqacHi8XQdMGPD4l4TllI0IfIr9SkKJuCZoe50FOJmt7l5lfUqPwWZYpjVk52NRpRpRpXostyy3Pjuf/8QAJBABAAICAgIDAAIDAAAAAAAAAQARITFBYVFxEIGRwfGh0eH/2gAIAQEAAT8hyq84iyQvmyIaQV5i/qMbJC3h7mQmvMJTERsW+iX2Co+E/JwKfqeg+ogyj7iy5cWXG7b9sTWoK8CUgFiecRWBhrEwsxUtc4OGBHGZi1QypLujqVX8kRkV7hmrh4puUPMP7/K5lyhAlTM34h3A/OJawAHhf9TRNZlkWCDAH7T+IYhVZXGZQ452EQWVKUrcwByubxm11xRc4D91N2b9Rtkge7Cks/ogVOCtQlY3tDFQPTESmScCOOWDob9MdD7WKlWThs93AQmbzGlgGmDVRuXKBagbGilBLUKkaGru0tioo28Qrqxogt5Eb833BQhCvggjbpWGoHNdIACxQzL1ttnVZirjwAt2IZIsGIzlTPr9pU0wdwmFUzZm/EL7ePJV3APMxuaSLp/5lVgpsgzcvDXMyrHEpiTT+YaNX9Tle98GjpaauLV5HUvus3yZumiX5E35Jqm3fvzLwaJXlAcnuaItp7WEp0h9Eqi/KDEV7ajCyUoWlCDlWN3M2qL8Jja0gkFriIbKl5h5ODd3ETL8mo4+oFBk9Sta/wAwC658jDTuDg+5uBsW+2NvGUKHVS7xOiBHJ4inCeUt4SjfymuiVPXx1DGtF4SH/9oADAMBAAIAAwAAABDn/LMzDsw0HA4ELDz7LIKgGT5XGAFAEfwDB8wDJM3TDDGEGs//xAAgEQADAAIBBQEBAAAAAAAAAAAAAREhMRBBUWFxsYGh/9oACAEDAQE/EFUpOF4RCQSTIPJn2OrAkoOdBFRER3DKh5HSj7iIbfGCu/w6j2Nuj+FEJ70WkW2lwoQyVQ0uT6mz4dmU0ssyvLNUefw2i0VNmUXn0Txf4iLIU80hGf/EAB8RAAMBAQACAgMAAAAAAAAAAAABESExgbFRcUGRof/aAAgBAgEBPxBpW0wWnRNzRiXBMq6hOjdCs0bor5HzUUyNYJTpDiKEl0r8Nk6SFwVa17INqzolMF9vCSr8+BOqshOMR6fRwj0HCE6sIJiFa1Z5OA096cISe+2X2P8AbMUL+DviU8EEH//EACYQAQACAgIBBAIDAQEAAAAAAAEAESExQWFRcYGhsZHhwdHwEPH/2gAIAQEAAT8QWNQwQe4AeXT9cxEKvXmKIg7M5i4g1fDKkSjV4P3A2AtVdl+0FmTMpKKpZeT/AHiJoXY1gYLoKVTfv3CNiG7NpQtPu8qgJlTw6RovcBtAAsopWB89k5LXxqCSDdZwXLiwWpRogpgJTYxgaS0Cbgqctfv1goAgW6KeSYYLD2el4iMQ1QC8uo2lE5HEUt12MuGvuJ2rCJlsd31GIJ3tAtRLHr7O4XuJj6LCiVhsHFtLi73qKcnai6xx7xKQChQ1BSgmhFQp0PELAE2seL7bIhQEEumNp0G5BjjDiVkHeQ/KlB2VazkVRGF8BVYPizffrNKEJSvCPioKsIui75E6qFUKSlj8woVDmm8PmCjABQdGCp3NNvpncQjaZD+uOCw0sO6ruUxysEOdTsQCm/iswi0MFcBaPg1gmfM2sFPuUQKkdhBTvuJkweRDfudSnFZQtO7TV1L4UGEJMMKCLpd5p7jKnCrH/mDBYVBQvmb2apNYH6SLdKSQ1nYVHIrq3rfev3DJLvAVQXddfE2iAyhz+IKEQFBckTeaxbQvPvE9nZW5TGDeshfXcs21yKcYz/71EVtZjYfXH5hAIBlSrjxAKLLDlceZzGQ7nPEVDYjpJR2VjJyKMICq7Lm+/wDalbNqqzoWpmFFw1yvkmQKDhAFe8SV3xuL8RLEKsiGq11FUerJKR+WolpGFgCtfUYRKvIZFvjcVxpUXUdBgHj1guucGifSAXM+LHxFKxeawjS2N0NemI4iZApn4l5Xr5dfErn26boxxf8AEIVrTealMTZ3KHRvXOuY3eOcmpzEfSHnF+DjvGepimhweZ4FdR2CrvJWsQChRNiUxNkMNswV/MegddC+lxwoNWf2i1CN28tYYeIApRQfcHaFUb4i0wGhLOeYvkSh1fmJduQpd75Nw2voiaPiKCEaRD0ZjQxWPvxGjEFNC766gyLBpapX9xCngWinpM7ZSssp84+pYu6OeD4/coSzjlzKyHCDR5edkLsF5y0x2DpxiLwyr5u+kZWUuucjn5iHB9G5l2CpZbr0ICiIFufiybAI9/qLKYq+cfMCKtPDbA/2TKzVTRH/AAZjCz/pKT/j9o2aHf6z/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Web performance infographic\"\n        title=\"\"\n        src=\"/static/ef4ac175a9a0d7e91e2bb79356ddb6a6/4b190/Website-Speed-IG.jpg\"\n        srcset=\"/static/ef4ac175a9a0d7e91e2bb79356ddb6a6/6f81f/Website-Speed-IG.jpg 270w,\n/static/ef4ac175a9a0d7e91e2bb79356ddb6a6/09d21/Website-Speed-IG.jpg 540w,\n/static/ef4ac175a9a0d7e91e2bb79356ddb6a6/4b190/Website-Speed-IG.jpg 800w\"\n        sizes=\"(max-width: 800px) 100vw, 800px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>","timeToRead":1,"frontmatter":{"title":"Web performance statistics infographic","unformattedDate":"2019-04-14T10:38:01.889Z","date":"Apr 14, 2019","path":"/webperf-statistics-inforgraphic","author":"Yaser Adel Mehraban","tags":["web","performance","page load time"],"thumbnail":null}}},{"node":{"id":"f1af9551-01eb-5335-a217-b006546dc893","html":"<p>Web fonts enable us to have good design, branding, readability and accessibility. Moreover, they would bring selectable, searchable, zoomable and high DPI text. However, with every advantage comes a trade off.</p>\n<!--more-->\n<p>All other parts:</p>\n<p><a href=\"/blog/2018/09/29/web-perf-1\">Part 1 on HTML and CSS</a></p>\n<p><a href=\"/blog/2018/10/06/web-perf-2\">Part 2 use Preload/Prefetch to boost load time</a></p>\n<p><a href=\"/blog/2018/10/12/web-perf-3\">Part 3 JavaScript tips and tricks</a></p>\n<p><a href=\"/blog/2018/11/12/web-perf-4\">Part 4 Image optimisation</a></p>\n<h2 id=\"intro\" style=\"position:relative;\"><a href=\"#intro\" aria-label=\"intro permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Intro</h2>\n<p>People use web fonts heavily these days without realising how much impact it would have on the overall page speed.</p>\n<p>This doesn’t mean you shouldn’t use them, just the fact that you should know how to use an optimised font and to how to load to reduce the impact on page load.</p>\n<p>Optimising web fonts depends on where you host the font, your web application’s design and back end server, your technical abilities and how far your company is willing to invest in this. But don’t let this hold you from following the techniques I will go through, even a little improvement on overall page load counts towards a better user experience.</p>\n<h2 id=\"finding-out-how-many-fonts-you-are-using\" style=\"position:relative;\"><a href=\"#finding-out-how-many-fonts-you-are-using\" aria-label=\"finding out how many fonts you are using permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Finding out how many fonts you are using</h2>\n<p>Before you start the task, you should find out what fonts are used throughout your website. You can easily find this out using Audit tabs in Chrome DevTools’ network tab and looking at the HTTP requests.</p>\n<p>Once in the tab click on the filter icon and look for file extensions like <code class=\"language-text\">woff</code>, <code class=\"language-text\">woff2</code>, <code class=\"language-text\">tff</code>, <code class=\"language-text\">otf</code> and so on:</p>\n<p><img src=\"/8576b18315655ed5f59939bc2581ce78/webfontusage.jpg\" alt=\"Finding what web fonts you are using\"></p>\n<h2 id=\"deciding-how-many-is-too-many\" style=\"position:relative;\"><a href=\"#deciding-how-many-is-too-many\" aria-label=\"deciding how many is too many permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Deciding how many is too many</h2>\n<p>Research shows on average 67% of web pages use custom fonts, with websites averaging between four web font HTTP requests.</p>\n<p>Once you figured out how many fonts you are using, you should think about how many fonts you should use. Normally these decisions are driven by UX or design team, but you can definitely have a word with them.</p>\n<p>If you are thinking how many is too many, the rule of thumb is that <a href=\"https://engageinteractive.co.uk/blog/how-many-fonts-is-too-many-fonts\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">three is crowd and two is the best to stick to</a>.</p>\n<p>If you use less fonts throughout your website, not only the number of network requests are reduced, but also the design is more streamlined and consistent.</p>\n<h2 id=\"choose-the-subset-you-need\" style=\"position:relative;\"><a href=\"#choose-the-subset-you-need\" aria-label=\"choose the subset you need permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Choose the subset you need</h2>\n<p>Unless you have an international website supporting multiple languages, it doesn’t make sense to use all character sets. Choose only what you need and for the languages you use.</p>\n<p>Ilya Grigorik a Developer Advocate and Web Perf Guru at Google, <a href=\"https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">explains how you can subset or split web fonts into multiple unicode ranges to deliver only what you need</a>.</p>\n<p>You can use the <a href=\"http://www.w3.org/TR/css3-fonts/#descdef-unicode-range\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Unicode-range descriptor</a> to specify a list of range values, which can be set out in three different forms:</p>\n<ul>\n<li><strong>Single codepoint</strong>: indicates a single character.</li>\n<li><strong>Interval range</strong>: indicates start and of the codepoints of a range of characters.</li>\n<li><strong>Wildcard range</strong>: <code class=\"language-text\">?</code> character indicates any hexadecimal digit.</li>\n</ul>\n<p>To demonstrate the possibilities, this is how you can split the <a href=\"https://fontawesome.com/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Font Awesome</a> into Latin and Japanese subsets. Once done, the browser would download each subset as needed.</p>\n<div class=\"custom-block info\"><div class=\"custom-block-body\"> Note: Unicode-range subsetting is particularly important for Asian languages, where the number of glyphs is much larger than in Western languages and a typical “full” font is often measured in megabytes instead of tens of kilobytes.</div></div>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"24167569279394853000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`@font-face {\r\n  font-family: 'Awesome Font';\r\n  font-style: normal;\r\n  font-weight: 400;\r\n  src: local('Awesome Font'),\r\n    url('/fonts/awesome-l.woff2') format('woff2'),\r\n    url('/fonts/awesome-l.woff') format('woff'),\r\n    url('/fonts/awesome-l.ttf') format('truetype'),\r\n    url('/fonts/awesome-l.eot') format('embedded-opentype');\r\n  unicode-range: U+000-5FF; /* Latin glyphs */\r\n}\r\n\r\n@font-face {\r\n  font-family: 'Awesome Font';\r\n  font-style: normal;\r\n  font-weight: 400;\r\n  src: local('Awesome Font'),\r\n    url('/fonts/awesome-jp.woff2') format('woff2'),\r\n    url('/fonts/awesome-jp.woff') format('woff'),\r\n    url('/fonts/awesome-jp.ttf') format('truetype'),\r\n    url('/fonts/awesome-jp.eot') format('embedded-opentype');\r\n  unicode-range: U+3000-9FFF, U+ff??; /* Japanese glyphs */\r\n}`, `24167569279394853000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"css\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-css line-numbers\"><code class=\"language-css\"><span class=\"token atrule\"><span class=\"token rule\">@font-face</span></span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token property\">font-family</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'Awesome Font'</span><span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">font-style</span><span class=\"token punctuation\">:</span> normal<span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">font-weight</span><span class=\"token punctuation\">:</span> 400<span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">src</span><span class=\"token punctuation\">:</span> <span class=\"token function\">local</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Awesome Font'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">'/fonts/awesome-l.woff2'</span><span class=\"token punctuation\">)</span></span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'woff2'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">'/fonts/awesome-l.woff'</span><span class=\"token punctuation\">)</span></span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'woff'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">'/fonts/awesome-l.ttf'</span><span class=\"token punctuation\">)</span></span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'truetype'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">'/fonts/awesome-l.eot'</span><span class=\"token punctuation\">)</span></span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'embedded-opentype'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">unicode-range</span><span class=\"token punctuation\">:</span> U+000-5FF<span class=\"token punctuation\">;</span> <span class=\"token comment\">/* Latin glyphs */</span>\r\n<span class=\"token punctuation\">}</span>\r\n\r\n<span class=\"token atrule\"><span class=\"token rule\">@font-face</span></span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token property\">font-family</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'Awesome Font'</span><span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">font-style</span><span class=\"token punctuation\">:</span> normal<span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">font-weight</span><span class=\"token punctuation\">:</span> 400<span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">src</span><span class=\"token punctuation\">:</span> <span class=\"token function\">local</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Awesome Font'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">'/fonts/awesome-jp.woff2'</span><span class=\"token punctuation\">)</span></span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'woff2'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">'/fonts/awesome-jp.woff'</span><span class=\"token punctuation\">)</span></span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'woff'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">'/fonts/awesome-jp.ttf'</span><span class=\"token punctuation\">)</span></span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'truetype'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">'/fonts/awesome-jp.eot'</span><span class=\"token punctuation\">)</span></span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'embedded-opentype'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">unicode-range</span><span class=\"token punctuation\">:</span> U+3000-9FFF<span class=\"token punctuation\">,</span> U+ff??<span class=\"token punctuation\">;</span> <span class=\"token comment\">/* Japanese glyphs */</span>\r\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<div class=\"custom-block info\"><div class=\"custom-block-body\"><strong>Note:</strong> The <code class=\"language-text\">local()</code> directive allows you to reference, load, and use locally installed fonts. The <code class=\"language-text\">url()</code> directive allows you to load external fonts, and are allowed to contain an optional <code class=\"language-text\">format()</code> hint indicating the format of the font referenced by the provided URL.</div></div>\n<p>There is a catch however which is not all browsers currently <a href=\"http://caniuse.com/#feat=font-unicode-range\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">support unicode-range</a>. Fortunately most of the major browsers support it, you will need to have a fallback option.</p>\n<p>Now if you’re asking how I can determine which subsets I need, the answer is:</p>\n<ul>\n<li>If the browser supports unicode-range, then it will automatically select the right subset. You will just need to provide the subset files and specify the appropriate range in the <code class=\"language-text\">@font-face</code> rules.</li>\n<li>If the browser does not support this feature, then you will need to hide all unnecessary subsets, which is, you have to specify the required subsets manually.</li>\n</ul>\n<p>You can generate the subsets using an open source tool called <a href=\"https://github.com/behdad/fonttools/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">pyftsubset tool</a>. In addition to that some font services allow manual subsetting via custom query parameters.</p>\n<p>There are some other opportunities you can leverage apart from subsetting. Let’s say you just need a Google font to show your page title. You can specify which characters to download from that font only using a <code class=\"language-text\">&amp;text=</code> syntax:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"63469037658304406000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<link\r\n  href=&quot;//fonts.googleapis.com/css?family=Roboto&text=log&quot;\r\n  rel=&quot;stylesheet&quot;\r\n/>`, `63469037658304406000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span>\r\n  <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>//fonts.googleapis.com/css?family=Roboto&amp;text=log<span class=\"token punctuation\">\"</span></span>\r\n  <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>stylesheet<span class=\"token punctuation\">\"</span></span>\r\n<span class=\"token punctuation\">/></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span></span></pre></div>\n<div class=\"custom-block warning\"><div class=\"custom-block-body\"><strong>Warning:</strong> You need to be careful since this is not a word selector but a character selector. This means characters <code class=\"language-text\">l</code>, <code class=\"language-text\">o</code>, and <code class=\"language-text\">g</code> will be shown on Roboto.</div></div>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/727a971696e3f21f5fc9977746d48ca0/41099/font-certain-characters.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 60%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAQAF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB2hBqP//EABcQAAMBAAAAAAAAAAAAAAAAABAREiD/2gAIAQEAAQUCxKH/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAZEAACAwEAAAAAAAAAAAAAAAAAARARQXH/2gAIAQEAAT8hFeqKEmm+x//aAAwDAQACAAMAAAAQw8//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAaEAACAwEBAAAAAAAAAAAAAAABEQAhMRBR/9oACAEBAAE/EIRNAukWxwgdEIO/6amT/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"This image shows that only the letter g is rendered with Roboto font\"\n        title=\"\"\n        src=\"/static/727a971696e3f21f5fc9977746d48ca0/41099/font-certain-characters.jpg\"\n        srcset=\"/static/727a971696e3f21f5fc9977746d48ca0/6f81f/font-certain-characters.jpg 270w,\n/static/727a971696e3f21f5fc9977746d48ca0/41099/font-certain-characters.jpg 500w\"\n        sizes=\"(max-width: 500px) 100vw, 500px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<h2 id=\"deliver-optimised-font-formats\" style=\"position:relative;\"><a href=\"#deliver-optimised-font-formats\" aria-label=\"deliver optimised font formats permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Deliver optimised font formats</h2>\n<p>There are four major formats used on the web:</p>\n<ul>\n<li><strong>Embedded Open Type (EOT)</strong>: Microsoft designed this format, which is now only used by IE browsers.</li>\n<li><strong>True Type Font (TTF)</strong>: A format that’s been around since the late 1980s that has partial IE support.</li>\n<li><strong>Web Open Font Format (WOFF)</strong>: A format developed in 2009, which is essentially OpenType or TrueType with compression and additional metadata. It enjoys widespread support but is not available in some older browser.</li>\n<li><strong>Web Open Font Format (WOFF2)</strong>: An improvement on WOFF that provides, on average, a 30% reduction in file size. Support is still a work in progress for many browsers.</li>\n</ul>\n<p>There isn’t one format that works in all of the browsers, hence the need to deliver multiple formats to provide a consistent experience. From Google developer’s website:</p>\n<ul>\n<li>Serve WOFF 2.0 variant to browsers that support it.</li>\n<li>Serve WOFF variant to the majority of browsers.</li>\n<li>Serve TTF variant to old Android (below 4.4) browsers.</li>\n<li>Serve EOT variant to old IE (below IE9) browsers.</li>\n</ul>\n<p>If majority of your users use modern web browsers you can get away with specifying just two formats:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"94111531194680160000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`@font-face {\r\n  font-family: 'Roboto';\r\n  src: local('Roboto'), local('Roboto'),\r\n    url(fonts/Roboto.woff2) format('woff2'), url(fonts/Roboto.woff)\r\n      format('woff');\r\n}`, `94111531194680160000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"css\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-css line-numbers\"><code class=\"language-css\"><span class=\"token atrule\"><span class=\"token rule\">@font-face</span></span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token property\">font-family</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'Roboto'</span><span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">src</span><span class=\"token punctuation\">:</span> <span class=\"token function\">local</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Roboto'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">local</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Roboto'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span>fonts/Roboto.woff2<span class=\"token punctuation\">)</span></span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'woff2'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span>fonts/Roboto.woff<span class=\"token punctuation\">)</span></span>\r\n      <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'woff'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\r\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<h2 id=\"always-check-for-the-font-locally\" style=\"position:relative;\"><a href=\"#always-check-for-the-font-locally\" aria-label=\"always check for the font locally permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Always check for the font locally</h2>\n<p>Some users might already have the fonts installed on their system, so why they should be forced to download the fonts again. You can prevent this by making sure you give precedence to <code class=\"language-text\">local()</code> in the <code class=\"language-text\">src</code> attribute of font face rule.</p>\n<p>In the above sample note how the <code class=\"language-text\">src: local</code> is used before the <code class=\"language-text\">url</code>.</p>\n<h2 id=\"optimnising-the-loading-and-rendering\" style=\"position:relative;\"><a href=\"#optimnising-the-loading-and-rendering\" aria-label=\"optimnising the loading and rendering permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Optimnising the loading and rendering</h2>\n<p>By default the fonts are lazy loaded, which means the network request is delayed until the render tree is fully constructed, which in turn results in delayed text rendering.</p>\n<p>There are three hooks you would need to implement a custom font loading strategy:</p>\n<ul>\n<li><code class=\"language-text\">&lt;link rel=preload></code></li>\n<li>CSS <code class=\"language-text\">font-display</code> property</li>\n<li>Font Loading API</li>\n</ul>\n<h3 id=\"preload-your-web-font\" style=\"position:relative;\"><a href=\"#preload-your-web-font\" aria-label=\"preload your web font permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Preload your web font</h3>\n<p>If there is a high chance that the font is used in the page, then you can load the font eagerly using the platform feature: <code class=\"language-text\">&lt;link rel=preload></code>.</p>\n<p>This will tell the browser that the font should be fetched early, but it won’t specify how to use it. You will need to specify the appropriate CSS <code class=\"language-text\">@font-face</code>:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"31332087639403120000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<link\r\n  rel=&quot;preload&quot;\r\n  href=&quot;/fonts/Roboto.woff2&quot;\r\n  as=&quot;font&quot;\r\n/>`, `31332087639403120000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span>\r\n  <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>preload<span class=\"token punctuation\">\"</span></span>\r\n  <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>/fonts/Roboto.woff2<span class=\"token punctuation\">\"</span></span>\r\n  <span class=\"token attr-name\">as</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>font<span class=\"token punctuation\">\"</span></span>\r\n<span class=\"token punctuation\">/></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"74762321996478380000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`@font-face {\r\n  font-family: 'Awesome Font';\r\n  font-style: normal;\r\n  font-weight: 400;\r\n  /* will be preloaded */\r\n  src: local('Awesome Font'),\r\n    url('/fonts/awesome-l.woff2') format('woff2'),\r\n    url('/fonts/awesome-l.woff') format('woff'),\r\n    url('/fonts/awesome-l.ttf') format('truetype'),\r\n    url('/fonts/awesome-l.eot') format('embedded-opentype');\r\n  unicode-range: U+000-5FF; /* Latin glyphs */\r\n}`, `74762321996478380000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"css\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-css line-numbers\"><code class=\"language-css\"><span class=\"token atrule\"><span class=\"token rule\">@font-face</span></span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token property\">font-family</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'Awesome Font'</span><span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">font-style</span><span class=\"token punctuation\">:</span> normal<span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">font-weight</span><span class=\"token punctuation\">:</span> 400<span class=\"token punctuation\">;</span>\r\n  <span class=\"token comment\">/* will be preloaded */</span>\r\n  <span class=\"token property\">src</span><span class=\"token punctuation\">:</span> <span class=\"token function\">local</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Awesome Font'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">'/fonts/awesome-l.woff2'</span><span class=\"token punctuation\">)</span></span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'woff2'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">'/fonts/awesome-l.woff'</span><span class=\"token punctuation\">)</span></span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'woff'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">'/fonts/awesome-l.ttf'</span><span class=\"token punctuation\">)</span></span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'truetype'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n    <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">'/fonts/awesome-l.eot'</span><span class=\"token punctuation\">)</span></span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'embedded-opentype'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">unicode-range</span><span class=\"token punctuation\">:</span> U+000-5FF<span class=\"token punctuation\">;</span> <span class=\"token comment\">/* Latin glyphs */</span>\r\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<div class=\"custom-block warning\"><div class=\"custom-block-body\"><strong>Warning:</strong> Not all browsers support this feature, but those who support it also support WOFF2, so you should use that format.</div></div>\n<p>For more info on the other solutions refer to <a href=\"https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">this great post</a>.</p>\n<h2 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h2>\n<p>In short these are the points you have to consider when optimising web fonts:</p>\n<ul>\n<li>Audit and monitor your font use.</li>\n<li>Subset your font resources.</li>\n<li>Deliver optimized font formats to each browser.</li>\n<li>Give precedence to <code class=\"language-text\">local()</code> in your <code class=\"language-text\">src</code> list.</li>\n<li>Customize font loading and rendering using <code class=\"language-text\">&lt;link rel=\"preload\"></code>, <code class=\"language-text\">font-display</code>, or the Font Loading API.</li>\n<li>Specify revalidation and optimal caching policies</li>\n</ul>\n<p>Hope this helps you move one more step in the right direction to improve your web application’s performance.</p>","timeToRead":6,"frontmatter":{"title":"Web font optimisation","unformattedDate":"2018-11-23T00:00:00.000Z","date":"Nov 23, 2018","path":"web-perf-5/","author":"Yaser Adel Mehraban","tags":["web","performance","web fonts"],"thumbnail":{"childImageSharp":{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAArwAAAK8AFCrDSYAAAC70lEQVR42j2S20+bZRzH+1d4bTTeubtdmOxu3hkXwsDpPBCabQih1UQmO5A5swmibqZOxtwCm4AseyfQhXIIWwqytqwpbVNabUuBtKwHSunbA7T09Pb9+FKc3+T3XD3PJ59fvo/KarUyOzuLIAjMzMzgdDrIZDJUqjKFUpF8fp8td4SUJ4o+EKZuYIrGQQM6kxtJhlg0gt1ux+/34/P5UBkMBuzLy2SzWQ5SA+3nycR95BJJbN1GRhpuMVh/g6g9Qq9lhff7xzlxb5KeBRcFhZrY3lZEnIdAWZZrILlSQSpV2HQILA2rmb9xlOCSjg3DOkLDHfrrezG2CGy6wnxjdKAWFvhp3kFoW6y9T4oiKy4XqlwsTmhyjuWubtaGJtjyTqC/8iY/tr3N2LdHSL804nng4vbxa4x/NMhKnwkxX1RASXbTacrVKlJuF7lUYG8vhyrwu8BCwxnMzV8wX68m6fQSNHWja32dO1++heX2McTgP6w98RJ2biCm0rxKObFFelog1ttBckhHtVhAVRRTOLp6WGo5z/MmDS/aL5MJ+rANNeJ43MbG8jj5zE4NICk2+7tZPPpHzF3vZM/vJnJNg7WtkcglNan7N1EdXAxPPVXsmjE3abFpLyG63JSlHCWl5UKxRKUiEQpnSEWjCJ++x8TnHzLXpalBS6EAG1fbsWo/xt3RdAgs7+ZYu/+QTeNz4rGt/1cqFIosWFa5rjNy8uwIj6a9/D3Sh/nXXuSqhGt0AMtvN5GDqwQuqAl89clhy7KyyqtUi2Uie1nGw17W4zs0toxy7oKe1ot6znbqcfp3WLyqxT58l7DNTP87b2Dq+4Gyx0bWMIqqqsAORjlYTSXo9pg5sfgndYtjPNkOYFoKorkySd2ZETq/m+acAn0ZijGlOc3PR17j4QfvYhu4haR8u4PUDKX/DK3JKJ+9mFTGgNbxjHb7U9zZBL/cs9DcMUZP31+cav2Dr79/hrjuwzM2TGwzRFxpXiqXlNYk/gU1ac0RQRemPwAAAABJRU5ErkJggg=="},"backgroundColor":"transparent","images":{"fallback":{"src":"/static/9553f938d0498173e8cc22c7ae49e078/6bd28/webfonts.png","srcSet":"/static/9553f938d0498173e8cc22c7ae49e078/6ed98/webfonts.png 750w,\n/static/9553f938d0498173e8cc22c7ae49e078/6bd28/webfonts.png 800w","sizes":"(min-width: 800px) 800px, 100vw"},"sources":[{"srcSet":"/static/9553f938d0498173e8cc22c7ae49e078/cbeef/webfonts.webp 750w,\n/static/9553f938d0498173e8cc22c7ae49e078/93d42/webfonts.webp 800w","type":"image/webp","sizes":"(min-width: 800px) 800px, 100vw"}]},"width":800,"height":450}}}}}},{"node":{"id":"ce1cb9ac-675c-57d9-a7f9-7a4244bfdc5f","html":"<p>Recently I had a chance to present a talk at <a href=\"https://ndcsydney.com/talk/need-for-speed-8-performance-tuning-of-your-web-application/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">NDC Sydney</a> about web performance and it received a great feedback.</p>\n<!--more-->\n<p>That inspired me to write up a series of posts on each topic I covered in that talk, and who knows, maybe each of these posts would be a talk some day by their own 😃.</p>\n<p>All other parts:</p>\n<p><a href=\"/blog/2018/09/29/web-perf-1\">Part 1 on HTML and CSS</a></p>\n<p><a href=\"/blog/2018/10/06/web-perf-2\">Part 2 use Preload/Prefetch to boost load time</a></p>\n<p><a href=\"/blog/2018/10/12/web-perf-3\">Part 3 JavaScript tips and tricks</a></p>\n<p><a href=\"/blog/2018/11/23/web-perf-5\">Part 5 Web font optimisation</a></p>\n<h2 id=\"intro\" style=\"position:relative;\"><a href=\"#intro\" aria-label=\"intro permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Intro</h2>\n<p>Believe me you don’t want Google to hate your website. Knowing\r\nthe most heavy weight items on every website are images, it is very important to focus on their optimisation.</p>\n<p>Fortunately, reducing their size is very easy and has massive impact on the overall size of the page. For most of the users on a mobile device, the image quality wouldn’t be so important. Even on a desktop with high resolution there are sacrifices you can make. That’s because human eyes won’t detect certain pixels not being present.</p>\n<p>As long as you don’t go too far optimising an image to make it ugly, it is a good to continue reducing its size 🤷‍.</p>\n<blockquote>\n<p>Images take more than %50 of a web page’s overall weight 😱. That’s why we should optimise them!</p>\n</blockquote>\n<table>\n<thead>\n<tr>\n<th align=\"center\"><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1024px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/94dd15338b0d454aa565d4505c40c020/72e01/avragebytespp.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 65.92592592592594%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHtzZKpf//EABgQAAIDAAAAAAAAAAAAAAAAAAERAAIQ/9oACAEBAAEFAiZW2JwBZ//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABkQAQADAQEAAAAAAAAAAAAAAAEAEUEQkf/aAAgBAQABPyFRgt37BvGO0FXz/9oADAMBAAIAAwAAABAPz//EABcRAAMBAAAAAAAAAAAAAAAAAAEQESH/2gAIAQMBAT8QNuL/xAAWEQADAAAAAAAAAAAAAAAAAAAQESH/2gAIAQIBAT8QiH//xAAaEAEAAwEBAQAAAAAAAAAAAAABABEhQRBR/9oACAEBAAE/EFFP3BGIUI5rblKyiAlWcDI6Cq9fP//Z'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Average bytes per page\"\n        title=\"\"\n        src=\"/static/94dd15338b0d454aa565d4505c40c020/72e01/avragebytespp.jpg\"\n        srcset=\"/static/94dd15338b0d454aa565d4505c40c020/6f81f/avragebytespp.jpg 270w,\n/static/94dd15338b0d454aa565d4505c40c020/09d21/avragebytespp.jpg 540w,\n/static/94dd15338b0d454aa565d4505c40c020/72e01/avragebytespp.jpg 1024w\"\n        sizes=\"(max-width: 1024px) 100vw, 1024px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td align=\"center\"><em>Average bytes per page 2018</em></td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"what-does-image-optimisation-mean\" style=\"position:relative;\"><a href=\"#what-does-image-optimisation-mean\" aria-label=\"what does image optimisation mean permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What does image optimisation mean</h2>\n<p>Image optimisation is referred to <strong>reducing image sizes</strong> using different techniques. This will result in the page being loaded faster, hence having a better user experience.</p>\n<h2 id=\"why-bother\" style=\"position:relative;\"><a href=\"#why-bother\" aria-label=\"why bother permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why bother</h2>\n<p>Here are some benefits you would gain by optimising your images:</p>\n<ul>\n<li>It will improve the page load time. For every second users have to wait for the page to load, Amazon will lose $1.6 billion in sales per year (you may now pick a calculator and see how much your company would be impacted 😁).</li>\n<li>It improves your SEO capabilities, your site will rank higher in search engines resulting in more traffic.</li>\n<li>Creating site backups will be faster (if you are using a CMS or if you backup the whole site)</li>\n<li>Smaller image sizes use less bandwidth, resulting in not draining user’s mobile data quota.</li>\n<li>Requires less storage space on the server (or CDN), makes it more cost effective.</li>\n</ul>\n<h2 id=\"lets-optimise-them\" style=\"position:relative;\"><a href=\"#lets-optimise-them\" aria-label=\"lets optimise them permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Let’s optimise them</h2>\n<p>The primary goal of image optimisation is to find the balance between file size and image quality. But before we start on optimisation tips, we should understand different image formats and when to use each.</p>\n<h3 id=\"choose-the-right-format\" style=\"position:relative;\"><a href=\"#choose-the-right-format\" aria-label=\"choose the right format permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Choose the right format</h3>\n<ul>\n<li><strong>PNG</strong> – produces higher quality images, but also has a larger file size. Was created as a lossless image format, although it can also be lossy.</li>\n<li><strong>JPEG</strong> – uses lossy and lossless optimization. You can adjust the quality level for a good balance of quality and file size.</li>\n<li><strong>GIF</strong> – only uses 256 colors. It’s the best choice for animated images. It only uses lossless compression.</li>\n</ul>\n<p>There are some newer image formats like <strong>WebP</strong> and <strong>Jpeg2000</strong>, but the browser support is not there yet. In summary you should use JPEG for images with lots of colour and PNG for simpler images.</p>\n<h3 id=\"size-vs-compression\" style=\"position:relative;\"><a href=\"#size-vs-compression\" aria-label=\"size vs compression permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Size vs Compression</h3>\n<p>This is an example of an image before and after compression. Note how the quality is impacted (you can’t see it in the cat, but around it):</p>\n<p><strong>Before</strong>\r\n<span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1080px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/f418272fbe68058ad6a67edb674ebd63/21b8f/cat-lg.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAEEAv/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAGqapGhEv8A/8QAGRAAAwEBAQAAAAAAAAAAAAAAAAECAxEE/9oACAEBAAEFAr9EovfhDVzWWbp5QcR//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGhAAAgIDAAAAAAAAAAAAAAAAAAECMRESMv/aAAgBAQAGPwKhGyMuJyij/8QAGxABAAICAwAAAAAAAAAAAAAAAQARIVExQYH/2gAIAQEAAT8h7TnZHsooeNwdgHZKUVlXLeQIqP/aAAwDAQACAAMAAAAQlO//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAcEAEAAgIDAQAAAAAAAAAAAAABABEhMUFxgaH/2gAIAQEAAT8QFKMQCgvnHsr3IEY6RDHTKmWrPlV+RwojQ6SqABgn/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Cat\"\n        title=\"\"\n        src=\"/static/f418272fbe68058ad6a67edb674ebd63/47311/cat-lg.jpg\"\n        srcset=\"/static/f418272fbe68058ad6a67edb674ebd63/6f81f/cat-lg.jpg 270w,\n/static/f418272fbe68058ad6a67edb674ebd63/09d21/cat-lg.jpg 540w,\n/static/f418272fbe68058ad6a67edb674ebd63/47311/cat-lg.jpg 1080w,\n/static/f418272fbe68058ad6a67edb674ebd63/0047d/cat-lg.jpg 1620w,\n/static/f418272fbe68058ad6a67edb674ebd63/274e1/cat-lg.jpg 2160w,\n/static/f418272fbe68058ad6a67edb674ebd63/21b8f/cat-lg.jpg 4896w\"\n        sizes=\"(max-width: 1080px) 100vw, 1080px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<p><strong>After</strong>\r\n<span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1080px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/90e74e99d64dfa1db5e3ee84560be56e/e5166/cat-sm.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAQB/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAapqhrEv/8QAGRAAAwEBAQAAAAAAAAAAAAAAAAECAwQR/9oACAEBAAEFAr6JRe7RDVzWWbp5QeI//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGxAAAgEFAAAAAAAAAAAAAAAAAAECEBESMTL/2gAIAQEABj8C0JmSLuJyqf/EABsQAAIDAAMAAAAAAAAAAAAAAAABESFRMUGB/9oACAEBAAE/Ie03qKwpPjROoT1EKLZFt3glKIP/2gAMAwEAAgADAAAAEITv/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFREBAQAAAAAAAAAAAAAAAAAAACH/2gAIAQIBAT8QR//EABwQAQACAgMBAAAAAAAAAAAAAAEAESExQXGBsf/aAAgBAQABPxClo7AKC+ceyoBkIx0iGOiVMsWfKvyOFEaHSVQQME//2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Cat\"\n        title=\"\"\n        src=\"/static/90e74e99d64dfa1db5e3ee84560be56e/47311/cat-sm.jpg\"\n        srcset=\"/static/90e74e99d64dfa1db5e3ee84560be56e/6f81f/cat-sm.jpg 270w,\n/static/90e74e99d64dfa1db5e3ee84560be56e/09d21/cat-sm.jpg 540w,\n/static/90e74e99d64dfa1db5e3ee84560be56e/47311/cat-sm.jpg 1080w,\n/static/90e74e99d64dfa1db5e3ee84560be56e/e5166/cat-sm.jpg 1200w\"\n        sizes=\"(max-width: 1080px) 100vw, 1080px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<p>For the same reason that you can’t figure out the difference in the cat itself between the first and second image, it is safe to compress image to that degree. Just to let you know the first image is 4mb and the second is only 27kb. 🤷‍</p>\n<h3 id=\"lossy-vs-lossless-optimisation\" style=\"position:relative;\"><a href=\"#lossy-vs-lossless-optimisation\" aria-label=\"lossy vs lossless optimisation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Lossy vs Lossless Optimisation</h3>\n<p>Now that you know how important it is to compress images and reduce the quality, it is also important to know we have two types of compression:</p>\n<ul>\n<li>\n<p><strong>Lossy</strong> - this is kind of a filter to eliminate some data from the image, in the above example you could see some loss in the area around the cat. Using this technique, the file size will be reduced to a large degree. Tools such as Adobe Photoshop, Affinity Photo or some free online tools such as <a href=\"https://imagecompressor.com/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Image Compressor</a> will do the trick for you.</p>\n</li>\n<li>\n<p><strong>Lossless</strong> - this is a filter that does not eliminate any data, but uses compression only to reduce the size, but it means it requires images to be uncompressed to operate. You can do this easily using tools like <a href=\"http://netm.ag/optimize-263\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">FileOptimizer</a> and <a href=\"http://imageoptim.com/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ImageOptim</a>.</p>\n</li>\n</ul>\n<p>You will need to experience it yourself and find the sweet spot for your images. It is a task which requires some work beforehand but saves you a lot of time later. Another thing to consider is to use these tools like ImageOptim in your build process, this way you don’t even need to worry about doing it upfront. And your original images remain untouched.</p>\n<h2 id=\"using-the-right-dimension\" style=\"position:relative;\"><a href=\"#using-the-right-dimension\" aria-label=\"using the right dimension permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Using the right dimension</h2>\n<p>As important as compression is, by itself it can go only so far keeping the same dimension. After you apply the compression you cannot reduce the size with the same width and height anymore.</p>\n<p>Apart from this, you will need to know that showing a picture with 2000px width on a mobile device is not such a good idea. Especially on smaller devices the human ability to detect changes are far less than when they are looking at a bit monitor with a large aspect ratio.</p>\n<p>To achieve this you can use the <code class=\"language-text\">srcset</code> and <code class=\"language-text\">width descriptors</code> attribute in <code class=\"language-text\">HTML</code>. With this, you can mention multiple screen sizes and specify which image to use for each size.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 800px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/dbcaa7867cc1481e522b666ffbd0e07f/5a190/srcset-width-descriptors.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 56.29629629629629%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAABl0lEQVR42o1Sa2+iQBTl//+apn9g06TWWpWHUoQqMojIS3AQFRhmYA/VsM1+2OzNzWQe59w59yG1Xfef/tNwFG0r/fXcb2DD5d2+oXNZllXV8/0ojq+3G8A9mQtRXC70nGO9XK9VVZ2LAvsTpQDR/FxcbmVVJ1mW+f5OX+ry3DAMVVMlBCirKghDd7eDh1HkHw5739/YNtw/BEHoEqLYjnYOvC7LRBS2cdQ2Tc1YT8Y/W8cBFmtyPK43m53nYYV9TOcbW7Ptt5U5jj3S0hM7ZSw4iKZ5yH5k26fWxUlirFbEdU3LWupLRVUcsjCMF90YV/QkioJnKT8mgnMxkFEPZA5ymmVf6zVxCUKsTFNRVcdRPz9/fdmzEprTtIljUZZ3ljT0QHz/fExTcKDfsixtoU1nU4I45pu2eC1oUgf+wOzJZVl6+z3Nc8bYXfZS11G298lEVpTRaAT9DplNJs/j8ZNH1qKnPXopVXUNnUBAIdD2dgs+VOAe9YQQmlPWsJpVOHLOf07BH9kN5+gZWgPyMEbdP+an634Dt35n+UM7BVEAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Cat picture using srcset\"\n        title=\"\"\n        src=\"/static/dbcaa7867cc1481e522b666ffbd0e07f/5a190/srcset-width-descriptors.png\"\n        srcset=\"/static/dbcaa7867cc1481e522b666ffbd0e07f/01bf6/srcset-width-descriptors.png 270w,\n/static/dbcaa7867cc1481e522b666ffbd0e07f/07484/srcset-width-descriptors.png 540w,\n/static/dbcaa7867cc1481e522b666ffbd0e07f/5a190/srcset-width-descriptors.png 800w\"\n        sizes=\"(max-width: 800px) 100vw, 800px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<p>When you use width descriptors, you’re providing the browser with a list of images and their true width so that it can select the best source based on the viewport size.</p>\n<h2 id=\"using-svgs\" style=\"position:relative;\"><a href=\"#using-svgs\" aria-label=\"using svgs permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Using SVGs</h2>\n<p>SVG is a scalable vector format which works great for logos, icons, text, and simple images. Here are a couple reasons why you would consider using them:</p>\n<ul>\n<li>SVGs are automatically scalable in both browsers and photo editing tools. This is a dream for a web and graphic designers!</li>\n<li>Google indexes SVGs, the same way it does PNGs and JPGs, so you don’t have to worry about SEO.</li>\n<li>SVGs are traditionally (not always) smaller in file size than PNGs or JPGs. This can result in faster load times.</li>\n</ul>\n<p>Here is an example to show you how much difference it can have (Images from <a href=\"https://genkihagata.com\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://genkihagata.com</a>):</p>\n<table>\n<thead>\n<tr>\n<th align=\"center\"><strong>JPEG</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td align=\"center\"><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1080px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/39d7d939e8db298746ac301d7cd1204d/eea4a/boatscape_b.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 41.85185185185185%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAME/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAHRMubA/8QAFhABAQEAAAAAAAAAAAAAAAAAEQEA/9oACAEBAAEFAmYizf/EABYRAQEBAAAAAAAAAAAAAAAAAAARAf/aAAgBAwEBPwGrr//EABYRAAMAAAAAAAAAAAAAAAAAAAABEv/aAAgBAgEBPwGUSj//xAAXEAADAQAAAAAAAAAAAAAAAAAAATEQ/9oACAEBAAY/ApkR/8QAGhABAAIDAQAAAAAAAAAAAAAAAQARIUFRgf/aAAgBAQABPyFTWLWrHIEUF5P/2gAMAwEAAgADAAAAEPQP/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAh/9oACAEDAQE/EFpsv//EABcRAQEBAQAAAAAAAAAAAAAAAAEAIWH/2gAIAQIBAT8QAcuN/8QAGhABAAIDAQAAAAAAAAAAAAAAAQARQXGRsf/aAAgBAQABPxCsV62eSzOiuwUOMBn/2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"JPG\"\n        title=\"\"\n        src=\"/static/39d7d939e8db298746ac301d7cd1204d/47311/boatscape_b.jpg\"\n        srcset=\"/static/39d7d939e8db298746ac301d7cd1204d/6f81f/boatscape_b.jpg 270w,\n/static/39d7d939e8db298746ac301d7cd1204d/09d21/boatscape_b.jpg 540w,\n/static/39d7d939e8db298746ac301d7cd1204d/47311/boatscape_b.jpg 1080w,\n/static/39d7d939e8db298746ac301d7cd1204d/eea4a/boatscape_b.jpg 1280w\"\n        sizes=\"(max-width: 1080px) 100vw, 1080px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></td>\n</tr>\n<tr>\n<td align=\"center\">Size: 81.4KB</td>\n</tr>\n</tbody>\n</table>\n<br/>\n<table>\n<thead>\n<tr>\n<th align=\"center\"><strong>PNG</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td align=\"center\"><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1080px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/6cafe49417919c68012b51e78b9ac1d0/21b4d/boatscape_b.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 41.85185185185185%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABo0lEQVR42n3L22vTYBgG8PyDu/bC3enFcKtaJE0P6bYcvjRdsiz5cq5J2m8zS7vm4JrYuY0dCjsgSEHBMVBhHYwpKHihVyKYiReiIPx4L97nebBUKRz1yC2P8JeLkC3J1COeJTm6tgjoGsdX58lipXoPr80US3cLD2/dmZ2anpkrFtpmuetVsfcHzOSYn5w0z3eZWMfXJHzDqGSrC8oSydLzCwxdpSiiTs7hlduzpQdl4nATfBiL39+u/HgnYZMRmIwWL4/A1Yulj2Px82vpyxvp67l8/VLYjzlRblRY7n6dqQHqechcnDa/nQmfXolnx+bh7hqWpNF2ZI4CerRaPkD4HiLGG8QzVH+KqEHAmZZQF2QciIIqJZHVQXA9sJM07kTbTn8HM7pDPdjS/dR0OoaqqCq0ZR5CpanaTaOtoNDqDnQ/Uf0B9IfwSaYFw3xi97JWL8OAGwI3Al4M2psAZRxKzZb12NbEdr+B0oaX5BHnJdzNjX7J+yHrRjnsZvlbCJxcf8WwoAZlTeNb68CN/yj8DfvnFfKGy+tOrqE7oNX9z/gnMBIhqzkG0R0AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"JPG\"\n        title=\"\"\n        src=\"/static/6cafe49417919c68012b51e78b9ac1d0/302a4/boatscape_b.png\"\n        srcset=\"/static/6cafe49417919c68012b51e78b9ac1d0/01bf6/boatscape_b.png 270w,\n/static/6cafe49417919c68012b51e78b9ac1d0/07484/boatscape_b.png 540w,\n/static/6cafe49417919c68012b51e78b9ac1d0/302a4/boatscape_b.png 1080w,\n/static/6cafe49417919c68012b51e78b9ac1d0/21b4d/boatscape_b.png 1280w\"\n        sizes=\"(max-width: 1080px) 100vw, 1080px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></td>\n</tr>\n<tr>\n<td align=\"center\">Size: 85.1KB</td>\n</tr>\n</tbody>\n</table>\n<br/>\n<table>\n<thead>\n<tr>\n<th align=\"center\"><strong>SVG</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td align=\"center\"><svg  xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1280 534.7\" enable-background=\"new 0 0 1280 534.7\"><g><linearGradient id=\"a\" gradientUnits=\"userSpaceOnUse\" x1=\"131\" y1=\"692.654\" x2=\"1149\" y2=\"-161.548\"><stop offset=\"0\" stop-color=\"#D2864A\"></stop><stop offset=\".576\" stop-color=\"#7A898D\"></stop><stop offset=\"1\" stop-color=\"#3C4A57\"></stop></linearGradient><path fill=\"url(#a)\" d=\"M0-5.4h1280v542H0z\"></path></g><g><linearGradient id=\"b\" gradientUnits=\"userSpaceOnUse\" x1=\"294.611\" y1=\"236.036\" x2=\"184.739\" y2=\"-65.835\"><stop offset=\"0\" stop-color=\"#D2864A\"></stop><stop offset=\".197\" stop-color=\"#CE844A\"></stop><stop offset=\".383\" stop-color=\"#C3804B\"></stop><stop offset=\".564\" stop-color=\"#B0784D\"></stop><stop offset=\".743\" stop-color=\"#956D4F\"></stop><stop offset=\".918\" stop-color=\"#736052\"></stop><stop offset=\"1\" stop-color=\"#605854\"></stop></linearGradient><path opacity=\".22\" fill=\"url(#b)\" d=\"M385.1 203.1h-105L94.2-32.9h105l164.6 209.1z\"></path><linearGradient id=\"c\" gradientUnits=\"userSpaceOnUse\" x1=\"358.667\" y1=\"200.556\" x2=\"399.383\" y2=\"-30.355\"><stop offset=\"0\" stop-color=\"#D2864A\"></stop><stop offset=\".197\" stop-color=\"#CE844A\"></stop><stop offset=\".383\" stop-color=\"#C3804B\"></stop><stop offset=\".564\" stop-color=\"#B0784D\"></stop><stop offset=\".743\" stop-color=\"#956D4F\"></stop><stop offset=\".918\" stop-color=\"#736052\"></stop><stop offset=\"1\" stop-color=\"#605854\"></stop></linearGradient><path opacity=\".22\" fill=\"url(#c)\" d=\"M466.1 203.1h-93l-9.3-26.9L292-32.9h93l50.7 147.5 18.7 54.6 5 14.5z\"></path><linearGradient id=\"d\" gradientUnits=\"userSpaceOnUse\" x1=\"443.874\" y1=\"216.529\" x2=\"539.545\" y2=\"-46.325\"><stop offset=\"0\" stop-color=\"#D2864A\"></stop><stop offset=\".288\" stop-color=\"#D0854A\"></stop><stop offset=\".444\" stop-color=\"#C8824B\"></stop><stop offset=\".569\" stop-color=\"#BA7C4C\"></stop><stop offset=\".676\" stop-color=\"#A7754E\"></stop><stop offset=\".773\" stop-color=\"#8E6B50\"></stop><stop offset=\".862\" stop-color=\"#6F5E53\"></stop><stop offset=\".944\" stop-color=\"#4B5056\"></stop><stop offset=\".973\" stop-color=\"#3C4A57\"></stop></linearGradient><path opacity=\".22\" fill=\"url(#d)\" d=\"M576.4-32.9L528 116.7 512.7 164 500 203.1h-93l28.7-88.5 47.7-147.5z\"></path><linearGradient id=\"e\" gradientUnits=\"userSpaceOnUse\" x1=\"608.784\" y1=\"238.684\" x2=\"662.946\" y2=\"-68.483\"><stop offset=\"0\" stop-color=\"#D2864A\"></stop><stop offset=\".2\" stop-color=\"#CF854A\"></stop><stop offset=\".358\" stop-color=\"#C5814B\"></stop><stop offset=\".502\" stop-color=\"#B47A4D\"></stop><stop offset=\".637\" stop-color=\"#9D714F\"></stop><stop offset=\".766\" stop-color=\"#7E6451\"></stop><stop offset=\".89\" stop-color=\"#595654\"></stop><stop offset=\".973\" stop-color=\"#3C4A57\"></stop></linearGradient><path opacity=\".22\" fill=\"url(#e)\" d=\"M864.8-32.9l-194 138.2-137.2 97.8H407l47.4-34 73.6-52.4L737.4-32.9z\"></path><linearGradient id=\"f\" gradientUnits=\"userSpaceOnUse\" x1=\"712.124\" y1=\"345.401\" x2=\"1012.582\" y2=\"-175.007\"><stop offset=\".456\" stop-color=\"#D2864A\"></stop><stop offset=\".479\" stop-color=\"#C8824B\"></stop><stop offset=\".599\" stop-color=\"#966E4F\"></stop><stop offset=\".712\" stop-color=\"#6F5E53\"></stop><stop offset=\".815\" stop-color=\"#535355\"></stop><stop offset=\".905\" stop-color=\"#424C56\"></stop><stop offset=\".973\" stop-color=\"#3C4A57\"></stop></linearGradient><path opacity=\".12\" fill=\"url(#f)\" d=\"M1258.7-32.9l-672.6 246h-94.4l-25.7-9.8 55.6-10 522-226.2z\"></path><path fill=\"#EBD08D\" d=\"M1301.9 59.6c0-14.5-11.7-26.2-26.2-26.2-7.3 0-14 3-18.7 7.9-6.6-5.7-15.2-9.2-24.6-9.2-10 0-19 3.9-25.8 10.2-6.5-2.5-13.5-3.8-20.9-3.8-17.4 0-33 7.5-43.8 19.5-2.6-1.2-5.5-2-8.6-2-11 0-19.9 8.9-19.9 19.9 0 1.6.2 3.1.6 4.6-3.3-1.1-6.7-1.7-10.4-1.7-11.5 0-21.6 6-27.4 15.1-1.2-6.6-7-11.5-13.9-11.5-7.8 0-14.1 6.3-14.1 14.1v.3c-1.8-.5-3.8-.7-5.8-.7-13.4 0-24.2 10.8-24.2 24.2 0 2.9.5 5.6 1.4 8.2-3 1.3-5.1 4.3-5.1 7.7 0 .3 0 .6.1.9-3-1.8-6.5-2.9-10.3-2.9-10.3 0-18.7 7.9-19.5 18-4.4-4.2-10.3-6.8-16.8-6.8-13.4 0-24.2 10.8-24.2 24.2v.2l-.9.3c-3.2-2.5-7.2-3.9-11.5-3.9-1 0-2 .1-3 .3-3.5-2.9-8-4.6-12.9-4.6-9.8 0-18 7-19.8 16.4-5.1 2.4-9.1 6.7-10.9 12.1-1.5-.5-3.1-.8-4.8-.8-8.4 0-15.3 6.8-15.3 15.2 0 8.4 6.8 15.2 15.3 15.2h407V83.3c8.8-4.2 14.9-13.2 14.9-23.7z\"></path><path fill=\"#859DAD\" d=\"M-9 303.5h1289v233.1H-9z\"></path><circle fill=\"#F2AC66\" cx=\"419.6\" cy=\"203.1\" r=\"46.4\"></circle><path opacity=\".8\" fill=\"#EBD08D\" d=\"M274.2 121.2c-5.9 0-11.6 1-16.8 2.9 5.3-4 8.7-10.4 8.7-17.5 0-12.1-9.8-22-22-22-6.5 0-12.4 2.9-16.4 7.4l-1.9-.2c1.2-3.3 1.9-6.9 1.9-10.6 0-16.9-13.7-30.5-30.5-30.5-9.8 0-18.5 4.6-24.1 11.8-5.3-12.5-17.6-21.3-32.1-21.3-10 0-19 4.2-25.3 10.9-3.3-12.6-14.8-21.9-28.5-21.9-16.3 0-29.5 13.2-29.5 29.5 0 1.6.1 3.2.4 4.8-8.3 1.3-15.8 5-21.7 10.3-2.9-.5-5.9-.8-9-.8-28.8 0-52.1 23.3-52.1 52 0 14.6 5.7 27.8 15.7 37.3v59.8h283.2c28.1 0 50.9-22.8 50.9-51 0-28.1-22.8-50.9-50.9-50.9z\"></path><path fill=\"#A0ADB7\" d=\"M25.3 217.4l29.9-6.1 18 16.5 17.8 4.3 9 8h13l5 7 44 15 13-8 15 3 7 10.2 15 4.8 5 7.7 25 5.3 12 11 17-7h8l17 7h26l19 5 36-8 12 1 18 13 64-10 19-3h16l20 4 9 2h20l10-7h18l9 1h15l10-1.8 8-12.2h24l25-7 15 1.9 11-7.9h31l26 .2 16-3.4 23 8.2 38 2 53-21 12-3 10-7h12l41 7 31 5 20-12 28 4 22-11h11l71-33 18-5 26-8 16-9 10-19 26 7 26.2 3 19.8 1v143H-9v-100l19-4z\"></path><path fill=\"#EBD08D\" d=\"M673.9 209.2c-1.4 0-2.7.3-3.8 1l-1-.4c0-.4.1-.8.1-1.2 0-7.4-6-13.5-13.5-13.5-2.7 0-5.2.8-7.3 2.1-2.2-8.6-10-15.1-19.3-15.1-5.1 0-9.7 1.9-13.2 5-3-10.6-12.7-18.4-24.2-18.4-.6 0-1.2 0-1.8.1-4.1-12.1-15.5-20.8-28.9-20.8-4.8 0-9.4 1.1-13.4 3.1-4.6-4.6-11-7.5-18-7.6-1-9.8-9.3-17.4-19.3-17.4-8.5 0-15.7 5.5-18.3 13.1-2.5-5.7-7-10.3-12.7-12.8 2.3-2.9 3.7-6.6 3.7-10.5 0-9.4-7.6-17-17-17s-17 7.6-17 17c-10 2.6-17.4 11.8-17.4 22.6 0 1.7.2 3.3.5 4.8-4.4-2.8-9.6-4.4-15.2-4.4-3.9 0-7.5.8-10.9 2.2-3.8-7.2-11.3-12.1-20-12.1-5.1 0-9.8 1.7-13.5 4.5-3.8-5.6-10.2-9.2-17.4-9.2-11.6 0-21 9.4-21 21 0 1.5.2 3 .5 4.5-.6-.1-1.2-.1-1.9-.1-7.9 0-14.3 6.1-14.8 13.9-3.1-1.2-6.5-1.9-10-1.9-10.8 0-20.1 6.4-24.4 15.5-3.2-1.8-6.9-2.9-10.9-2.9-12 0-21.8 9.8-21.8 21.8l-3.1.4c-1.9-1.5-4.2-2.4-6.8-2.4-3.6 0-6.9 1.8-8.8 4.6l-4.2.6c-2.2-3.1-5.9-5.2-10-5.2-5.3 0-9.9 3.4-11.6 8.2l-1.7.2c-1.9-2.7-5-4.5-8.5-4.5-3.7 0-7 2-8.8 4.9-1.6-4.3-5.7-7.4-10.5-7.4-6.2 0-11.2 5-11.2 11.2v.2c-1.6-2.9-4.7-4.9-8.3-4.9-4.8 0-8.8 3.6-9.4 8.2-1.6-1.8-4-2.9-6.6-2.9-4.9 0-8.8 4-8.8 8.9 0 4.5 2.8 8.3 7.8 8.8v.2h533.9c4.4 0 7.9-3.6 7.9-8-.3-4.4-3.8-8-8.2-8z\"></path><linearGradient id=\"g\" gradientUnits=\"userSpaceOnUse\" x1=\"535.212\" y1=\"308.863\" x2=\"547.588\" y2=\"544.998\"><stop offset=\"0\" stop-color=\"#D2864A\"></stop><stop offset=\".973\" stop-color=\"#7A898D\"></stop></linearGradient><path opacity=\".37\" fill=\"url(#g)\" d=\"M709.1 536.5l-324-1.8 12-218.6h75z\"></path></g></svg></td>\n</tr>\n<tr>\n<td align=\"center\">Size: 6.1KB</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"lazy-loading-images\" style=\"position:relative;\"><a href=\"#lazy-loading-images\" aria-label=\"lazy loading images permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Lazy loading images</h2>\n<p>When we consider all we’ve gone through so far, you would realise at some point that it is not enough to make images smaller anymore. Especially if you have too many of them in the page. This is where we need to make sure our web page loads with them fast instead.</p>\n<p>This is where lazy loading comes to rescue. Let’s see a demonstration on how it works (video from <a href=\"https://css-tricks.com\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">CSS Tricks</a>):</p>\n<div class=\"gatsby-resp-iframe-wrapper\" style=\"padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem\" > <iframe id=\"ytplayer\" type=\"text/html\" src=\"https://www.youtube.com/embed/CPmNHj9a0JI?autoplay=0&amp;origin=https://yashints.dev\" frameborder=\"0\" style=\" position: absolute; top: 0; left: 0; width: 100%; height: 100%; \"></iframe> </div>\n<h3 id=\"what-is-it\" style=\"position:relative;\"><a href=\"#what-is-it\" aria-label=\"what is it permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is it?</h3>\n<p>Lazy loading images is simply the act of not loading images until a later point in time. It is a technique in web development which applies to many other form of resources, but here we are focusing on images.</p>\n<blockquote>\n<p><strong>Wikipedia:</strong> Lazy loading is a design pattern commonly used in computer programming to defer initialization of an object until the point at which it is needed. It can contribute to efficiency in the program’s operation if properly and appropriately used.</p>\n</blockquote>\n<h3 id=\"how-it-is-done\" style=\"position:relative;\"><a href=\"#how-it-is-done\" aria-label=\"how it is done permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How it is done</h3>\n<p>Imagine you have a very long page with a lot of images. Why would the image at the bottom of the page get loaded if the user cannot see it. As simple as that, you can load the image on an event like when that part of the page is visible (using scroll event handler) or any other event. But not just when the page loads.</p>\n<p>Apart from that, if the user never scrolls down, that image wouldn’t get loaded, resulting in saving some network traffic and data usage for the end user.</p>\n<p>You will start to see a lot of benefits considering how much impact this has on the overall page load time and speed.</p>\n<h3 id=\"lazy-loading-techniques\" style=\"position:relative;\"><a href=\"#lazy-loading-techniques\" aria-label=\"lazy loading techniques permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Lazy loading techniques</h3>\n<p>There are two common ways of loading an image on a page, using an <code class=\"language-text\">img</code> tag, and CSS <code class=\"language-text\">background-image</code>. Let’s start with the image tag.</p>\n<h4 id=\"image-tag\" style=\"position:relative;\"><a href=\"#image-tag\" aria-label=\"image tag permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Image tag</h4>\n<p>Here is a simple image tag we normally use to load an image:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"87013735925598620000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<img src=&quot;/path/to/some/cat/image.jpg&quot; />`, `87013735925598620000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>/path/to/some/cat/image.jpg<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>The markup for lazy loading images is pretty similar. The <code class=\"language-text\">src</code> attribute is the trigger for the browser to send a network request and fetch the image. No matter if this is the first or the 50th image on your page.</p>\n<p>To defer the load, simply use <code class=\"language-text\">data-src</code> attribute.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"92257348909504040000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<img data-src=&quot;/path/to/some/cat/image.jpg&quot; />`, `92257348909504040000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">data-src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>/path/to/some/cat/image.jpg<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>Since the <code class=\"language-text\">src</code> is empty the browser doesn’t load the image when the tag is rendered. Now it is just the matter of triggering the load which normally is done when the image is entered the viewport.</p>\n<p>We can use events like <code class=\"language-text\">scroll</code>, <code class=\"language-text\">resize</code>, and <code class=\"language-text\">orientationChange</code> to figure out when to trigger the load. The scroll event is pretty clear, when the user scrolls if the image tag is on the page then we trigger the load and tell the browser to fetch the image. However, the resize and orientation change events are equally important. The resize is when the user changes the window size like when they make the window smaller. The orientation change happens when the user rotates their device.</p>\n<p>Once we hook into these events, we can enable lazy loading and the result is really good:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"66184999649395860000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`document.addEventListener(\r\n  'DOMContentLoaded',\r\n  function() {\r\n    var lazyloadImages = document.querySelectorAll(\r\n      'img.lazy'\r\n    )\r\n    var lazyloadThrottleTimeout\r\n\r\n    function lazyload() {\r\n      if (lazyloadThrottleTimeout) {\r\n        clearTimeout(lazyloadThrottleTimeout)\r\n      }\r\n\r\n      lazyloadThrottleTimeout = setTimeout(\r\n        function() {\r\n          var scrollTop = window.pageYOffset\r\n          lazyloadImages.forEach(function(img) {\r\n            if (\r\n              img.offsetTop <\r\n              window.innerHeight + scrollTop\r\n            ) {\r\n              img.src = img.dataset.src\r\n              img.classList.remove('lazy')\r\n            }\r\n          })\r\n          if (lazyloadImages.length == 0) {\r\n            document.removeEventListener(\r\n              'scroll',\r\n              lazyload\r\n            )\r\n            window.removeEventListener(\r\n              'resize',\r\n              lazyload\r\n            )\r\n            window.removeEventListener(\r\n              'orientationChange',\r\n              lazyload\r\n            )\r\n          }\r\n        },\r\n        20\r\n      )\r\n    }\r\n\r\n    document.addEventListener('scroll', lazyload)\r\n    window.addEventListener('resize', lazyload)\r\n    window.addEventListener(\r\n      'orientationChange',\r\n      lazyload\r\n    )\r\n  }\r\n)`, `66184999649395860000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\">document<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span>\r\n  <span class=\"token string\">'DOMContentLoaded'</span><span class=\"token punctuation\">,</span>\r\n  <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n    <span class=\"token keyword\">var</span> lazyloadImages <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelectorAll</span><span class=\"token punctuation\">(</span>\r\n      <span class=\"token string\">'img.lazy'</span>\r\n    <span class=\"token punctuation\">)</span>\r\n    <span class=\"token keyword\">var</span> lazyloadThrottleTimeout\r\n\r\n    <span class=\"token keyword\">function</span> <span class=\"token function\">lazyload</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>lazyloadThrottleTimeout<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n        <span class=\"token function\">clearTimeout</span><span class=\"token punctuation\">(</span>lazyloadThrottleTimeout<span class=\"token punctuation\">)</span>\r\n      <span class=\"token punctuation\">}</span>\r\n\r\n      lazyloadThrottleTimeout <span class=\"token operator\">=</span> <span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span>\r\n        <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n          <span class=\"token keyword\">var</span> scrollTop <span class=\"token operator\">=</span> window<span class=\"token punctuation\">.</span>pageYOffset\r\n          lazyloadImages<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">img</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>\r\n              img<span class=\"token punctuation\">.</span>offsetTop <span class=\"token operator\">&lt;</span>\r\n              window<span class=\"token punctuation\">.</span>innerHeight <span class=\"token operator\">+</span> scrollTop\r\n            <span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n              img<span class=\"token punctuation\">.</span>src <span class=\"token operator\">=</span> img<span class=\"token punctuation\">.</span>dataset<span class=\"token punctuation\">.</span>src\r\n              img<span class=\"token punctuation\">.</span>classList<span class=\"token punctuation\">.</span><span class=\"token function\">remove</span><span class=\"token punctuation\">(</span><span class=\"token string\">'lazy'</span><span class=\"token punctuation\">)</span>\r\n            <span class=\"token punctuation\">}</span>\r\n          <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\r\n          <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>lazyloadImages<span class=\"token punctuation\">.</span>length <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n            document<span class=\"token punctuation\">.</span><span class=\"token function\">removeEventListener</span><span class=\"token punctuation\">(</span>\r\n              <span class=\"token string\">'scroll'</span><span class=\"token punctuation\">,</span>\r\n              lazyload\r\n            <span class=\"token punctuation\">)</span>\r\n            window<span class=\"token punctuation\">.</span><span class=\"token function\">removeEventListener</span><span class=\"token punctuation\">(</span>\r\n              <span class=\"token string\">'resize'</span><span class=\"token punctuation\">,</span>\r\n              lazyload\r\n            <span class=\"token punctuation\">)</span>\r\n            window<span class=\"token punctuation\">.</span><span class=\"token function\">removeEventListener</span><span class=\"token punctuation\">(</span>\r\n              <span class=\"token string\">'orientationChange'</span><span class=\"token punctuation\">,</span>\r\n              lazyload\r\n            <span class=\"token punctuation\">)</span>\r\n          <span class=\"token punctuation\">}</span>\r\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\r\n        <span class=\"token number\">20</span>\r\n      <span class=\"token punctuation\">)</span>\r\n    <span class=\"token punctuation\">}</span>\r\n\r\n    document<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">'scroll'</span><span class=\"token punctuation\">,</span> lazyload<span class=\"token punctuation\">)</span>\r\n    window<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">'resize'</span><span class=\"token punctuation\">,</span> lazyload<span class=\"token punctuation\">)</span>\r\n    window<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span>\r\n      <span class=\"token string\">'orientationChange'</span><span class=\"token punctuation\">,</span>\r\n      lazyload\r\n    <span class=\"token punctuation\">)</span>\r\n  <span class=\"token punctuation\">}</span>\r\n<span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<h3 id=\"using-intersection-api\" style=\"position:relative;\"><a href=\"#using-intersection-api\" aria-label=\"using intersection api permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Using intersection API</h3>\n<p>Let’s see what this API offers:</p>\n<blockquote>\n<p>The Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document’s viewport.</p>\n</blockquote>\n<p>Opposite to the previous technique where you might see some performance impact on the page because of all of those event handlers, this approach is relatively new.</p>\n<p>This API removes the previous performance hit by doing the math and delivering a very efficient way to call a callback function when the resource is on screen:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"68344103345425600000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`document.addEventListener(\r\n  'DOMContentLoaded',\r\n  function() {\r\n    var lazyloadImages\r\n\r\n    if ('IntersectionObserver' in window) {\r\n      lazyloadImages = document.querySelectorAll(\r\n        '.lazy'\r\n      )\r\n      var imageObserver = new IntersectionObserver(\r\n        function(entries, observer) {\r\n          entries.forEach(function(entry) {\r\n            if (entry.isIntersecting) {\r\n              var image = entry.target\r\n              image.src = image.dataset.src\r\n              image.classList.remove('lazy')\r\n              imageObserver.unobserve(image)\r\n            }\r\n          })\r\n        }\r\n      )\r\n\r\n      lazyloadImages.forEach(function(image) {\r\n        imageObserver.observe(image)\r\n      })\r\n    } else {\r\n      var lazyloadThrottleTimeout\r\n      lazyloadImages = document.querySelectorAll(\r\n        '.lazy'\r\n      )\r\n\r\n      function lazyload() {\r\n        if (lazyloadThrottleTimeout) {\r\n          clearTimeout(lazyloadThrottleTimeout)\r\n        }\r\n\r\n        lazyloadThrottleTimeout = setTimeout(\r\n          function() {\r\n            var scrollTop = window.pageYOffset\r\n            lazyloadImages.forEach(function(img) {\r\n              if (\r\n                img.offsetTop <\r\n                window.innerHeight + scrollTop\r\n              ) {\r\n                img.src = img.dataset.src\r\n                img.classList.remove('lazy')\r\n              }\r\n            })\r\n            if (lazyloadImages.length == 0) {\r\n              document.removeEventListener(\r\n                'scroll',\r\n                lazyload\r\n              )\r\n              window.removeEventListener(\r\n                'resize',\r\n                lazyload\r\n              )\r\n              window.removeEventListener(\r\n                'orientationChange',\r\n                lazyload\r\n              )\r\n            }\r\n          },\r\n          20\r\n        )\r\n      }\r\n\r\n      document.addEventListener(\r\n        'scroll',\r\n        lazyload\r\n      )\r\n      window.addEventListener('resize', lazyload)\r\n      window.addEventListener(\r\n        'orientationChange',\r\n        lazyload\r\n      )\r\n    }\r\n  }\r\n)`, `68344103345425600000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\">document<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span>\r\n  <span class=\"token string\">'DOMContentLoaded'</span><span class=\"token punctuation\">,</span>\r\n  <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n    <span class=\"token keyword\">var</span> lazyloadImages\r\n\r\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token string\">'IntersectionObserver'</span> <span class=\"token keyword\">in</span> window<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n      lazyloadImages <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelectorAll</span><span class=\"token punctuation\">(</span>\r\n        <span class=\"token string\">'.lazy'</span>\r\n      <span class=\"token punctuation\">)</span>\r\n      <span class=\"token keyword\">var</span> imageObserver <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">IntersectionObserver</span><span class=\"token punctuation\">(</span>\r\n        <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">entries<span class=\"token punctuation\">,</span> observer</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n          entries<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">entry</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>entry<span class=\"token punctuation\">.</span>isIntersecting<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n              <span class=\"token keyword\">var</span> image <span class=\"token operator\">=</span> entry<span class=\"token punctuation\">.</span>target\r\n              image<span class=\"token punctuation\">.</span>src <span class=\"token operator\">=</span> image<span class=\"token punctuation\">.</span>dataset<span class=\"token punctuation\">.</span>src\r\n              image<span class=\"token punctuation\">.</span>classList<span class=\"token punctuation\">.</span><span class=\"token function\">remove</span><span class=\"token punctuation\">(</span><span class=\"token string\">'lazy'</span><span class=\"token punctuation\">)</span>\r\n              imageObserver<span class=\"token punctuation\">.</span><span class=\"token function\">unobserve</span><span class=\"token punctuation\">(</span>image<span class=\"token punctuation\">)</span>\r\n            <span class=\"token punctuation\">}</span>\r\n          <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\r\n        <span class=\"token punctuation\">}</span>\r\n      <span class=\"token punctuation\">)</span>\r\n\r\n      lazyloadImages<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">image</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n        imageObserver<span class=\"token punctuation\">.</span><span class=\"token function\">observe</span><span class=\"token punctuation\">(</span>image<span class=\"token punctuation\">)</span>\r\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\r\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\r\n      <span class=\"token keyword\">var</span> lazyloadThrottleTimeout\r\n      lazyloadImages <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelectorAll</span><span class=\"token punctuation\">(</span>\r\n        <span class=\"token string\">'.lazy'</span>\r\n      <span class=\"token punctuation\">)</span>\r\n\r\n      <span class=\"token keyword\">function</span> <span class=\"token function\">lazyload</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>lazyloadThrottleTimeout<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n          <span class=\"token function\">clearTimeout</span><span class=\"token punctuation\">(</span>lazyloadThrottleTimeout<span class=\"token punctuation\">)</span>\r\n        <span class=\"token punctuation\">}</span>\r\n\r\n        lazyloadThrottleTimeout <span class=\"token operator\">=</span> <span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span>\r\n          <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n            <span class=\"token keyword\">var</span> scrollTop <span class=\"token operator\">=</span> window<span class=\"token punctuation\">.</span>pageYOffset\r\n            lazyloadImages<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">img</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n              <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>\r\n                img<span class=\"token punctuation\">.</span>offsetTop <span class=\"token operator\">&lt;</span>\r\n                window<span class=\"token punctuation\">.</span>innerHeight <span class=\"token operator\">+</span> scrollTop\r\n              <span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n                img<span class=\"token punctuation\">.</span>src <span class=\"token operator\">=</span> img<span class=\"token punctuation\">.</span>dataset<span class=\"token punctuation\">.</span>src\r\n                img<span class=\"token punctuation\">.</span>classList<span class=\"token punctuation\">.</span><span class=\"token function\">remove</span><span class=\"token punctuation\">(</span><span class=\"token string\">'lazy'</span><span class=\"token punctuation\">)</span>\r\n              <span class=\"token punctuation\">}</span>\r\n            <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\r\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>lazyloadImages<span class=\"token punctuation\">.</span>length <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n              document<span class=\"token punctuation\">.</span><span class=\"token function\">removeEventListener</span><span class=\"token punctuation\">(</span>\r\n                <span class=\"token string\">'scroll'</span><span class=\"token punctuation\">,</span>\r\n                lazyload\r\n              <span class=\"token punctuation\">)</span>\r\n              window<span class=\"token punctuation\">.</span><span class=\"token function\">removeEventListener</span><span class=\"token punctuation\">(</span>\r\n                <span class=\"token string\">'resize'</span><span class=\"token punctuation\">,</span>\r\n                lazyload\r\n              <span class=\"token punctuation\">)</span>\r\n              window<span class=\"token punctuation\">.</span><span class=\"token function\">removeEventListener</span><span class=\"token punctuation\">(</span>\r\n                <span class=\"token string\">'orientationChange'</span><span class=\"token punctuation\">,</span>\r\n                lazyload\r\n              <span class=\"token punctuation\">)</span>\r\n            <span class=\"token punctuation\">}</span>\r\n          <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\r\n          <span class=\"token number\">20</span>\r\n        <span class=\"token punctuation\">)</span>\r\n      <span class=\"token punctuation\">}</span>\r\n\r\n      document<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span>\r\n        <span class=\"token string\">'scroll'</span><span class=\"token punctuation\">,</span>\r\n        lazyload\r\n      <span class=\"token punctuation\">)</span>\r\n      window<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">'resize'</span><span class=\"token punctuation\">,</span> lazyload<span class=\"token punctuation\">)</span>\r\n      window<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span>\r\n        <span class=\"token string\">'orientationChange'</span><span class=\"token punctuation\">,</span>\r\n        lazyload\r\n      <span class=\"token punctuation\">)</span>\r\n    <span class=\"token punctuation\">}</span>\r\n  <span class=\"token punctuation\">}</span>\r\n<span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>We attach the observer on all the images we want to be lazy loaded. When the API detects that the element has entered the viewport, using the <code class=\"language-text\">isIntersecting</code> property, we pick the URL from the <code class=\"language-text\">data-src</code> attribute and move it to the <code class=\"language-text\">src</code> attribute for the browser to trigger the image load like before. Once this is done, we remove the lazy class from the image and also remove the observer from that image.</p>\n<h3 id=\"css-background-image\" style=\"position:relative;\"><a href=\"#css-background-image\" aria-label=\"css background image permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>CSS background image</h3>\n<p>CSS background images are not as straightforward as the image tag. To load them the browser needs to build both the DOM tree and CSSDOM tree (<a href=\"/2018/09/29/web-perf-1\">see here</a>). If the CSS rule is applicable to the node the browser loads it, otherwise doesn’t. So all we need to do is to not give it a background property by default and add it when it’s visible:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"3999019304719153700\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`document.addEventListener(\r\n  'DOMContentLoaded',\r\n  function() {\r\n    var lazyloadImages\r\n\r\n    if ('IntersectionObserver' in window) {\r\n      lazyloadImages = document.querySelectorAll(\r\n        '.lazy'\r\n      )\r\n      var imageObserver = new IntersectionObserver(\r\n        function(entries, observer) {\r\n          entries.forEach(function(entry) {\r\n            if (entry.isIntersecting) {\r\n              var image = entry.target\r\n              image.classList.remove('lazy')\r\n              imageObserver.unobserve(image)\r\n            }\r\n          })\r\n        }\r\n      )\r\n\r\n      lazyloadImages.forEach(function(image) {\r\n        imageObserver.observe(image)\r\n      })\r\n    } else {\r\n      var lazyloadThrottleTimeout\r\n      lazyloadImages = document.querySelectorAll(\r\n        '.lazy'\r\n      )\r\n\r\n      function lazyload() {\r\n        if (lazyloadThrottleTimeout) {\r\n          clearTimeout(lazyloadThrottleTimeout)\r\n        }\r\n\r\n        lazyloadThrottleTimeout = setTimeout(\r\n          function() {\r\n            var scrollTop = window.pageYOffset\r\n            lazyloadImages.forEach(function(img) {\r\n              if (\r\n                img.offsetTop <\r\n                window.innerHeight + scrollTop\r\n              ) {\r\n                img.src = img.dataset.src\r\n                img.classList.remove('lazy')\r\n              }\r\n            })\r\n            if (lazyloadImages.length == 0) {\r\n              document.removeEventListener(\r\n                'scroll',\r\n                lazyload\r\n              )\r\n              window.removeEventListener(\r\n                'resize',\r\n                lazyload\r\n              )\r\n              window.removeEventListener(\r\n                'orientationChange',\r\n                lazyload\r\n              )\r\n            }\r\n          },\r\n          20\r\n        )\r\n      }\r\n\r\n      document.addEventListener(\r\n        'scroll',\r\n        lazyload\r\n      )\r\n      window.addEventListener('resize', lazyload)\r\n      window.addEventListener(\r\n        'orientationChange',\r\n        lazyload\r\n      )\r\n    }\r\n  }\r\n)`, `3999019304719153700`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\">document<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span>\r\n  <span class=\"token string\">'DOMContentLoaded'</span><span class=\"token punctuation\">,</span>\r\n  <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n    <span class=\"token keyword\">var</span> lazyloadImages\r\n\r\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token string\">'IntersectionObserver'</span> <span class=\"token keyword\">in</span> window<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n      lazyloadImages <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelectorAll</span><span class=\"token punctuation\">(</span>\r\n        <span class=\"token string\">'.lazy'</span>\r\n      <span class=\"token punctuation\">)</span>\r\n      <span class=\"token keyword\">var</span> imageObserver <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">IntersectionObserver</span><span class=\"token punctuation\">(</span>\r\n        <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">entries<span class=\"token punctuation\">,</span> observer</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n          entries<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">entry</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>entry<span class=\"token punctuation\">.</span>isIntersecting<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n              <span class=\"token keyword\">var</span> image <span class=\"token operator\">=</span> entry<span class=\"token punctuation\">.</span>target\r\n              image<span class=\"token punctuation\">.</span>classList<span class=\"token punctuation\">.</span><span class=\"token function\">remove</span><span class=\"token punctuation\">(</span><span class=\"token string\">'lazy'</span><span class=\"token punctuation\">)</span>\r\n              imageObserver<span class=\"token punctuation\">.</span><span class=\"token function\">unobserve</span><span class=\"token punctuation\">(</span>image<span class=\"token punctuation\">)</span>\r\n            <span class=\"token punctuation\">}</span>\r\n          <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\r\n        <span class=\"token punctuation\">}</span>\r\n      <span class=\"token punctuation\">)</span>\r\n\r\n      lazyloadImages<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">image</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n        imageObserver<span class=\"token punctuation\">.</span><span class=\"token function\">observe</span><span class=\"token punctuation\">(</span>image<span class=\"token punctuation\">)</span>\r\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\r\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\r\n      <span class=\"token keyword\">var</span> lazyloadThrottleTimeout\r\n      lazyloadImages <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelectorAll</span><span class=\"token punctuation\">(</span>\r\n        <span class=\"token string\">'.lazy'</span>\r\n      <span class=\"token punctuation\">)</span>\r\n\r\n      <span class=\"token keyword\">function</span> <span class=\"token function\">lazyload</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>lazyloadThrottleTimeout<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n          <span class=\"token function\">clearTimeout</span><span class=\"token punctuation\">(</span>lazyloadThrottleTimeout<span class=\"token punctuation\">)</span>\r\n        <span class=\"token punctuation\">}</span>\r\n\r\n        lazyloadThrottleTimeout <span class=\"token operator\">=</span> <span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span>\r\n          <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n            <span class=\"token keyword\">var</span> scrollTop <span class=\"token operator\">=</span> window<span class=\"token punctuation\">.</span>pageYOffset\r\n            lazyloadImages<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">img</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n              <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>\r\n                img<span class=\"token punctuation\">.</span>offsetTop <span class=\"token operator\">&lt;</span>\r\n                window<span class=\"token punctuation\">.</span>innerHeight <span class=\"token operator\">+</span> scrollTop\r\n              <span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n                img<span class=\"token punctuation\">.</span>src <span class=\"token operator\">=</span> img<span class=\"token punctuation\">.</span>dataset<span class=\"token punctuation\">.</span>src\r\n                img<span class=\"token punctuation\">.</span>classList<span class=\"token punctuation\">.</span><span class=\"token function\">remove</span><span class=\"token punctuation\">(</span><span class=\"token string\">'lazy'</span><span class=\"token punctuation\">)</span>\r\n              <span class=\"token punctuation\">}</span>\r\n            <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\r\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>lazyloadImages<span class=\"token punctuation\">.</span>length <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n              document<span class=\"token punctuation\">.</span><span class=\"token function\">removeEventListener</span><span class=\"token punctuation\">(</span>\r\n                <span class=\"token string\">'scroll'</span><span class=\"token punctuation\">,</span>\r\n                lazyload\r\n              <span class=\"token punctuation\">)</span>\r\n              window<span class=\"token punctuation\">.</span><span class=\"token function\">removeEventListener</span><span class=\"token punctuation\">(</span>\r\n                <span class=\"token string\">'resize'</span><span class=\"token punctuation\">,</span>\r\n                lazyload\r\n              <span class=\"token punctuation\">)</span>\r\n              window<span class=\"token punctuation\">.</span><span class=\"token function\">removeEventListener</span><span class=\"token punctuation\">(</span>\r\n                <span class=\"token string\">'orientationChange'</span><span class=\"token punctuation\">,</span>\r\n                lazyload\r\n              <span class=\"token punctuation\">)</span>\r\n            <span class=\"token punctuation\">}</span>\r\n          <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\r\n          <span class=\"token number\">20</span>\r\n        <span class=\"token punctuation\">)</span>\r\n      <span class=\"token punctuation\">}</span>\r\n\r\n      document<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span>\r\n        <span class=\"token string\">'scroll'</span><span class=\"token punctuation\">,</span>\r\n        lazyload\r\n      <span class=\"token punctuation\">)</span>\r\n      window<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">'resize'</span><span class=\"token punctuation\">,</span> lazyload<span class=\"token punctuation\">)</span>\r\n      window<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span>\r\n        <span class=\"token string\">'orientationChange'</span><span class=\"token punctuation\">,</span>\r\n        lazyload\r\n      <span class=\"token punctuation\">)</span>\r\n    <span class=\"token punctuation\">}</span>\r\n  <span class=\"token punctuation\">}</span>\r\n<span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>And:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"6785556189351461000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`#bg-image.lazy {\r\n  background-image: none;\r\n  background-color: #f1f1fa;\r\n}\r\n#bg-image {\r\n  background-image: url('path/to/some/cat/image.jpg');\r\n  max-width: 600px;\r\n  height: 400px;\r\n}`, `6785556189351461000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"css\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-css line-numbers\"><code class=\"language-css\"><span class=\"token selector\">#bg-image.lazy</span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token property\">background-image</span><span class=\"token punctuation\">:</span> none<span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">background-color</span><span class=\"token punctuation\">:</span> #f1f1fa<span class=\"token punctuation\">;</span>\r\n<span class=\"token punctuation\">}</span>\r\n<span class=\"token selector\">#bg-image</span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token property\">background-image</span><span class=\"token punctuation\">:</span> <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">'path/to/some/cat/image.jpg'</span><span class=\"token punctuation\">)</span></span><span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">max-width</span><span class=\"token punctuation\">:</span> 600px<span class=\"token punctuation\">;</span>\r\n  <span class=\"token property\">height</span><span class=\"token punctuation\">:</span> 400px<span class=\"token punctuation\">;</span>\r\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<h2 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h2>\n<p>We’ve seen how to reduce the image size using different compression methods, how to load different sizes for different screen sizes and at last how to lazy load them. Using these techniques, you can improve the performance of the page so much it becomes a hobby for you after some time to play with.</p>\n<p>And as always please spread the word and behold for the next post on web fonts 😃👋.</p>","timeToRead":9,"frontmatter":{"title":"Image optimisation","unformattedDate":"2018-11-12T00:00:00.000Z","date":"Nov 12, 2018","path":"web-perf-4/","author":"Yaser Adel Mehraban","tags":["web","performance","image optimisation"],"thumbnail":{"childImageSharp":{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAwACBf/EABUBAQEAAAAAAAAAAAAAAAAAAAMC/9oADAMBAAIQAxAAAAFCyhgtz5Y//8QAGhAAAgMBAQAAAAAAAAAAAAAAAQIAAxETMf/aAAgBAQABBQJr1A7bFsUhQMfwz//EABgRAAIDAAAAAAAAAAAAAAAAAAABAiFR/9oACAEDAQE/AawcUf/EABYRAQEBAAAAAAAAAAAAAAAAAAEAA//aAAgBAgEBPwF2Y0v/xAAZEAACAwEAAAAAAAAAAAAAAAAAARAhMRH/2gAIAQEABj8CpdFRpk//xAAaEAEAAgMBAAAAAAAAAAAAAAABABEhMUGR/9oACAEBAAE/IUASHd7l1Sh1YDakZkPIDmEvU//aAAwDAQACAAMAAAAQZ9//xAAWEQEBAQAAAAAAAAAAAAAAAAABABH/2gAIAQMBAT8QA4YkK3//xAAXEQEBAQEAAAAAAAAAAAAAAAABABEh/9oACAECAQE/EBOS4cv/xAAaEAEAAwEBAQAAAAAAAAAAAAABABEhMUFR/9oACAEBAAE/EAHuVVp8IECTcQZyMFD0WqlZTvonksSs5FBQtfJ//9k="},"backgroundColor":"transparent","images":{"fallback":{"src":"/static/46f62ba21d32bb09b72f685b75cc9e85/66aa2/imgoptimisation.jpg","srcSet":"/static/46f62ba21d32bb09b72f685b75cc9e85/c93cd/imgoptimisation.jpg 750w,\n/static/46f62ba21d32bb09b72f685b75cc9e85/66aa2/imgoptimisation.jpg 760w","sizes":"(min-width: 760px) 760px, 100vw"},"sources":[{"srcSet":"/static/46f62ba21d32bb09b72f685b75cc9e85/11ba1/imgoptimisation.webp 750w,\n/static/46f62ba21d32bb09b72f685b75cc9e85/f5df0/imgoptimisation.webp 760w","type":"image/webp","sizes":"(min-width: 760px) 760px, 100vw"}]},"width":760,"height":380}}}}}},{"node":{"id":"0ffa1c82-fc0d-50b9-a88b-612616b90e83","html":"<p>Recently I had a chance to present a talk at <a href=\"https://ndcsydney.com/talk/need-for-speed-8-performance-tuning-of-your-web-application/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">NDC Sydney</a> about web performance and it received a great feedback.</p>\n<!--more-->\n<p>That inspired me to write up a series of posts on each topic I covered in that talk, and who knows, maybe each of these posts would be a talk some day by their own 😃.</p>\n<p>All other parts:</p>\n<p><a href=\"/blog/2018/09/29/web-perf-1\">Part 1 on HTML and CSS</a></p>\n<p><a href=\"/blog/2018/10/06/web-perf-2\">Part 2 use Preload/Prefetch to boost load time</a></p>\n<p><a href=\"/blog/2018/11/12/web-perf-4\">Part 4 Image optimisation</a></p>\n<p><a href=\"/blog/2018/11/23/web-perf-5\">Part 5 Web font optimisation</a></p>\n<p>Time to see what we can do for our old friend JavaScript. So let’s begin.</p>\n<h1 id=\"switch-to-http2\" style=\"position:relative;\"><a href=\"#switch-to-http2\" aria-label=\"switch to http2 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Switch to HTTP/2</h1>\n<p>With more and more hosting providers supporting <a href=\"https://en.wikipedia.org/wiki/HTTP/2\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">HTTP/2</a>, it’s becoming a good time to switch to this protocol instead and benefit from its multiplexed nature. What it means in terms of performance is that we don’t need to bundle all of our JavaScript into large bundles to reduce the number of calls to server.</p>\n<p>With <strong>HTTP/2</strong> designed to handle large number of requests, you can now increase the number of files required to render the page. Not too much tho:</p>\n<blockquote>\n<p>Too much of a good thing is a bad thing.</p>\n</blockquote>\n<h1 id=\"async--defer\" style=\"position:relative;\"><a href=\"#async--defer\" aria-label=\"async  defer permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Async &#x26; Defer</h1>\n<p>As I mentioned before, JavaScript, like CSS is a <strong>render blocking</strong> element. This simply means the browser needs to wait for it to load and execute before it can parse the rest of the <code class=\"language-text\">HTML</code> document.</p>\n<p>This hugely increases our <a href=\"https://developers.google.com/web/tools/lighthouse/audits/first-contentful-paint\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">First Meaningful Pain</a>. In order to fix this issue we can use two of the features which are not used by many people but are very effective.</p>\n<h3 id=\"normal-execution\" style=\"position:relative;\"><a href=\"#normal-execution\" aria-label=\"normal execution permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Normal execution</h3>\n<p>When you use a <code class=\"language-text\">&lt;script></code> to load a JavaScript file, it interrupts the parsing of the document. Browser fetches the resource, executes this and then continues on paring:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1080px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/d562503683c7b6a3c0ee5ed90085f60c/78c62/normaljsexec.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 20.740740740740744%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAEABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwEC/9oADAMBAAIQAxAAAAHVsQ7Gb//EABkQAAIDAQAAAAAAAAAAAAAAAAERAAISMf/aAAgBAQABBQLRaIlef//EABcRAAMBAAAAAAAAAAAAAAAAAAACMQH/2gAIAQMBAT8BTaLD/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAx/9oACAECAQE/AUnb/8QAGBAAAgMAAAAAAAAAAAAAAAAAAAEQMTL/2gAIAQEABj8Cs04//8QAGBAAAwEBAAAAAAAAAAAAAAAAAAERIXH/2gAIAQEAAT8hdashevR29On/2gAMAwEAAgADAAAAEPvf/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAEDAQE/EETTJRf/xAAWEQADAAAAAAAAAAAAAAAAAAAAASH/2gAIAQIBAT8QRBaP/8QAGRABAQADAQAAAAAAAAAAAAAAAREAIaEx/9oACAEBAAE/EJcALNGuZYGpShnMfrq+oZ//2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Normal execution\"\n        title=\"\"\n        src=\"/static/d562503683c7b6a3c0ee5ed90085f60c/47311/normaljsexec.jpg\"\n        srcset=\"/static/d562503683c7b6a3c0ee5ed90085f60c/6f81f/normaljsexec.jpg 270w,\n/static/d562503683c7b6a3c0ee5ed90085f60c/09d21/normaljsexec.jpg 540w,\n/static/d562503683c7b6a3c0ee5ed90085f60c/47311/normaljsexec.jpg 1080w,\n/static/d562503683c7b6a3c0ee5ed90085f60c/78c62/normaljsexec.jpg 1589w\"\n        sizes=\"(max-width: 1080px) 100vw, 1080px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<h3 id=\"the-code-classlanguage-textasynccode-attribute\" style=\"position:relative;\"><a href=\"#the-code-classlanguage-textasynccode-attribute\" aria-label=\"the code classlanguage textasynccode attribute permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The <code class=\"language-text\">Async</code> attribute</h3>\n<p>The <code class=\"language-text\">Async</code> attribute is used to indicate that this resource can be executed asynchronously. The parsing doesn’t need to be halted, it can be done right after the resource is fetched from network and is ready.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"20109166581918147000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<script async src=&quot;script.js&quot;>`, `20109166581918147000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span> <span class=\"token attr-name\">async</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>script.js<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>This attribute can be used only on external JavaScript files. The file would be downloaded in parallel and once the download is finished, the parsing is paused for the script to be executed:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1080px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/7d5975f30349a8282be6f1d8b956cde5/ac99c/asyncjs.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 22.59259259259259%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAFABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgAB/9oADAMBAAIQAxAAAAHZkRsZf//EABgQAAIDAAAAAAAAAAAAAAAAAAAiAhES/9oACAEBAAEFAnMztj//xAAWEQEBAQAAAAAAAAAAAAAAAAAAARH/2gAIAQMBAT8BjH//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAgEBPwGq/8QAGRAAAgMBAAAAAAAAAAAAAAAAAAEyM5Gh/9oACAEBAAY/ApLCzhJYf//EABoQAAICAwAAAAAAAAAAAAAAAAABESFR0fD/2gAIAQEAAT8hXBsV1tGBBH//2gAMAwEAAgADAAAAEPPv/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAER4f/aAAgBAwEBPxBINLp//8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQIBAT8QYf/EABoQAQEBAAMBAAAAAAAAAAAAAAERACExYbH/2gAIAQEAAT8QozNTYS9QZPgl7b93/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Async execution\"\n        title=\"\"\n        src=\"/static/7d5975f30349a8282be6f1d8b956cde5/47311/asyncjs.jpg\"\n        srcset=\"/static/7d5975f30349a8282be6f1d8b956cde5/6f81f/asyncjs.jpg 270w,\n/static/7d5975f30349a8282be6f1d8b956cde5/09d21/asyncjs.jpg 540w,\n/static/7d5975f30349a8282be6f1d8b956cde5/47311/asyncjs.jpg 1080w,\n/static/7d5975f30349a8282be6f1d8b956cde5/ac99c/asyncjs.jpg 1536w\"\n        sizes=\"(max-width: 1080px) 100vw, 1080px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<h3 id=\"the-code-classlanguage-textdefercode-attribute\" style=\"position:relative;\"><a href=\"#the-code-classlanguage-textdefercode-attribute\" aria-label=\"the code classlanguage textdefercode attribute permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The <code class=\"language-text\">Defer</code> attribute</h3>\n<p>The <code class=\"language-text\">Defer</code> attribute is used to tell the browser to execute this script after parsing the whole document.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"26011793348018040000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<script defer src=&quot;script.js&quot;>`, `26011793348018040000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span> <span class=\"token attr-name\">defer</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>script.js<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>Like <code class=\"language-text\">Async</code> this file gets downloaded in parallel but the execution only happens when the whole <code class=\"language-text\">HTML</code> document is parsed:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1080px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/61e576b9875fc024a3679482e7e2398a/ac99c/deferjs.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 22.59259259259259%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAFABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAEDBf/EABQBAQAAAAAAAAAAAAAAAAAAAAL/2gAMAwEAAhADEAAAAdmBC8F//8QAGBAAAgMAAAAAAAAAAAAAAAAAAQIAECL/2gAIAQEAAQUC1FDiv//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAEDAQE/ASf/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAcEAAABgMAAAAAAAAAAAAAAAAAAQIQESExgZH/2gAIAQEABj8CyXBa503/xAAZEAACAwEAAAAAAAAAAAAAAAABEQAQIUH/2gAIAQEAAT8hZ5UABnXP/9oADAMBAAIAAwAAABB4D//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QH//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/EFn/xAAbEAEAAgIDAAAAAAAAAAAAAAABABEhQWFxof/aAAgBAQABPxDKBXvX2KUBXdU6pgRSuTP/2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Deferred execution\"\n        title=\"\"\n        src=\"/static/61e576b9875fc024a3679482e7e2398a/47311/deferjs.jpg\"\n        srcset=\"/static/61e576b9875fc024a3679482e7e2398a/6f81f/deferjs.jpg 270w,\n/static/61e576b9875fc024a3679482e7e2398a/09d21/deferjs.jpg 540w,\n/static/61e576b9875fc024a3679482e7e2398a/47311/deferjs.jpg 1080w,\n/static/61e576b9875fc024a3679482e7e2398a/ac99c/deferjs.jpg 1536w\"\n        sizes=\"(max-width: 1080px) 100vw, 1080px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<p>At the end remember to put all of your <code class=\"language-text\">script</code> tags right at the end of the <code class=\"language-text\">body</code> to prevent more delay in parsing your <code class=\"language-text\">HTML</code>.</p>\n<p>As for the browser support, fortunately these attributes are fully supported by all of the major ones.</p>\n<h1 id=\"code-splitting\" style=\"position:relative;\"><a href=\"#code-splitting\" aria-label=\"code splitting permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Code splitting</h1>\n<p>Most of the modern sites will bundle all of their JavaScript into one, resulting in an increase in load time and suffering from load performance.</p>\n<p>Code splitting allows you to split your application code into separate chunks and lazy load them when needed. This also means minimum required code to client and improve the page load time.</p>\n<p>You can split your code in three areas:</p>\n<ul>\n<li>Vendor code</li>\n<li>Entry point</li>\n<li>Dynamic splitting</li>\n</ul>\n<h2 id=\"vendor-code\" style=\"position:relative;\"><a href=\"#vendor-code\" aria-label=\"vendor code permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Vendor code</h2>\n<p>Vendor code like Angular, React, moment, etc. can be separated from your main code. <a href=\"https://webpack.js.org/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Webpack</a> has full support for this and other methods. This technique allows you to have better control over cache invalidation of your bundles whenever your app or vendor code changes independently of one another.</p>\n<p>This is something every app should do.</p>\n<h2 id=\"entry-point\" style=\"position:relative;\"><a href=\"#entry-point\" aria-label=\"entry point permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Entry point</h2>\n<p>This technique separates your code by entry points in your app. These points are where bundlers like webpack start from, when they build a dependency tree of your app.</p>\n<p>This is bar far the easiest way to split code, but it is manual and has some pitfalls:</p>\n<ul>\n<li>If there are any duplicated modules between entry points, they will be bundled in both.</li>\n<li>It isn’t as flexible and cannot be used to dynamically split code with your app logic.</li>\n</ul>\n<p>This technique is not suitable for when you have client side routing or when you have a mix of server side rendering and a single page app.</p>\n<h2 id=\"dynamic-splitting\" style=\"position:relative;\"><a href=\"#dynamic-splitting\" aria-label=\"dynamic splitting permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Dynamic splitting</h2>\n<p>Separate code when dynamic <code class=\"language-text\">import</code> are used. This is the best option for single page applications. Having different modules for different routes in your SPA is an example of this.</p>\n<h2 id=\"do-i-even-need-code-splitting\" style=\"position:relative;\"><a href=\"#do-i-even-need-code-splitting\" aria-label=\"do i even need code splitting permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Do I even need code splitting?</h2>\n<p>This is one of many times when you hear me say it depends (I am a consultant after all 😉). If your app has many routes with isolated functionality and heavily uses frameworks and libraries, this answer is most probably <strong>YES</strong>.</p>\n<p>However, it is up to you to decide whether you need it or not by your own understanding of your app structure and code.</p>\n<h1 id=\"import-wisely\" style=\"position:relative;\"><a href=\"#import-wisely\" aria-label=\"import wisely permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Import wisely</h1>\n<p>If you use <code class=\"language-text\">npm</code> or other package management systems for your dependencies, then you will have a lot of extra and unneeded files in your buid folder.</p>\n<p>When using a framework or a library, make sure you investigate wether they have separate modules you can import and if yes, only import what you need.</p>\n<p>For instance, let’s assume you are using <a href=\"https://underscorejs.org/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">underscore</a>, but only use <code class=\"language-text\">groupBy</code>, <code class=\"language-text\">shuffle</code>, and <code class=\"language-text\">partition</code>. Most people import the whole library like this:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"97611862796379520000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`import * as _ from 'underscore'`, `97611862796379520000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">as</span> _ <span class=\"token keyword\">from</span> <span class=\"token string\">'underscore'</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>Instead of this, you could just import what you need:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"48223981261563020000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`import {\r\n  groupBy,\r\n  shuffle,\r\n  partition,\r\n} from 'underscore'`, `48223981261563020000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span>\r\n  groupBy<span class=\"token punctuation\">,</span>\r\n  shuffle<span class=\"token punctuation\">,</span>\r\n  partition<span class=\"token punctuation\">,</span>\r\n<span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'underscore'</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>This way you only bring what your need and the bundlers will take care of the rest for you. Your total package size and as a result your page load time will decrease.</p>\n<h1 id=\"throttling-and-debounce\" style=\"position:relative;\"><a href=\"#throttling-and-debounce\" aria-label=\"throttling and debounce permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Throttling and debounce</h1>\n<p>Ok, enough about the size, let’s see where else we can improve our performance.</p>\n<p>Many times you have to add an event listener to do something, like listening to page scroll. Then we forget that the listener fires every time the event is triggered.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"57296372215837630000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`window.addEventListener('scroll', function() {\r\n  console.log('page scrolled')\r\n})`, `57296372215837630000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\">window<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">'scroll'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n  console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'page scrolled'</span><span class=\"token punctuation\">)</span>\r\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span></span></pre></div>\n<p>In the above example, the message is printed into console whenever you scroll. Imagine you have some heavy operation in that callback function, this would turn into a big performance bottleneck.</p>\n<p>If you can’t remove that event listener and use a different approach, then you can use either <code class=\"language-text\">debounce</code> or <code class=\"language-text\">throttle</code> to alleviate the situation.</p>\n<h2 id=\"debounce\" style=\"position:relative;\"><a href=\"#debounce\" aria-label=\"debounce permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Debounce</h2>\n<p>This feature enforces a function call to not happen until some time has passed since it’s last call. For example, call the function if 100 millisecond has passed from it’s last call.</p>\n<p>Look at this implementation from underscore:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"27463992666054214000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const debounce = (func, delay) => {\r\n  let inDebounce\r\n  return function() {\r\n    const context = this\r\n    const args = arguments\r\n    clearTimeout(inDebounce)\r\n    inDebounce = setTimeout(\r\n      () => func.apply(context, args),\r\n      delay\r\n    )\r\n  }\r\n}`, `27463992666054214000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">debounce</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">func<span class=\"token punctuation\">,</span> delay</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token keyword\">let</span> inDebounce\r\n  <span class=\"token keyword\">return</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n    <span class=\"token keyword\">const</span> context <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span>\r\n    <span class=\"token keyword\">const</span> args <span class=\"token operator\">=</span> arguments\r\n    <span class=\"token function\">clearTimeout</span><span class=\"token punctuation\">(</span>inDebounce<span class=\"token punctuation\">)</span>\r\n    inDebounce <span class=\"token operator\">=</span> <span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span>\r\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">func</span><span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> args<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n      delay\r\n    <span class=\"token punctuation\">)</span>\r\n  <span class=\"token punctuation\">}</span>\r\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>Now we can debounce our event listener for every 100 millisecond:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"53433851718920960000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`var efficientScrollListener = debounce(\r\n  function() {\r\n    console.log('page scrolled')\r\n  },\r\n  100\r\n)\r\n\r\nwindow.addEventListener(\r\n  'scroll',\r\n  efficientScrollListener\r\n)`, `53433851718920960000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">var</span> efficientScrollListener <span class=\"token operator\">=</span> <span class=\"token function\">debounce</span><span class=\"token punctuation\">(</span>\r\n  <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'page scrolled'</span><span class=\"token punctuation\">)</span>\r\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\r\n  <span class=\"token number\">100</span>\r\n<span class=\"token punctuation\">)</span>\r\n\r\nwindow<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span>\r\n  <span class=\"token string\">'scroll'</span><span class=\"token punctuation\">,</span>\r\n  efficientScrollListener\r\n<span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<h2 id=\"throttle\" style=\"position:relative;\"><a href=\"#throttle\" aria-label=\"throttle permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Throttle</h2>\n<p>Throttling is similar to debounce but different since it will enforce the maximum number of times a function can be called over a period of time. For example execute this function once every 100 millisecond.</p>\n<p>Here is a simple implementation:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"16968976238430345000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const throttle = (func, limit) => {\r\n  let inThrottle\r\n  return function() {\r\n    const args = arguments\r\n    const context = this\r\n    if (!inThrottle) {\r\n      func.apply(context, args)\r\n      inThrottle = true\r\n      setTimeout(\r\n        () => (inThrottle = false),\r\n        limit\r\n      )\r\n    }\r\n  }\r\n}`, `16968976238430345000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">throttle</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">func<span class=\"token punctuation\">,</span> limit</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token keyword\">let</span> inThrottle\r\n  <span class=\"token keyword\">return</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n    <span class=\"token keyword\">const</span> args <span class=\"token operator\">=</span> arguments\r\n    <span class=\"token keyword\">const</span> context <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span>\r\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>inThrottle<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n      <span class=\"token function\">func</span><span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> args<span class=\"token punctuation\">)</span>\r\n      inThrottle <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span>\r\n      <span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span>\r\n        <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span>inThrottle <span class=\"token operator\">=</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\r\n        limit\r\n      <span class=\"token punctuation\">)</span>\r\n    <span class=\"token punctuation\">}</span>\r\n  <span class=\"token punctuation\">}</span>\r\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>Now we can throttle our scroll event listener:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"60621288071380386000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`var efficientScrollListener = throttle(\r\n  function() {\r\n    console.log('page scrolled')\r\n  },\r\n  100\r\n)\r\n\r\nwindow.addEventListener(\r\n  'scroll',\r\n  efficientScrollListener\r\n)`, `60621288071380386000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-js line-numbers\"><code class=\"language-js\"><span class=\"token keyword\">var</span> efficientScrollListener <span class=\"token operator\">=</span> <span class=\"token function\">throttle</span><span class=\"token punctuation\">(</span>\r\n  <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'page scrolled'</span><span class=\"token punctuation\">)</span>\r\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\r\n  <span class=\"token number\">100</span>\r\n<span class=\"token punctuation\">)</span>\r\n\r\nwindow<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span>\r\n  <span class=\"token string\">'scroll'</span><span class=\"token punctuation\">,</span>\r\n  efficientScrollListener\r\n<span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<h1 id=\"so-what\" style=\"position:relative;\"><a href=\"#so-what\" aria-label=\"so what permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>So what</h1>\n<p>I hope I have given you enough information on just some of the areas you can focus to improve your applications performance when using JavaScript. If you would like to have other topics covered please comment below and I will add them here or in another post.</p>\n<p>And as always don’t forget to share the ❤️.</p>","timeToRead":5,"frontmatter":{"title":"Optimising JavaScript","unformattedDate":"2018-10-12T00:00:00.000Z","date":"Oct 12, 2018","path":"web-perf-3/","author":"Yaser Adel Mehraban","tags":["web","performance","javascript"],"thumbnail":{"childImageSharp":{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB7aWimgQX/8QAGRABAAIDAAAAAAAAAAAAAAAAAQIRAAMS/9oACAEBAAEFAmg1T7jiWVHXkXo//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFxAAAwEAAAAAAAAAAAAAAAAAABEg4f/aAAgBAQAGPwLYYz//xAAcEAADAAEFAAAAAAAAAAAAAAAAAREhEDFBYXH/2gAIAQEAAT8hW52ejrGuNFSY0MN3MCYD/9oADAMBAAIAAwAAABAAD//EABYRAQEBAAAAAAAAAAAAAAAAAAEQEf/aAAgBAwEBPxBHZ//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABwQAQADAAIDAAAAAAAAAAAAAAEAESEQMUGh8f/aAAgBAQABPxBUxHf0htYKTS5474UHY+oLDaBQzJWRC62f/9k="},"backgroundColor":"transparent","images":{"fallback":{"src":"/static/f7498c20b7bc9bf0825914e963e06b46/414c8/WebPerformance.jpg","srcSet":"/static/f7498c20b7bc9bf0825914e963e06b46/414c8/WebPerformance.jpg 448w","sizes":"(min-width: 448px) 448px, 100vw"},"sources":[{"srcSet":"/static/f7498c20b7bc9bf0825914e963e06b46/cfb46/WebPerformance.webp 448w","type":"image/webp","sizes":"(min-width: 448px) 448px, 100vw"}]},"width":448,"height":311}}}}}},{"node":{"id":"68dfaf3d-b04d-5bfc-b880-64386f0236fa","html":"<p>Recently I had a chance to present a talk at <a href=\"https://ndcsydney.com/talk/need-for-speed-8-performance-tuning-of-your-web-application/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">NDC Sydney</a> about web performance and it received a great feedback.</p>\n<!--more-->\n<p>That inspired me to write up a series of posts on each topic I covered in that talk, and who knows, maybe each of these posts would be a talk some day by their own 😃.</p>\n<p>Link to all other parts:</p>\n<p><a href=\"/blog/2018/09/29/web-perf-1\">Part 1 on HTML and CSS</a></p>\n<p><a href=\"/blog/2018/10/12/web-perf-3\">Part 3 JavaScript tips and tricks</a></p>\n<p><a href=\"/blog/2018/11/12/web-perf-4\">Part 4 Image optimisation</a></p>\n<p><a href=\"/blog/2018/11/23/web-perf-5\">Part 5 Web font optimisation</a></p>\n<p>OK, just to recap, here are the rules from part 1:</p>\n<ul>\n<li>Stream HTML to client</li>\n<li>Send minimal CSS and send it fast</li>\n</ul>\n<p>In this part, we’re going to see how we can request our resources before we need them. You might be wondering why we want to do so, and the answer is, if you want to send minimal CSS to client, or any other resource for that matter, you need to break them into smaller pieces and load them separately.</p>\n<p>There are some techniques which allow you to do it like lazy loading, but with lazy loading, user has to wait (most probably watching a spinner 😏) until the resource is loaded.</p>\n<p>But, we can do better. One of the letters from <a href=\"https://developers.google.com/web/fundamentals/performance/prpl-pattern/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">PRPL pattern</a> stands for <code class=\"language-text\">pre-cache</code>. An effective way to load your resources before they are required, cache them and then use them when they are needed. We can achieve this using <code class=\"language-text\">preload</code> and <code class=\"language-text\">prefetch</code> features of browsers.</p>\n<p>Before we go further into how, let me explain their difference:</p>\n<h3 id=\"preload\" style=\"position:relative;\"><a href=\"#preload\" aria-label=\"preload permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Preload</h3>\n<p><code class=\"language-text\">&lt;link rel=\"preload\"></code> tells the browser that the resource should be loaded as part of the current navigation and it should start fetching it ASAP. This attribute can be applied to CSS, fonts, images, JavaScript files and more. When using this attribute you will also tell the browser what file type this file has, which can be set in an <code class=\"language-text\">as</code> attribute:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"36928331087882400000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<link\r\n  rel=&quot;preload&quot;\r\n  as=&quot;script&quot;\r\n  href=&quot;super-important.js&quot;\r\n/>\r\n<link\r\n  rel=&quot;preload&quot;\r\n  as=&quot;style&quot;\r\n  href=&quot;critical.css&quot;\r\n/>`, `36928331087882400000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span>\r\n  <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>preload<span class=\"token punctuation\">\"</span></span>\r\n  <span class=\"token attr-name\">as</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>script<span class=\"token punctuation\">\"</span></span>\r\n  <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>super-important.js<span class=\"token punctuation\">\"</span></span>\r\n<span class=\"token punctuation\">/></span></span>\r\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span>\r\n  <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>preload<span class=\"token punctuation\">\"</span></span>\r\n  <span class=\"token attr-name\">as</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>style<span class=\"token punctuation\">\"</span></span>\r\n  <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>critical.css<span class=\"token punctuation\">\"</span></span>\r\n<span class=\"token punctuation\">/></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>So by now you should have guessed that <code class=\"language-text\">preload</code> is used in the current route and resources fetched via this technique are very important. The difference between using <code class=\"language-text\">rel=preload</code> and <code class=\"language-text\">rel=stylesheet</code> is that browser will know about that resource way ahead of time allowing the download to start sooner.</p>\n<p>If you are trying this for your stylesheet and don’t see your styles get applied, it is because there is a catch when using <code class=\"language-text\">preload</code> which is the browser downloads the resource but won’t apply it until we tell it to. To get it working you will need a bit of JavaScript:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"63334279221373665000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<link\r\n  rel=&quot;preload&quot;\r\n  as=&quot;style&quot;\r\n  href=&quot;critical.css&quot;\r\n  onload=&quot;this.rel='stylesheet'&quot;\r\n/>`, `63334279221373665000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span>\r\n  <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>preload<span class=\"token punctuation\">\"</span></span>\r\n  <span class=\"token attr-name\">as</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>style<span class=\"token punctuation\">\"</span></span>\r\n  <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>critical.css<span class=\"token punctuation\">\"</span></span>\r\n  <span class=\"token special-attr\"><span class=\"token attr-name\">onload</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token value javascript language-javascript\"><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>rel<span class=\"token operator\">=</span><span class=\"token string\">'stylesheet'</span></span><span class=\"token punctuation\">\"</span></span></span>\r\n<span class=\"token punctuation\">/></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>What happens now is that the styles get applied as soon as the file is loaded.</p>\n<h3 id=\"prefetch\" style=\"position:relative;\"><a href=\"#prefetch\" aria-label=\"prefetch permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Prefetch</h3>\n<p><code class=\"language-text\">&lt;link rel=\"prefetch\"></code> is different from <code class=\"language-text\">&lt;link rel=\"preload\"></code> in that it is not trying to load a critical resource faster, it is trying to load a non-critical resource sooner.</p>\n<p>Resources loaded by this technique are loaded after current page is loaded, page load event is finished and bandwidth is available. This means it is ideal for lazy loading future routes’ resources or resources that user might need later. Some use cases are fetching a next page if pagination is used:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"6757914177292900000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<link rel=&quot;prefetch&quot; href=&quot;page-2.html&quot; />`, `6757914177292900000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>prefetch<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>page-2.html<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>By the time user clicks on next page button, the page is already loaded and the app feels real fast.</p>\n<p>To read more about the usage of these features and also know about other useful features, have a look at <a href=\"https://developers.google.com/web/fundamentals/performance/resource-prioritization\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google developer’s resource prioritisation page.</a></p>\n<p>Same catch applied for <code class=\"language-text\">prefetch</code> as well. But since we are loading a resource which is required potentially for a different route, you might have a separate <code class=\"language-text\">rel=stylesheet</code> on that page which uses this in memory file or in case of a SPA just set the <code class=\"language-text\">rel</code> to <code class=\"language-text\">stylesheet</code> when the route is loaded.</p>\n<h2 id=\"when-to-use-these\" style=\"position:relative;\"><a href=\"#when-to-use-these\" aria-label=\"when to use these permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>When to use these</h2>\n<p>So to emphasise why we need to know about these techniques, let me take you back to part one. CSS is a render blocking element, so we need to break it down to the smallest possible chunk which is required to render our main route. Then we can use the above techniques to either load the resource later in the same page without blocking the rendering or to load the resource which is required for our possible next route beforehand and use it when needed.</p>\n<p>Hope this has helped you to get started with optimising your HTML and CSS loading so far.</p>\n<p>Next post will be on <code class=\"language-text\">JavaScript</code> and what we can do there to improve our web application’s performance.</p>\n<p>Alla prossima 😎.</p>","timeToRead":3,"frontmatter":{"title":"How to use Preload/Prefetch to boost load time","unformattedDate":"2018-10-06T00:00:00.000Z","date":"Oct 06, 2018","path":"web-perf-2/","author":"Yaser Adel Mehraban","tags":["web","performance","preload","prefetch"],"thumbnail":null}}},{"node":{"id":"f511313b-3959-5b82-ad58-16adb92adcf6","html":"<p>Recently I had a chance to present a talk at <a href=\"https://ndcsydney.com/talk/need-for-speed-8-performance-tuning-of-your-web-application/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">NDC Sydney</a> about web performance and it received a great feedback.</p>\n<!--more-->\n<p>That inspired me to write up a series of posts on each topic I covered in that talk, and who knows, maybe each of these posts would be a talk some day by their own 😃.</p>\n<p>Link to all other parts:</p>\n<p><a href=\"/blog/2018/10/06/web-perf-2\">Part 2 use Preload/Prefetch to boost load time</a></p>\n<p><a href=\"/blog/2018/10/12/web-perf-3\">Part 3 JavaScript tips and tricks</a></p>\n<p><a href=\"/blog/2018/11/12/web-perf-4\">Part 4 Image optimisation</a></p>\n<p><a href=\"/blog/2018/11/23/web-perf-5\">Part 5 Web font optimisation</a></p>\n<p>So here we go, part one is about tips and tricks on HTML and CSS to improve the performance.</p>\n<p>But before we jump into this, you will need to know how browsers render your page. This involves <a href=\"https://en.wikipedia.org/wiki/HTML\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">HTML</a>, <a href=\"https://en.wikipedia.org/wiki/Cascading_Style_Sheets\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">CSS</a> and <a href=\"https://en.wikipedia.org/wiki/JavaScript\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">JavaScript</a> and steps every browser takes to show your web page to end user.</p>\n<h2 id=\"the-critical-rendering-path\" style=\"position:relative;\"><a href=\"#the-critical-rendering-path\" aria-label=\"the critical rendering path permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The Critical Rendering Path</h2>\n<p>The <a href=\"https://css-tricks.com/understanding-critical-rendering-path/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Critical Rendering Path</a> consists of five steps which are best to be seen in visual:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/f85f1171d19386f6bdde3c2463b18ef2/29d31/crp.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 27.40740740740741%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAFABQDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABuABP/8QAGBAAAgMAAAAAAAAAAAAAAAAAAAECEjH/2gAIAQEAAQUCZHKn/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFxAAAwEAAAAAAAAAAAAAAAAAAAEQMf/aAAgBAQAGPwKaz//EABkQAQADAQEAAAAAAAAAAAAAAAEAESGBMf/aAAgBAQABPyEadgzr4RurX2f/2gAMAwEAAgADAAAAEPAf/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oACAEDAQE/EGR//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGhABAAIDAQAAAAAAAAAAAAAAAREhADFBsf/aAAgBAQABPxDtTVneuOLLMJQ+415OFDP/2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Critical Rendering Path\"\n        title=\"\"\n        src=\"/static/f85f1171d19386f6bdde3c2463b18ef2/29d31/crp.jpg\"\n        srcset=\"/static/f85f1171d19386f6bdde3c2463b18ef2/6f81f/crp.jpg 270w,\n/static/f85f1171d19386f6bdde3c2463b18ef2/09d21/crp.jpg 540w,\n/static/f85f1171d19386f6bdde3c2463b18ef2/29d31/crp.jpg 700w\"\n        sizes=\"(max-width: 700px) 100vw, 700px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<p>Alright now that you saw it in a picture, let me explain each step in more details.</p>\n<h3 id=\"building-dom-and-cccom\" style=\"position:relative;\"><a href=\"#building-dom-and-cccom\" aria-label=\"building dom and cccom permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Building DOM and CCCOM</h3>\n<p>As most of the pages consist of HTML, CSS and JavaScript. Web browsers need to know what and how to show to users and they do this by parsing the HTML page sent over network and constructing a Document Object Model (DOM). They look at HTML tags (<code class=\"language-text\">&lt;p>&lt;/p></code>, <code class=\"language-text\">&lt;div>&lt;/div></code>, <code class=\"language-text\">&lt;h1>&lt;/h1></code>) and convert them to tokens. These tokens are then converted to nodes in parallel.</p>\n<p>By processing the start and end tags for each token in order, the browser then establishes their hierarchy (parent and child).</p>\n<p>This is way simpler than it looks, in the picture above imagine DOM to be a bit tree with all the nodes (branches) and their children (leaves). This tree contains all the dependencies of nodes to construct our HTML:</p>\n<p><img src=\"/2c902bcd526dc480e0cd902e1381fcc1/DOM.gif\" alt=\"Document Object Model\"></p>\n<p><i>Image from <a href=\"https://www.w3schools.com/js/pic_htmltree.gif\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">W3C website</a></i></p>\n<p>The DOM represents your whole markup and is built incrementally by the browser. As of HTML5 the browsers support streaming HTML instead of waiting for the whole page to get sent to browser in one go. This is great because it helps the rendering to be done at the same time as the bytes are arrived.</p>\n<p>After constructing the DOM, browser looks at any style which is referenced in the page to build the CSS Object Model (CCCOM). CCCOM describes the style rules that need to be applied to the document. This is very similar to how DOM was built, however, in this process each child inherits the styles applied to its parent - hence the name cascading style sheets.</p>\n<p>Partial processing of styles is not possible so browsers need to wait for all the style rules to be sent over before they can start inferring what rule is applied to which nodes. This is the reason why CSS is a render blocking element.</p>\n<p>Mix of DOM and CCCOM is something called the Render Tree. This tree includes all the nodes and their dependencies plus all the CSS rules which are applied to those.</p>\n<h3 id=\"render-tree\" style=\"position:relative;\"><a href=\"#render-tree\" aria-label=\"render tree permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Render Tree</h3>\n<p>After constructing all the nodes, browser needs to know which ones to show on the page. Render Tree is exactly the representation <strong>visible</strong> content on the page.</p>\n<p>The browser stars from the root and then copies all the <strong>visible</strong> nodes from DOM and CCCOM. The steps taken are roughly as below:</p>\n<ul>\n<li>Starting at the root, traverse each visible node\n<ul>\n<li>Some nodes are not visible like meta tags, links, etc.</li>\n<li>Some nodes are hidden using CSS like <code class=\"language-text\">display: none</code></li>\n</ul>\n</li>\n<li>For each node find the matching CSS rule and apply it</li>\n<li>Emit visible nodes with content and they styles</li>\n</ul>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 800px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/1ff69ed70a06bcffbf7d84dce1e72381/5a190/render-tree.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 46.666666666666664%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAACi0lEQVR42k1SXUgUURQeLRVs26UMLTQwo8QwEMKHXqK3eg/yQXopMglcesgVsRrRxURETdeFqQ1CEWQMdwlb0QmmXWdnZmfu7MzOz87uOjO246qEZhC9TzPiSh+ce+/HOfe7555zIMhGMTlS8wkZvtqHAI/DJWq6QyWH1/P5eTd0DFn+6Vr8HL4XXl29a1lW5TbtazBJf73js3nZ8V4OadpcrUqPBDP06DhJoucxADwp6oNXjA9Ogh1QvbYmnDmg77slfbc9nSuEUqo+SglcR4Z86xc2xl7HYu+vLC/P1Kh4R6Ml36iEsiTsU4ihXpUeG02DhemcMNe/SQ0sEQzTHN7Yv5ViFp5vkq9oLbPYSqW2r33nirc3Gf9SnuztToKVhwqL8Lz47ZmcDDGiiHWepAt+/L3E5famgJwdFhIBjBcJNCHtTSjS6iODfvFSVMVOXskWKCHPiXI8JIOP64qxTSRlLSEa+yFW1mJJaSsC4Th+GsdRVz4frXKEaVF/TAo6EmOzT1DLOlWqIWzHvZuPunFebUwpGkfxWY5TjR7H52jAMOxYORSNRqtWVhbOBYMTTbOTky2BQMDlBJF8rj7BcXdwwWxl0sVmQRIeUCJVdyRuX+zqgioQBK7G8S8XbA03hqGeSCRytpQA5PV663w+XwOKop60ajSnc+aarO+GRZXrNgziqblTnJC2/rQUGLjplzRwGfoPTtlK5nBnKYOdltsg+K22BMsacZpWMWD26vxsUOOmsK9x/TouWy6DG4mbqaE5+3yRkaR2gpfbEARUHGuXnbxy9H+nOcCqSAh7tahsVSrazriQ350RjIM3QNbDaf3wZoHtG8yRAz10xvTTHPub5KUNoB96SvP4D9Ugj125mX4nAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Render Tree\"\n        title=\"\"\n        src=\"/static/1ff69ed70a06bcffbf7d84dce1e72381/5a190/render-tree.png\"\n        srcset=\"/static/1ff69ed70a06bcffbf7d84dce1e72381/01bf6/render-tree.png 270w,\n/static/1ff69ed70a06bcffbf7d84dce1e72381/07484/render-tree.png 540w,\n/static/1ff69ed70a06bcffbf7d84dce1e72381/5a190/render-tree.png 800w\"\n        sizes=\"(max-width: 800px) 100vw, 800px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<p><em>Image from <a href=\"https://developers.google.com/web/fundamentals/performance/critical-rendering-path/images/render-tree-construction.png\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google Developers</a></em></p>\n<h3 id=\"layout\" style=\"position:relative;\"><a href=\"#layout\" aria-label=\"layout permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Layout</h3>\n<p>Now that we have all the nodes with their styles, it’s time to figure out where to put them on screen. This is exactly what layout step is. The first thing which is needed is the browser window size. This is the basis for all the following calculations, since the layout depends on it to know the position and dimension of each element.</p>\n<p>The output of this step is the <a href=\"https://www.w3schools.com/css/css_boxmodel.asp\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Box Model</a> which captures the exact position and size of it, plus their margin, padding, border and etc.</p>\n<p>This step will be repeated by each change to size or when we switch between landscape and portrait on a mobile device.</p>\n<h3 id=\"paint\" style=\"position:relative;\"><a href=\"#paint\" aria-label=\"paint permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Paint</h3>\n<p>This step is the last one where pixels are painted on screen which can take some time because the browser has quite a lot of work to do. This time depends on window size, how much style is applied to each node, the hardware used on device and so on.</p>\n<p>When this step is finished, the page is finally visible in the viewport.</p>\n<h2 id=\"so-what\" style=\"position:relative;\"><a href=\"#so-what\" aria-label=\"so what permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>So what</h2>\n<p>Ok, enough with Critical Rendering Path, let’s see how we can improve the web performance with tweaks on HTML and CSS.</p>\n<h3 id=\"stream-html-to-client\" style=\"position:relative;\"><a href=\"#stream-html-to-client\" aria-label=\"stream html to client permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Stream HTML to client</h3>\n<p>When sending HTML to client try to flush the buffer often instead of once at the end. This means chunks of HTML would arrive and browser can parse them as they arrive not at the end. This will help to boost the performance.</p>\n<p>As an example, when <code class=\"language-text\">HEAD</code> tag is arrived browser can send other requests for assets while the rest of the HTML is arriving.</p>\n<h3 id=\"size-matters\" style=\"position:relative;\"><a href=\"#size-matters\" aria-label=\"size matters permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Size matters</h3>\n<p>Minifying and compressing is really important since it can reduce the payload size and reduce the HTTP response time which in turn results in better load time.</p>\n<p>These techniques along with the right caching strategy can massively help the web performance to be improved.</p>\n<h3 id=\"send-the-css-early-and-keep-it-minimal\" style=\"position:relative;\"><a href=\"#send-the-css-early-and-keep-it-minimal\" aria-label=\"send the css early and keep it minimal permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Send the CSS early and keep it minimal</h3>\n<p>As you saw CSS is a render blocking element, so it should be sent down to client as early as possible. Also think of how much CSS is needed on first page load, extract the unused CSS from the main file and load them separately and later when needed.</p>\n<p>You can also use pre-loading/pre-caching to improve the performance. These are part of <a href=\"https://developers.google.com/web/fundamentals/performance/prpl-pattern/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">PRPL pattern which was introduced by Google in 2016</a>.</p>\n<p>Another technique which is not used as often by developers is to use link tags inside body along with content. This is really useful as you can send a minimum amount of CSS to client even inside your HTML in a <code class=\"language-text\">style tag</code> and then load the rest later when needed to improve the render time.</p>\n<h2 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h2>\n<p>In short, keep your recourses minimum and send them fast and optimum. Try to cut down unused CSS rules and use minification and compression to speed up the transfer.</p>\n<p>Hope you’ve enjoyed reading this and are looking forward for the rest of the series 😉.</p>\n<h3 id=\"resources\" style=\"position:relative;\"><a href=\"#resources\" aria-label=\"resources permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Resources</h3>\n<ul>\n<li>Web Performance Matters on <a href=\"https://developers.google.com/web/fundamentals/performance/why-performance-matters/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google Developers</a></li>\n<li>Understanding Critical Rendering Path on <a href=\"https://css-tricks.com/understanding-critical-rendering-path/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">CSS Tricks</a></li>\n</ul>","timeToRead":4,"frontmatter":{"title":"Improve HTML and CSS performance","unformattedDate":"2018-09-29T00:00:00.000Z","date":"Sep 29, 2018","path":"web-perf-1/","author":"Yaser Adel Mehraban","tags":["web","performance","html","css"],"thumbnail":{"childImageSharp":{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB7aWimgQX/8QAGRABAAIDAAAAAAAAAAAAAAAAAQIRAAMS/9oACAEBAAEFAmg1T7jiWVHXkXo//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFxAAAwEAAAAAAAAAAAAAAAAAABEg4f/aAAgBAQAGPwLYYz//xAAcEAADAAEFAAAAAAAAAAAAAAAAAREhEDFBYXH/2gAIAQEAAT8hW52ejrGuNFSY0MN3MCYD/9oADAMBAAIAAwAAABAAD//EABYRAQEBAAAAAAAAAAAAAAAAAAEQEf/aAAgBAwEBPxBHZ//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABwQAQADAAIDAAAAAAAAAAAAAAEAESEQMUGh8f/aAAgBAQABPxBUxHf0htYKTS5474UHY+oLDaBQzJWRC62f/9k="},"backgroundColor":"transparent","images":{"fallback":{"src":"/static/f7498c20b7bc9bf0825914e963e06b46/414c8/WebPerformance.jpg","srcSet":"/static/f7498c20b7bc9bf0825914e963e06b46/414c8/WebPerformance.jpg 448w","sizes":"(min-width: 448px) 448px, 100vw"},"sources":[{"srcSet":"/static/f7498c20b7bc9bf0825914e963e06b46/cfb46/WebPerformance.webp 448w","type":"image/webp","sizes":"(min-width: 448px) 448px, 100vw"}]},"width":448,"height":311}}}}}},{"node":{"id":"0955b60a-f44d-5cc2-b476-79548854cc48","html":"<p>Spoiler alert: we cannot compare these two as they are different in nature, but, I try to go through some points you to need to consider, when choosing a front end technology.</p>\n<!--more-->\n<p>When you <strong>deploy</strong> your app you probably want to delay sending unnecessary files to client and increase the page load speed. Well if that’s the case Angular has very little support for that as you can lazy load html templates.</p>\n<p>Although you can do so for the JS files but you eventually end up with a spaghetti code which is hard to maintain and also takes some time to completely address what you need.</p>\n<p>In this area React is the winner as it simply is JS and doesn’t care, you can lazy load files with RequireJS and also integrate with frameworks like WebPack.</p>\n<p>I think <strong>learning</strong> Angular would take more time than React. As some people including  me have experienced you can learn React to a good extent in about a week. With Angular, however, it takes some time to learn the basics and then it gets harder as you go like a marriage.</p>\n<p>Good <strong>abstraction</strong> is priceless. Abstraction provides fast development and hides details that are not necessary for the developer using a library.</p>\n<p>Angular is week in keeping people away from its model state as so many developers have had to debug its internal state as they were debugging their code. React’s abstraction has led to it being less flexible like not be able to add attributes to Html tags (which I think is fixed by mixins implementation). However in total React is the winner.</p>\n<p><strong>Data model complexity</strong> is another factor which means how it is structured to be shown in view later on. Angular is suffering from relying heavily in scope because of the copy-n-compare. React gives you the ability to choose without facing performance hits and the outcome depends on whether you are a good or bad coder.</p>\n<p>Next thing to consider is <strong>binding</strong>. Angular allows you to bind only to model. This means that you cannot bind to a server/async service. If you want to do that you have to have intermediate models and even then you will suffer from the explicit watches and digest cycle.</p>\n<p>React on the other hand provides syntactic sugar for binding which is called valueLink. It is a single attribute for both “Value” and “onChange” properties. This is so simple to believe that it is doing what you want but it does and if you understand it well, you can implement any of your needs easily.</p>\n<p>Then it comes <strong>debugging</strong>. With debugging you want to achieve mostly two things. First why you logic is not working and second why the HTML outcome does not look like what you wanted to be.</p>\n<p>Angular does a good job of providing constructs that are logical, like services. If used correctly, they make the code easier to test and debug, but any good programmer will try to separate code and logic with or without them.</p>\n<p>React has two main scenarios - updating the model/doing other actions as a result of user events; and the one-way rendering flow which is always the same. This means that there are fewer places to look for your bugs and the stack traces have clear distinction between React’s code, and your own. They normally don’t mix. React also has less magic, and it’s all concentrated in one place - the vDom comparison. It is a closed black box but in our experience, it worked as expected.</p>\n<p>Time to discuss <strong>performance tweaking</strong>. In Angular you need to count the number of scopes, global scope variables and functions (which makes scope heavy and sometimes tided to other scopes) and in some cases you have to implement a component in pure js as you can find heaps of articles on Angular perf tuning.</p>\n<p>On the other hand React makes it easy to take control of performance by letting you choose between customising when the DOM should be updated by yourself or let React take care of it by a simple comparison of the vDOM. Of course if your model if complex you need to do it yourself by implementing a custom ShouldComponentUpdate method to use efficient way of doing state and dirty checks.</p>\n<p>Next comes my favourite <strong>Code Reuse</strong>. No one can deny the fact that there are thousands of libraries ready to use for Angular. The point here is to not use too many libraries from different vendors due to namespace and priority collisions. React lets you do that by creating reusable components and it is super easy to create complex hierarchical component structures that can be used for future needs. But the winner is Angular as you can almost find anything from a simple date only directive to a complex file upload with background ajax calls to upload your file with nice UI which has progress bar and everything.</p>\n<p>Templating is another important feature of any front end framework. Angular is a clear winner in this case but not in all aspects and you will see why when I walk you through an example. Imagine that you are writing a repeater which looks like this in React:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"69538522002416255000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`var createItem = function(itemText) {\r\n  return <li> {itemText} </li>\r\n}\r\n\r\nreturn <ul> {this.props.items.map(createItem)} </ul>`, `69538522002416255000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-javascript line-numbers\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> <span class=\"token function-variable function\">createItem</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">itemText</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\r\n  <span class=\"token keyword\">return</span> <span class=\"token operator\">&lt;</span>li<span class=\"token operator\">></span> <span class=\"token punctuation\">{</span>itemText<span class=\"token punctuation\">}</span> <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>li<span class=\"token operator\">></span>\r\n<span class=\"token punctuation\">}</span>\r\n\r\n<span class=\"token keyword\">return</span> <span class=\"token operator\">&lt;</span>ul<span class=\"token operator\">></span> <span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>items<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span>createItem<span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>ul<span class=\"token operator\">></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>In Angular this will be like:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"13463743773342474000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<ul>\r\n  <li ng-repeat=&quot;item in items&quot;><span ng-bind=&quot;item&quot;></span></li>\r\n</ul>`, `13463743773342474000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ul</span><span class=\"token punctuation\">></span></span>\r\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span> <span class=\"token attr-name\">ng-repeat</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>item in items<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>span</span> <span class=\"token attr-name\">ng-bind</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>item<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>span</span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\r\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ul</span><span class=\"token punctuation\">></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span></span></pre></div>\n<p>Which one is better to you?</p>\n<p>The question here will be how do we get advantage of all of React’s benefits while preserving this great feature of Angular.</p>\n<p>The answer is by using rt pre-compiled templates. You can find more information on this <a href=\"http://wix.github.io/react-templates/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">here</a>.</p>\n<p>Thanks to this awesome feature the code above will become:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"26339731510430474000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<ul>\r\n  <li rt-repeat=&quot;item in items&quot;>{item} at index {itemIndex}</li>\r\n</ul>`, `26339731510430474000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ul</span><span class=\"token punctuation\">></span></span>\r\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span> <span class=\"token attr-name\">rt-repeat</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>item in items<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>{item} at index {itemIndex}<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\r\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ul</span><span class=\"token punctuation\">></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span></span></pre></div>\n<p>And this is a true <strong>if expression</strong> which means this will not render if the condition is false:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"10604923695725122000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<label rt-if=&quot;chips.isGoodForHealth&quot;> I don't think so </label>`, `10604923695725122000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>label</span> <span class=\"token attr-name\">rt-if</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>chips.isGoodForHealth<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span> I don't think so <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>label</span><span class=\"token punctuation\">></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>It is nice, isn’t it. Now wait for this sugar:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"45717313012831900000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<div rt-scope=&quot;this.getItems() as items&quot; title=&quot;{item.title}&quot;>\r\n  Item Description: {item.description}<br />\r\n  Last viewed at:\r\n  <span rt-class=&quot;{status:true, lasSeen:this.lastSeen(item) > '25-11-2015'}&quot;\r\n    >{item.lastSeen}</span\r\n  >\r\n</div>`, `45717313012831900000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">rt-scope</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>this.getItems() as items<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">title</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>{item.title}<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\r\n  Item Description: {item.description}<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>br</span> <span class=\"token punctuation\">/></span></span>\r\n  Last viewed at:\r\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>span</span> <span class=\"token attr-name\">rt-class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>{status:true, lasSeen:this.lastSeen(item) > '25-11-2015'}<span class=\"token punctuation\">\"</span></span>\r\n    <span class=\"token punctuation\">></span></span>{item.lastSeen}<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>span</span>\r\n  <span class=\"token punctuation\">></span></span>\r\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>Also for <strong>transclusion</strong>:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"14352372781019929000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<span>{this.props.children}</span>`, `14352372781019929000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>span</span><span class=\"token punctuation\">></span></span>{this.props.children}<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>span</span><span class=\"token punctuation\">></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>And <strong>handling events</strong>:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"26484335328923850000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied to clipboard ✅\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`<div>\r\n  <div\r\n    rt-repeat=&quot;task in tasks&quot;\r\n    style=&quot;font-weight:{task.selected ? 'bold' : 'normal' }&quot;\r\n    onClick=&quot;() => this.toggleTask(task)&quot;\r\n  >\r\n    {task.title}\r\n  </div>\r\n  <button onClick=&quot;{this.save}&quot;>Save</button>\r\n</div>`, `26484335328923850000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                Copy<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-html line-numbers\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span>\r\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span>\r\n    <span class=\"token attr-name\">rt-repeat</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>task in tasks<span class=\"token punctuation\">\"</span></span>\r\n    <span class=\"token special-attr\"><span class=\"token attr-name\">style</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token value css language-css\"><span class=\"token selector\">font-weight:</span><span class=\"token punctuation\">{</span>task.selected ? <span class=\"token string\">'bold'</span> <span class=\"token punctuation\">:</span> <span class=\"token string\">'normal'</span> <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">\"</span></span></span>\r\n    <span class=\"token special-attr\"><span class=\"token attr-name\">onClick</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token value javascript language-javascript\"><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">toggleTask</span><span class=\"token punctuation\">(</span>task<span class=\"token punctuation\">)</span></span><span class=\"token punctuation\">\"</span></span></span>\r\n  <span class=\"token punctuation\">></span></span>\r\n    {task.title}\r\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\r\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>button</span> <span class=\"token special-attr\"><span class=\"token attr-name\">onClick</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token value javascript language-javascript\"><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>save<span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">\"</span></span></span><span class=\"token punctuation\">></span></span>Save<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>button</span><span class=\"token punctuation\">></span></span>\r\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p><strong>Conclusion</strong>: It seems that the question is wrong basically because each framework has something special to offer and is used it a specific scenario. Also you can combine them together (we’ve done that in one project and it is very nice and easy to get done) to use the React’s fast rendering experience along with end-to-end features of Angular. Of course there are a lot of other ways to combine React with other techs to replace Angular but they have their own pros and cons.</p>","timeToRead":5,"frontmatter":{"title":"Angular or React???","unformattedDate":"2016-06-21T00:00:00.000Z","date":"Jun 21, 2016","path":"/angular-or-react/","author":"Yaser Adel Mehraban","tags":["angularjs","binding","debugging","performance","reactjs","scope","template","transclusion"],"thumbnail":{"childImageSharp":{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAIEBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAdWwkAf/xAAYEAADAQEAAAAAAAAAAAAAAAABAhADEf/aAAgBAQABBQLVnBnL/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAh/9oACAEDAQE/AVyf/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFxAAAwEAAAAAAAAAAAAAAAAAARESIP/aAAgBAQAGPwIStf/EABoQAQADAAMAAAAAAAAAAAAAAAEQESEAMUH/2gAIAQEAAT8hB8vb5eQh7Bn/2gAMAwEAAgADAAAAEHfP/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAEDAQE/ENAT/8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQIBAT8QJ//EABsQAQEAAgMBAAAAAAAAAAAAAAERACEQQWFR/9oACAEBAAE/EFIp0DN91IS7+4ukDxXTg0HEqp6XISQnH//Z"},"backgroundColor":"transparent","images":{"fallback":{"src":"/static/37031334f7623efe9eed37f2023c70c7/8e40d/angular-vs-react.png","srcSet":"/static/37031334f7623efe9eed37f2023c70c7/216f2/angular-vs-react.png 750w,\n/static/37031334f7623efe9eed37f2023c70c7/8e40d/angular-vs-react.png 760w","sizes":"(min-width: 760px) 760px, 100vw"},"sources":[{"srcSet":"/static/37031334f7623efe9eed37f2023c70c7/426c6/angular-vs-react.webp 750w,\n/static/37031334f7623efe9eed37f2023c70c7/28e90/angular-vs-react.webp 760w","type":"image/webp","sizes":"(min-width: 760px) 760px, 100vw"}]},"width":760,"height":400}}}}}}]}},"pageContext":{"tag":"performance"}},"staticQueryHashes":[],"slicesMap":{}}