<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Atif Afzal</title>
    <description>The latest articles on DEV Community by Atif Afzal (@atfzl).</description>
    <link>https://dev.to/atfzl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F198655%2Fd4ab566e-3951-4ebc-acbc-c412238c6095.jpeg</url>
      <title>DEV Community: Atif Afzal</title>
      <link>https://dev.to/atfzl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/atfzl"/>
    <language>en</language>
    <item>
      <title>Optimizing Netlify</title>
      <dc:creator>Atif Afzal</dc:creator>
      <pubDate>Mon, 06 Sep 2021 18:23:39 +0000</pubDate>
      <link>https://dev.to/atfzl/optimizing-netlify-k6i</link>
      <guid>https://dev.to/atfzl/optimizing-netlify-k6i</guid>
      <description>&lt;p&gt;I don’t work at netlify but I’ll show how their Single Page Application load time can be improved.&lt;/p&gt;

&lt;p&gt;Log in to &lt;a href="https://netlify.com"&gt;https://netlify.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q61hBBf---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/2c1d9195-c287-4dd0-a8e9-c091a90385a6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q61hBBf---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/2c1d9195-c287-4dd0-a8e9-c091a90385a6.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll be redirected to &lt;a href="https://app.netlify.com"&gt;https://app.netlify.com&lt;/a&gt; after logging in. This is the SPA we’ll be optimizing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--naLr9ngJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/f137516e-7d80-4b64-ad8a-0c8ca5f81487.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--naLr9ngJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/f137516e-7d80-4b64-ad8a-0c8ca5f81487.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open Chrome DevTools (cmd + options + i)&lt;br&gt;&lt;br&gt;
Select &lt;code&gt;Performance&lt;/code&gt; Panel&lt;/p&gt;

&lt;p&gt;Make sure &lt;code&gt;Screenshot&lt;/code&gt; option selected (useful to check when app was loaded)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Sq-bIAI2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/a26c050a-8ca5-47c9-9249-f41a56d80dde.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Sq-bIAI2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/a26c050a-8ca5-47c9-9249-f41a56d80dde.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Start recording and refresh the page. Stop the recording when the page has loaded. We have the DevTools open in detached mode to view the timeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nGD7kxU9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/111e10b7-ca15-4349-82c1-3baadc933630.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nGD7kxU9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/111e10b7-ca15-4349-82c1-3baadc933630.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On closer look in the network section, it looks like the network call &lt;code&gt;api.netlify.com/api/v1/user&lt;/code&gt; is duplicated. &lt;code&gt;api.segment.io/v1/p&lt;/code&gt; is also duplicated but that doesn’t look much interesting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ShPViQmk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/0fca616a-5007-4cc2-968f-ca58346745e2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ShPViQmk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/0fca616a-5007-4cc2-968f-ca58346745e2.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We go to the Network panel of DevTools to check the details about this &lt;code&gt;user&lt;/code&gt; api.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rXIB8-WW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/122b4e82-2097-4ad0-b0de-0538e5e8dda5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rXIB8-WW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/122b4e82-2097-4ad0-b0de-0538e5e8dda5.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we check the call stack for both these calls.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DWBuD_jI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/a820bc29-ef17-4d96-b9a5-23e336ded248.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DWBuD_jI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/a820bc29-ef17-4d96-b9a5-23e336ded248.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rNEvAsJ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/c125f121-5b54-4ed7-8202-629f6961214e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rNEvAsJ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/c125f121-5b54-4ed7-8202-629f6961214e.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both call stack look pretty similar with one difference.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- App.js:432
+ App.js:459
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Different lines in the same file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R9qzrFRQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/fd1e6d5c-707c-4ac9-89bd-b048bb661d72.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R9qzrFRQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/fd1e6d5c-707c-4ac9-89bd-b048bb661d72.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’re lucky Netlify has source-maps enabled in public, otherwise we’d see minify code.&lt;/p&gt;

&lt;p&gt;The first &lt;code&gt;useEffect&lt;/code&gt; is meant to run when the app loads for first time, at this time &lt;code&gt;userId&lt;/code&gt; is not defined.&lt;/p&gt;

&lt;p&gt;The second &lt;code&gt;useEffect&lt;/code&gt; is running again when &lt;code&gt;userId&lt;/code&gt; is not defined. It should be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  if (userId) {
    load(props);
  }
}, [userId]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This will fix the api call being made twice.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now back to the timeline, I see an opportunity for improving the app load time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JYpU5AZt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/28530f9b-596c-4427-9d11-dc49935aca89.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JYpU5AZt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/28530f9b-596c-4427-9d11-dc49935aca89.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looks like the main thread is not doing much while the network calls are being made. The current process is in series: the JavaScript runs and this code makes some network calls. We can do these in parallel because the network calls are handled by browser in a separate thread.&lt;/p&gt;

&lt;p&gt;To do this we’d normally need the source to build the code but we’ll be using &lt;a href="https://developer.chrome.com/blog/new-in-devtools-65/#overrides"&gt;Chrome Local Overrides&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have the main html file &lt;code&gt;overview&lt;/code&gt; and main js file &lt;code&gt;app.bundle.js&lt;/code&gt; overridden with my local copy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_PdZdptk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/0092f1ed-6ae0-4bc5-907d-a59ef751323c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_PdZdptk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/0092f1ed-6ae0-4bc5-907d-a59ef751323c.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I found a place where I’ll short-circuit the api call for &lt;code&gt;user&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jIZa6_2Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/db8f5341-1c43-44a5-9151-fa8569db82ce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jIZa6_2Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/db8f5341-1c43-44a5-9151-fa8569db82ce.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Updating this to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  user() {
    return window.userPromise || this.request('/user');
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we’ll define &lt;code&gt;window.userPromise&lt;/code&gt; in the main HTML file because we want this api call made ASAP. We’ll add a new &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag and add our &lt;code&gt;/user&lt;/code&gt; api call with the correct access token from the local storage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Fl-PhApi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/32f3318a-6d9e-4b23-a7a6-4aaab08cf674.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fl-PhApi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/32f3318a-6d9e-4b23-a7a6-4aaab08cf674.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And it works, we now have an api call at the start of page, in parallel as the main JavaScript code runs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TP9wI4t0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/4ebb7afe-64c5-4490-a991-a15fa732452c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TP9wI4t0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/4ebb7afe-64c5-4490-a991-a15fa732452c.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But there are 2 more network calls which are blocking the app render, let’s optimize them in the same way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_GJ9TbZ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/61866cba-07bf-4bbc-aa03-4545934d1cf1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_GJ9TbZ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/61866cba-07bf-4bbc-aa03-4545934d1cf1.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We now have a busy main thread, networks calls and JavaScript code are being run in parallel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NUadw86i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/891b1b3b-683c-4e4a-817a-75e2932a80e2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NUadw86i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/891b1b3b-683c-4e4a-817a-75e2932a80e2.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For my system and network, I could see around &lt;strong&gt;40% reduction in app load time from 2000ms to 1200ms&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is a common scenario in SPA using bundling systems like Webpack, API calls are made after the code is run. Early API calls is a simple method to improve app load time for a lot of web apps.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <item>
      <title>Don’t attach tooltips to document.body</title>
      <dc:creator>Atif Afzal</dc:creator>
      <pubDate>Wed, 10 Mar 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/atfzl/don-t-attach-tooltips-to-document-body-hk4</link>
      <guid>https://dev.to/atfzl/don-t-attach-tooltips-to-document-body-hk4</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Instead of attaching tooltips directly to &lt;code&gt;document.body&lt;/code&gt;, attach them to a predefined div in &lt;code&gt;document.body&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BAD&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body&amp;gt;
    &amp;lt;!-- temporary div, vanishes when tooltips vanishes --&amp;gt;
    &amp;lt;div&amp;gt;my tooltip&amp;lt;/div&amp;gt;
&amp;lt;body&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;GOOD&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body&amp;gt;
    &amp;lt;!-- this div stays forever, just for attaching tooltips --&amp;gt;
    &amp;lt;div id="tooltips-container"&amp;gt;
        &amp;lt;!-- temporary div, vanishes when tooltips vanishes --&amp;gt;
        &amp;lt;div&amp;gt;my tooltip&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;body&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Tooltips in our app were taking &lt;code&gt;&amp;gt;80ms&lt;/code&gt;. And during this time, the main thread was blocked, you couldn’t interact with anything.&lt;/p&gt;

&lt;p&gt;Other components like modal, popover, dropdown had similar performance issues. In some cases, a modal took more than 1 second to appear while making the UI unresponsive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--spMaM8z---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/42567303-439e-4b20-84dc-0acd2179691e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--spMaM8z---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/42567303-439e-4b20-84dc-0acd2179691e.png" alt="Tooltip performance timeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main reason for the slowness of Tooltip was &lt;code&gt;Recalculate Style&lt;/code&gt; being called at the end of mouseover event call stack which takes a lot of time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_3M6-oLa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/3606e18e-5417-417f-b564-bb34f04c4407.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_3M6-oLa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/3606e18e-5417-417f-b564-bb34f04c4407.png" alt="Recalculate Style in Performance Timeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I noticed the tooltip performance was inversely proportional to number of DOM nodes currently in document.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AB2EF2Jh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/cd5638e6-8875-4b3a-9792-16487dcb001b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AB2EF2Jh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/cd5638e6-8875-4b3a-9792-16487dcb001b.png" alt="Performance DOM Nodes graph"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before diving deep into the investigation, we’ll talk about some prerequisites.&lt;/p&gt;

&lt;h2&gt;
  
  
  How browser works at page load
&lt;/h2&gt;

&lt;p&gt;The browser creates a DOM tree from the HTML string.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6r-WhwjR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/a4dd83f7-1c48-4436-96c1-28fad953701d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6r-WhwjR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/a4dd83f7-1c48-4436-96c1-28fad953701d.png" alt="Dom Tree from HTML String"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see it as &lt;code&gt;Parse HTML&lt;/code&gt; in the performance timeline in Chrome DevTools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E0E06iC1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/0b42e521-5df8-4d57-b119-144d6018e3a2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E0E06iC1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/0b42e521-5df8-4d57-b119-144d6018e3a2.png" alt="Parse HTML in Performance Timeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then the CSS is parsed and browser creates the CSSOM (CSS Object Model).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VZ8jrH9G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/c143d55c-fe22-4528-a9af-79d83c0b3fe1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VZ8jrH9G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/c143d55c-fe22-4528-a9af-79d83c0b3fe1.jpg" alt="CSS Object Model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then the browser combines the DOM and CSSOM to create the &lt;code&gt;render tree&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Usl4cdb7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/4909edcc-87b1-41c1-b5a4-00e87b1c9f8b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Usl4cdb7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/4909edcc-87b1-41c1-b5a4-00e87b1c9f8b.png" alt="Render Tree"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Render tree consists of elements currently visible on the page. Elements with property like &lt;code&gt;display: none&lt;/code&gt; are not part of the &lt;code&gt;render tree&lt;/code&gt;. If we have a pseudo element in CSS like &lt;code&gt;after&lt;/code&gt;, then it is part of the &lt;code&gt;render tree&lt;/code&gt; although it is not a part of the DOM. The creation/modification of the render tree is called &lt;code&gt;Recalculate Style&lt;/code&gt; in the performance timeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_3M6-oLa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/3606e18e-5417-417f-b564-bb34f04c4407.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_3M6-oLa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/3606e18e-5417-417f-b564-bb34f04c4407.png" alt="Recalculate Style in Performance Timeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Important: render tree is invalidated when we modify DOM or change styles of any element.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next step is &lt;code&gt;layout&lt;/code&gt;. Layout is calculating the size and positions of elements of the render tree, to know where we have to draw exactly. This is referred to as &lt;code&gt;Layout&lt;/code&gt; in the performance timeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IojDAi62--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/d3ddd1c8-5f55-47c6-827f-ce0dc234c312.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IojDAi62--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/d3ddd1c8-5f55-47c6-827f-ce0dc234c312.png" alt="Layout in Performance Timeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Layout&lt;/code&gt; may need to be done again whenever there is a change in size/position of an element which affects the position of all the elements in the page. &lt;code&gt;Layout&lt;/code&gt; is also known as &lt;code&gt;Reflow&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next steps are &lt;code&gt;paint&lt;/code&gt; and &lt;code&gt;composting&lt;/code&gt; but we won’t talk about them here as they are not important for explanation of this topic.&lt;/p&gt;

&lt;h2&gt;
  
  
  How browser handles rendering during runtime
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JR1RTCay--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/cfbe79de-9352-4f32-a8af-f839a1784eef.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JR1RTCay--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/cfbe79de-9352-4f32-a8af-f839a1784eef.jpg" alt="Rendering during Runtime"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To render a frame in a browser, we go in this order: JavaScript runs, then there are style calculation, then layout. Ignore Paint and Composite for now.&lt;/p&gt;

&lt;p&gt;When we access any layout property like &lt;code&gt;offsetWidth&lt;/code&gt;, &lt;code&gt;offsetParent&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt; etc, the browser returns the value from previously calculated layout calculations, which is not expensive as the calculation was done earlier in the previous frame and now we are just reading it.&lt;/p&gt;

&lt;p&gt;But what happens when we change a style on an element or modify the DOM? Then the browser has its own heuristics and is smart enough to know if the browser needs to &lt;code&gt;Recalculate Style&lt;/code&gt;/&lt;code&gt;Layout&lt;/code&gt; in the current frame or defer it for later.&lt;/p&gt;

&lt;p&gt;You can see it as &lt;code&gt;Schedule Style Recalculation&lt;/code&gt; in timeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9ndYm1dq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/576e35de-1548-4fa9-bc6b-1bc0414a0f3f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9ndYm1dq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/576e35de-1548-4fa9-bc6b-1bc0414a0f3f.png" alt="Schedule Style Recalculation in Timeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem happens when we try to access a layout property just after we change style/modify DOM. Then the browser has to force &lt;code&gt;Recalculate Style&lt;/code&gt;/&lt;code&gt;Layout&lt;/code&gt; because browser has to return the current value, it cannot give you a stale value from the previous frame. This causes the problem known as &lt;code&gt;Layout Thrashing&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;BAD&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Here we are first changing the style and then immediately reading &lt;code&gt;offsetHeight&lt;/code&gt; property which causes a &lt;code&gt;Synchronous Forced Layout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kuBijWOf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/aae26576-396d-46cf-9265-be3f12ebb40b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kuBijWOf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/aae26576-396d-46cf-9265-be3f12ebb40b.png" alt="Bad Style Change"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll see this warning in browser when this happens:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2o-Ayg8B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/911239f1-6cc4-4ef2-a40d-66d011330b4f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2o-Ayg8B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/911239f1-6cc4-4ef2-a40d-66d011330b4f.png" alt="Forced Reflow Warning"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GOOD&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This is fine because we are first reading the layout property &lt;code&gt;offsetHeight&lt;/code&gt; which is not expensive as we are just reading the value from the previous frame’s layout calculation. Then we change the style later which is ok, the layout might still happen but it is up to browser when to do it, it is not forced.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MwZtOnMx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/aca72dbb-333e-4d2f-8e3b-2da94edae8f2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MwZtOnMx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/aca72dbb-333e-4d2f-8e3b-2da94edae8f2.png" alt="Good Style Change"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Investigation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YDI_9qYx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/79ed6c15-e9b3-4929-a75e-3d74dba53232.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YDI_9qYx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/79ed6c15-e9b3-4929-a75e-3d74dba53232.png" alt="Recalculate Style summary"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we can see a lot of elements (807) are affected by the &lt;code&gt;Recalculate Style&lt;/code&gt; event which is the reason this event takes a lot of time.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Call Stacks&lt;/code&gt; detail gives us important information to debug this issue. The field &lt;code&gt;Recalculation Forced&lt;/code&gt; shows the value &lt;code&gt;getOffsetParent @ popper.js:188&lt;/code&gt; which is this code in &lt;code&gt;popper.js@1.15.0&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var offsetPArent = element.offsetParent;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next field is &lt;code&gt;First Invalidation&lt;/code&gt; with value &lt;code&gt;Tooltip._this.handleEnter @ Tooltip.js:165&lt;/code&gt; in &lt;code&gt;@material-ui/core@3.9.3&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_this.childrenRef.setAttribute('title', '');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;First Invalidation&lt;/code&gt; shows where in code, the render tree was first invalidated which later caused &lt;code&gt;Forced Reflow&lt;/code&gt; because of &lt;code&gt;Recalculation Forced&lt;/code&gt; code.&lt;/p&gt;

&lt;p&gt;Doing &lt;code&gt;setAttribute&lt;/code&gt; on an element in DOM is invalidating the render tree, and then accessing the &lt;code&gt;offsetParent&lt;/code&gt; causes a &lt;code&gt;Forced Synchronous Layout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Had this been done in the opposite direction it wouldn’t be a problem.&lt;/p&gt;

&lt;p&gt;I tried commenting the setAttribute code and again ran the performance timeline. But the issue was still there but the invalidation was happening somewhere else.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lAcpRdxY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/054069df-d88a-417e-a652-c8d729894adf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lAcpRdxY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/054069df-d88a-417e-a652-c8d729894adf.png" alt="First Invalidated"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The invalidation is now happening when the tooltip is added to the body, which invalidates the render tree.&lt;/p&gt;

&lt;p&gt;Popper accessing the &lt;code&gt;offsetParent&lt;/code&gt; property after attaching the tooltip to the body is causing &lt;code&gt;Forced Reflow&lt;/code&gt;. If this property access was done before attaching the tooltip to body, the reflow would not have happened.&lt;/p&gt;

&lt;p&gt;But all this is not in our control as the code is in the third party library &lt;code&gt;popper.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, what can we do?&lt;/p&gt;

&lt;p&gt;Next, I created a separate container in the body where the tooltip would always be attached.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body&amp;gt;
    &amp;lt;div id="tooltips-container"&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;div id="myapp"&amp;gt;...&amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And instructed the popper to be rendered in this container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const popperProps = {
    container: () =&amp;gt; document.getElementById('tooltips-container'),
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the performance was greatly improved, the &lt;code&gt;Recalculate Style&lt;/code&gt; still happened but its cost was less than before. 0.79ms down from 66.57ms:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W9T0dfZV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/2814d1be-d234-4224-8999-24d32e64605e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W9T0dfZV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/2814d1be-d234-4224-8999-24d32e64605e.png" alt="Low Recalculate Style"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What happened here? The tooltip was attached to the tooltip container and not to the body. This invalidated a much smaller subtree, which was the tooltip container. The tooltip container is not visible in the page, so modifying it doesn’t invalidate the complete page render tree. If the tooltip container would have been visible in the page, then the complete render tree would be invalidated but in this case only an independent subtree was invalidated. &lt;code&gt;Recalculating Style&lt;/code&gt; for a small subtree of 3 doesn’t take a lot of time and hence is faster.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Element Affected&lt;/code&gt; is 3 which is the number of nodes inside our tooltip container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div id="tooltips-container"&amp;gt;
    &amp;lt;div role="tooltip" ...&amp;gt;
        &amp;lt;div class="MuiTooltip-tooltip-66 ..." ...&amp;gt;
            &amp;lt;span class="tooltipContent__.."&amp;gt;
                Tooltip Text
            &amp;lt;/span&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ideal case would be to not access the &lt;code&gt;offsetParent&lt;/code&gt; property in DOM after attaching it, but it is needed for &lt;code&gt;popper.js&lt;/code&gt; to calculate where to render the tooltip.&lt;/p&gt;

&lt;p&gt;Popper.js first attaches the tooltip to the body and then moves it to the correct position. If popper.js calculated the position first and then attached the tooltip to the body later, then we wouldn’t have this problem of &lt;code&gt;Recalculate Style&lt;/code&gt;. We are using an older version of &lt;code&gt;@material-ui/core@3.9.3&lt;/code&gt; which is using an old version of &lt;code&gt;popper.js@1.15.0&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Result
&lt;/h2&gt;

&lt;p&gt;The mouseover event in our tooltip finishes much quickly and does not cause jank in the experience.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;8ms from 80ms&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Tooltips are now &lt;strong&gt;10x faster&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---F7YRMBc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/1e35b3bb-c083-4da7-9c2c-8797bab83e12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---F7YRMBc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/1e35b3bb-c083-4da7-9c2c-8797bab83e12.png" alt="Final Result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.udacity.com/course/website-performance-optimization--ud884"&gt;Website Performance Optimization - Udacity&lt;/a&gt; (App load optimization)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.udacity.com/course/browser-rendering-optimization--ud860"&gt;Browser Rendering Optimization - Udacity&lt;/a&gt; (App runtime optimization)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing?utm_source=devtools#avoid_forced_synchronous_layouts"&gt;Avoid forced synchronous layouts - Web Fundamentals Google&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/paulirish/5d52fb081b3570c81e3a"&gt;What DOM element property access forces layout / reflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <item>
      <title>Understanding Solid: JSX</title>
      <dc:creator>Atif Afzal</dc:creator>
      <pubDate>Mon, 25 Nov 2019 20:28:56 +0000</pubDate>
      <link>https://dev.to/atfzl/understanding-solid-jsx-584p</link>
      <guid>https://dev.to/atfzl/understanding-solid-jsx-584p</guid>
      <description>&lt;p&gt;&lt;a href="https://facebook.github.io/jsx/"&gt;JSX&lt;/a&gt; was introduced by Facebook for complementing React in javascript. It is a common misconception that JSX is somehow coupled with React or its siblings like React Native, Preact, Inferno etc. But JSX is an extension to javascript and can be used in other places beside React.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ryansolid/solid"&gt;Solid&lt;/a&gt; uses JSX to render vanilla DOM elements. In React the &lt;code&gt;&amp;lt;div /&amp;gt;&lt;/code&gt; compiles to &lt;code&gt;React.createElement('div')&lt;/code&gt; but in Solid you could say it compiles to &lt;code&gt;document.createElement('div')&lt;/code&gt; (actually it uses HTML templates, more on this ahead).&lt;/p&gt;

&lt;h2&gt;
  
  
  Hello World component:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;HelloWorld&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Hello World
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will (conceptually) compile to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;HelloWorld&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;el$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;el$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;el$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Actually solid uses &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template"&gt;HTML template element&lt;/a&gt; because it is more performant for creating new instances from same template.&lt;/p&gt;

&lt;p&gt;So it actually compiles to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;_$template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;template&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstChild&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_tmpl$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_$template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;div&amp;gt;Hello World&amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;HelloWorld&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_tmpl$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cloneNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the previous &lt;a href="https://www.atfzl.com/understanding-solid-reactivity-basics"&gt;post&lt;/a&gt; we know how solid is tracking dependencies. We’ll use it here now by creating a counter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will compile to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_tmpl$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_$template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_el$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_tmpl$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cloneNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;_el$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_el$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}();&lt;/span&gt; &lt;span class="c1"&gt;// NOTE: this is an iife!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the string passed to &lt;code&gt;_$template&lt;/code&gt; does not have the part where we had the dynamic value &lt;code&gt;{state.counter}&lt;/code&gt;. It will be added later in &lt;code&gt;createEffect&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now whenever we update the counter, the createEffect block runs which updates the innerText of &lt;code&gt;_el$&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSX with nesting:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Counter:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compiles to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_tmpl$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_$template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;div&amp;gt;&amp;lt;div&amp;gt;Counter:&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_el$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_tmpl$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cloneNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nx"&gt;_el$2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_el$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstChild&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;_el$3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_el$2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextSibling&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;_el$3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_el$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the static part string: &lt;code&gt;Counter:&lt;/code&gt; is left inside the template string passed to &lt;code&gt;_$template&lt;/code&gt; We refer to the nested elements by using combination of &lt;code&gt;firstChild&lt;/code&gt;, &lt;code&gt;nextSibling&lt;/code&gt; etc.&lt;/p&gt;

&lt;p&gt;And this is in short how Solid works. Effectively these two parts: &lt;code&gt;dependency tracking&lt;/code&gt; and &lt;code&gt;JSX&lt;/code&gt; provide the best of both worlds. We get the best performance by executing only the minimal code which is needed and with &lt;code&gt;JSX&lt;/code&gt; we get to keep the mental model introduced by React which keeps us more productive.&lt;/p&gt;

</description>
      <category>solidjs</category>
      <category>react</category>
      <category>javascript</category>
      <category>reactive</category>
    </item>
    <item>
      <title>Using iTerm triggers</title>
      <dc:creator>Atif Afzal</dc:creator>
      <pubDate>Tue, 19 Nov 2019 18:17:38 +0000</pubDate>
      <link>https://dev.to/atfzl/using-iterm-triggers-1h93</link>
      <guid>https://dev.to/atfzl/using-iterm-triggers-1h93</guid>
      <description>&lt;p&gt;iTerm triggers can be used for converting text in your terminal to URLs and make them clickable. This is useful for creating JIRA issue links whenever there is a &lt;code&gt;JIRA-1234&lt;/code&gt; like pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps:
&lt;/h2&gt;

&lt;p&gt;Go to &lt;code&gt;iTerm -&amp;gt; Preferences -&amp;gt; Profiles -&amp;gt; Advanced -&amp;gt; Triggers Edit&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_7Z7JYaX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/89d0fab1-7602-4b5b-8b05-8d22186df123.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_7Z7JYaX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/89d0fab1-7602-4b5b-8b05-8d22186df123.png" alt="iterm preference"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add an entry in the table&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Regular Expression: (?i)JIRA-\d+
Action: Make Hyperlink
Parameters: https://jira.yourhost.com/jira/browse/\0¯
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KhdUjLxL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/67c579d6-ec52-4d06-8c69-4ffc3cfe385e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KhdUjLxL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blotcdn.com/blog_b4fa49aeb5e8474db144c0adb7862258/_image_cache/67c579d6-ec52-4d06-8c69-4ffc3cfe385e.png" alt="table"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now whenever there is a pattern with &lt;code&gt;JIRA-1234&lt;/code&gt;, it will become a clickable hyperlink.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Use emacs key bindings everywhere</title>
      <dc:creator>Atif Afzal</dc:creator>
      <pubDate>Tue, 12 Nov 2019 13:06:26 +0000</pubDate>
      <link>https://dev.to/atfzl/use-emacs-key-bindings-everywhere-42b9</link>
      <guid>https://dev.to/atfzl/use-emacs-key-bindings-everywhere-42b9</guid>
      <description>&lt;p&gt;I am used to emacs keybinding.&lt;/p&gt;

&lt;p&gt;My &lt;code&gt;caps lock&lt;/code&gt; is mapped to &lt;code&gt;ctrl&lt;/code&gt; to avoid &lt;a href="https://www.google.com/search?q=emacs+pinky"&gt;emacs pinky&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I am also used to making movements the emacs way , i.e.,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ctrl+f: right arrow
ctrl+b: left arrow
ctrl+p: up arrow
ctrl+n: down arrow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have also remapped &lt;code&gt;Ctrl+g&lt;/code&gt; to &lt;code&gt;escape&lt;/code&gt; because I despise the escape key in the MacBook Pro touch bar.&lt;/p&gt;

&lt;p&gt;Mac supports this keybinding in most applications but these do not work for all applications. Like in my case it was &lt;a href="https://itunes.apple.com/us/app/notability/id736189492"&gt;Notability&lt;/a&gt;. For any kind of text editing, easy movement is a must.&lt;/p&gt;

&lt;p&gt;After a lot of googling I found out about &lt;a href="https://pqrs.org/osx/karabiner/"&gt;Karabiner-Elements&lt;/a&gt; which modifies the key bindings in the most stable and reliable way. It also has some nice customisations like ignoring keybindings for some set of applications. I am ignoring emacs because it already has the correct keybinding and using the modified keybindings messes it up.&lt;/p&gt;

&lt;p&gt;After installing, open up the config &lt;code&gt;~/.config/karabiner/karabiner.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is my Karabiner configurations for above mentioned modifications:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;profiles[0].simple_modifications&lt;/code&gt; =&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
    "from": {
      "key_code": "caps_lock"
    },
    "to": {
      "key_code": "left_control"
    }
  }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;profiles[0].complex_modifications.rules&lt;/code&gt; =&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
    "description": "Ctrl+F to right_arrow",
    "manipulators": [
      {
        "description": "emacs like movement",
        "from": {
          "key_code": "f",
          "modifiers": {
            "mandatory": [
              "left_control"
            ]
          }
        },
        "to": [
          {
            "key_code": "right_arrow"
          }
        ],
        "conditions": [
          {
            "type": "frontmost_application_unless",
            "bundle_identifiers": [
              "^org\\.gnu\\.Emacs"
            ]
          }
        ],
        "type": "basic"
      }
    ]
  },
  {
    "description": "Ctrl+B to left_arrow",
    "manipulators": [
      {
        "description": "emacs like movement",
        "from": {
          "key_code": "b",
          "modifiers": {
            "mandatory": [
              "left_control"
            ]
          }
        },
        "to": [
          {
            "key_code": "left_arrow"
          }
        ],
        "conditions": [
          {
            "type": "frontmost_application_unless",
            "bundle_identifiers": [
              "^org\\.gnu\\.Emacs"
            ]
          }
        ],
        "type": "basic"
      }
    ]
  },
  {
    "description": "Ctrl+P to up_arrow",
    "manipulators": [
      {
        "description": "emacs like movement",
        "from": {
          "key_code": "p",
          "modifiers": {
            "mandatory": [
              "left_control"
            ]
          }
        },
        "to": [
          {
            "key_code": "up_arrow"
          }
        ],
        "conditions": [
          {
            "type": "frontmost_application_unless",
            "bundle_identifiers": [
              "^org\\.gnu\\.Emacs"
            ]
          }
        ],
        "type": "basic"
      }
    ]
  },
  {
    "description": "Ctrl+N to down_arrow",
    "manipulators": [
      {
        "description": "emacs like movement",
        "from": {
          "key_code": "n",
          "modifiers": {
            "mandatory": [
              "left_control"
            ]
          }
        },
        "to": [
          {
            "key_code": "down_arrow"
          }
        ],
        "conditions": [
          {
            "type": "frontmost_application_unless",
            "bundle_identifiers": [
              "^org\\.gnu\\.Emacs"
            ]
          }
        ],
        "type": "basic"
      }
    ]
  },
  {
    "description": "Ctrl+G to Escape",
    "manipulators": [
      {
        "description": "emacs like escape",
        "from": {
          "key_code": "g",
          "modifiers": {
            "mandatory": [
              "left_control"
            ]
          }
        },
        "to": [
          {
            "key_code": "escape"
          }
        ],
        "conditions": [
          {
            "type": "frontmost_application_unless",
            "bundle_identifiers": [
              "^org\\.gnu\\.Emacs"
            ]
          }
        ],
        "type": "basic"
      }
    ]
  }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>emacs</category>
      <category>productivity</category>
      <category>mac</category>
    </item>
    <item>
      <title>Understanding Solid: Reactivity Basics</title>
      <dc:creator>Atif Afzal</dc:creator>
      <pubDate>Thu, 10 Oct 2019 16:20:47 +0000</pubDate>
      <link>https://dev.to/atfzl/understanding-solid-reactivity-basics-39kk</link>
      <guid>https://dev.to/atfzl/understanding-solid-reactivity-basics-39kk</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/ryansolid/solid"&gt;Solid&lt;/a&gt; is a Reactive library for creating user interfaces. Solid updates the DOM only where it is required, without using Virtual DOM. Solid is &lt;a href="https://krausest.github.io/js-framework-benchmark/current.html"&gt;fast&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To understand Solid, first we have to understand its Reactive ideology.&lt;/p&gt;

&lt;p&gt;Let’s take an example of a simple auto updating counter to show how the code looks like and explain how it works under the hood.&lt;/p&gt;

&lt;p&gt;First a counter without a UI: &lt;a href="https://codesandbox.io/s/solid-counter-qsjju"&gt;Solid Counter - CodeSandbox&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;solid-js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code looks too much similar to React hooks and it is actually inspired from React hooks. But there is a major difference, contrary to React, this code will not run again and again top to down like in a React component. Instead we have code blocks which are run whenever their dependencies are updated.&lt;/p&gt;

&lt;h2&gt;
  
  
  createEffect
&lt;/h2&gt;

&lt;p&gt;Whenever the value of  &lt;code&gt;state.count&lt;/code&gt; is updated the code block passed to &lt;code&gt;createEffect&lt;/code&gt; is called which in turn will call &lt;code&gt;console.log&lt;/code&gt; every 1 second.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0
1
2
3
4
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How does &lt;code&gt;createEffect&lt;/code&gt; knows when to call this function whenever &lt;code&gt;state.count&lt;/code&gt; changes ?&lt;/p&gt;

&lt;p&gt;The answer lies in Javascript &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy"&gt;Proxy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The state returned by createState is actually a proxy object, it has setter and getter traps for all properties on the original object.&lt;/p&gt;

&lt;p&gt;Whenever a value is updated on this object, the setter is called. And whenever a value is accessed, the getter is called.&lt;/p&gt;

&lt;p&gt;Let’s try to have a feel with some rough pseudocode:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="c1"&gt;// not real code, rough estimation&lt;/span&gt;
&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;_blocks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="nx"&gt;getter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;activeBlock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_blocks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;activeBlock&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;setter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_blocks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_blocks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;activeBlock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;activeBlock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="nx"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s call the function passed to createEffect as &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When we call createEffect, first we save &lt;code&gt;f&lt;/code&gt; in &lt;code&gt;activeBlock&lt;/code&gt; variable and then run &lt;code&gt;f&lt;/code&gt;. Then whenever a getter is hit, we save &lt;code&gt;activeBlock&lt;/code&gt; with the current property so that the dependent blocks can be run, when there is a hit to its setter.&lt;/p&gt;

&lt;p&gt;In our counter example, &lt;code&gt;f&lt;/code&gt; is the block with &lt;code&gt;console.log(state.count)&lt;/code&gt; in it. For the first time when &lt;code&gt;createEffect&lt;/code&gt; calls &lt;code&gt;f&lt;/code&gt;, it saves &lt;code&gt;f&lt;/code&gt; in &lt;code&gt;activeBlock&lt;/code&gt; variable. Then it runs &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now when &lt;code&gt;f&lt;/code&gt; runs, it encounters &lt;code&gt;state.count&lt;/code&gt; and its getter is executed,. Then &lt;code&gt;f&lt;/code&gt; is pushed to &lt;code&gt;this._blocks&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we also had some other block with &lt;code&gt;state.count&lt;/code&gt;, its reference would also be pushed in the &lt;code&gt;this._blocks&lt;/code&gt; array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2 x Counter = &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If in the future &lt;code&gt;state.count&lt;/code&gt; is updated, its setter will be triggered and it will execute all its saved blocks.&lt;/p&gt;

&lt;p&gt;In this way we do not need to explicitly define what we have to track, and the blocks would be run whenever anything in the block changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  setState instead of setter
&lt;/h2&gt;

&lt;p&gt;Solid emphasises uni-directional data flow like React. So instead of directly updating the value of state, &lt;code&gt;setState&lt;/code&gt; must be used to trigger the setter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reactive html element with solid
&lt;/h2&gt;

&lt;p&gt;Now that we know the basics of &lt;code&gt;createEffect&lt;/code&gt; and how its works, let's use &lt;code&gt;createEffect&lt;/code&gt; to update an HTML element.&lt;/p&gt;

&lt;p&gt;Counter with a UI element: &lt;a href="https://codesandbox.io/s/solid-counter-kpjok"&gt;Solid Counter - CodeSandbox&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we are using createEffect to update the DOM text.&lt;/p&gt;

&lt;p&gt;Similarly we can update className, style and other attributes reactively:&lt;/p&gt;

&lt;h4&gt;
  
  
  className
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;even&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;odd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  style
&lt;/h4&gt;

&lt;p&gt;we are using Object.assign because &lt;code&gt;=&lt;/code&gt; does not work with style attribute.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;black&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;white&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  data-*
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;even&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;odd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These were the basic reactive ideas needed to understand how solid works under the hood. Next post will cover &lt;code&gt;jsx&lt;/code&gt; in solid.&lt;/p&gt;




&lt;p&gt;This is the first blog post of series: &lt;code&gt;Understanding Solid&lt;/code&gt;. Next post: &lt;a href="https://dev.to/atfzl/understanding-solid-jsx-584p"&gt;Understanding Solid: JSX&lt;/a&gt;&lt;/p&gt;

</description>
      <category>solid</category>
      <category>react</category>
      <category>javascript</category>
      <category>dom</category>
    </item>
    <item>
      <title>Using flow and eslint in Emacs</title>
      <dc:creator>Atif Afzal</dc:creator>
      <pubDate>Sun, 06 Nov 2016 00:00:00 +0000</pubDate>
      <link>https://dev.to/atfzl/using-flow-and-eslint-in-emacs-56b5</link>
      <guid>https://dev.to/atfzl/using-flow-and-eslint-in-emacs-56b5</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(require 'company)
(require 'web-mode)
(require 'flycheck)
(require 'flycheck-flow)

;; flow auto complete
;; skip this if you don't use company-mode
(eval-after-load 'company
  '(add-to-list 'company-backends 'company-flow))

;; add eslint and flow checkers to flycheck
(flycheck-add-mode 'javascript-eslint 'web-mode)
(flycheck-add-mode 'javascript-flow 'web-mode)

;;disable jshint since we prefer eslint checking
(setq-default flycheck-disabled-checkers
  (append flycheck-disabled-checkers
    '(javascript-jshint)))

(defun jsWithEslint ()
  "eslint for js files"
  (interactive)
  (web-mode)
  (web-mode-set-content-type "jsx")
  (flycheck-disable-checker 'javascript-flow)
  (flycheck-select-checker 'javascript-eslint)
  (flycheck-mode))

(defun jsWithEslintFlow ()
  "flow and eslint for js files"
  (interactive)
  (web-mode)
  (web-mode-set-content-type "jsx")
  (flycheck-select-checker 'javascript-eslint)
  (flycheck-add-next-checker 'javascript-eslint 'javascript-flow)
  (flycheck-mode))

;; set key shortcuts if you want
;; (global-set-key (kbd "C-c j") 'jsWithEslint)
;; (global-set-key (kbd "C-c f") 'jsWithEslintFlow)

(add-to-list 'auto-mode-alist '("\\.js\\'" . jsWithEslint))
(add-to-list 'magic-mode-alist '("/\\* @flow \\*/" . jsWithEslintFlow))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now all the .js files will use eslint.&lt;br&gt;&lt;br&gt;
But if you have &lt;code&gt;/\* @flow \*/&lt;/code&gt; comment at the first line, flow will also be used.&lt;/p&gt;

&lt;p&gt;To use local eslint and flow-bin from your node_modules, check out this package: &lt;a href="https://github.com/codesuki/add-node-modules-path"&gt;add-node-modules-path&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>flow</category>
      <category>eslint</category>
      <category>emacs</category>
    </item>
  </channel>
</rss>
