<?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: Miško Hevery</title>
    <description>The latest articles on DEV Community by Miško Hevery (@mhevery).</description>
    <link>https://dev.to/mhevery</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%2F647890%2Fa89c8fc1-ceb2-46d2-b354-9ad0d91d7654.jpeg</url>
      <title>DEV Community: Miško Hevery</title>
      <link>https://dev.to/mhevery</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mhevery"/>
    <language>en</language>
    <item>
      <title>How To Embed Tweets Without a Performance Penalty</title>
      <dc:creator>Miško Hevery</dc:creator>
      <pubDate>Thu, 02 Mar 2023 15:36:17 +0000</pubDate>
      <link>https://dev.to/builderio/how-to-embed-tweets-without-a-performance-penalty-494k</link>
      <guid>https://dev.to/builderio/how-to-embed-tweets-without-a-performance-penalty-494k</guid>
      <description>&lt;h2&gt;
  
  
  Why embed Twitter on your website
&lt;/h2&gt;

&lt;p&gt;You have a great product, and your users are raving about it on Twitter. You want to use the social proof on your page to tell new users how awesome you are. Let's embed some tweets into your site! Twitter makes this easy! Click the tree dots context menu and select &lt;code&gt;Embed Tweet&lt;/code&gt;, then follow the instructions. Twitter gives you a code snipped, which you embed into your page and success! You have a tweet embedded on your page.&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--eMcpLujN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1628461105235492864/wSjxF6L0_normal.jpg" alt="Miško Hevery (Builder.io/Qwik) profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Miško Hevery (Builder.io/Qwik)
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/mhevery"&gt;@mhevery&lt;/a&gt;
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Blank page with an embedded tweet. How bad can it be?&lt;br&gt;&lt;br&gt;JS: 1.5MB 🤯&lt;br&gt;PageSpeed score: 61/100 🤯&lt;br&gt;Time to Interactive: 9 sec 🤯&lt;br&gt;TBT: 1.7 sec 🤯&lt;br&gt;&lt;br&gt;What hope does an average site have if a simple tweet requires MegaBytes of JS and seconds to interactivity?&lt;br&gt;&lt;br&gt;&lt;a href="https://t.co/0CJBe6LXCP"&gt;mhevery.github.io/perf-tests/twi…&lt;/a&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      23:55 PM - 23 Dec 2022
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1606438382561026049" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1606438382561026049" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1606438382561026049" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  Embedding a tweet is expensive
&lt;/h2&gt;

&lt;p&gt;We don't give embedding a tweet onto our site much thought, but it turns out that that tweet is quite expensive from a performance perspective. To show you just how expensive that embed is, we have embedded a &lt;a href="https://mhevery.github.io/perf-tests/twitter-embed.html"&gt;single tweet&lt;/a&gt; and then &lt;a href="https://mhevery.github.io/perf-tests/twitter-embed-4.html"&gt;four tweets&lt;/a&gt; into a blank page and asked Google PageSpeed to rank the quality of our site. To make sure that we are measuring just the cost of the embedded tweet, the page we are testing is otherwise blank.&lt;/p&gt;

&lt;p&gt;To our surprise, the results are not great!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a1vjqQwq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F3441e5e8a99c48bbac97c331a731d803%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a1vjqQwq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F3441e5e8a99c48bbac97c331a731d803%3Fwidth%3D800" alt="a screenshot of a table showing the performance hit for 1 and 4 tweet embeds." width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are some highlights of the bad experience people will get on low-powered mobile devices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The users have to wait almost 18 seconds before the page becomes interactive.&lt;/li&gt;
&lt;li&gt;The tweet rendering freezes the UI (not responsive) for 4 seconds.&lt;/li&gt;
&lt;li&gt;Each additional tweet costs the visitor a little over 3 seconds of waiting.&lt;/li&gt;
&lt;li&gt;To render a tweet, the embed script makes about 27 requests and downloads 600 Kb over the wire, which results in 1.6 Mb of JavaScript, out of which only about 50% gets executed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep in mind this is on the blank page. The situation will get worse as the page becomes more complex with more third-party scripts.&lt;/p&gt;

&lt;p&gt;The thing to observe is that the Tweet Embed solution is JavaScript-heavy and requires a lot of JavaScript execution to render the tweet. The more JavaScript on startup, the slower your site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why so expensive
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ev5dYNfQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F8e28399c8e9645af902d17d8cc6233a4%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ev5dYNfQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F8e28399c8e9645af902d17d8cc6233a4%3Fwidth%3D800" alt="a picture of the Joker from the movie dark knight with the caption why so expensive." width="622" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The natural question is to ask, why is this so expensive? Why does Twitter not care about its users and the end-user experience? Well, it is easy to blame Twitter engineers but let's have some empathy for the engineer that designed this system. They were probably under time pressure to deliver, and so they chose the path of least resistance to deliver the Tweet embed feature.&lt;/p&gt;

&lt;p&gt;The Tweet embed is a standard stand-alone application that gets loaded in an iframe. (One iframe per tweet) The application is CSR (client-side rendered) SPA (single page application) written in React. React is a well-tested and loved technology by developers, so the fact that the Twitter engineer chose it for the tweet implementation is unsurprising.&lt;/p&gt;

&lt;p&gt;The Twitter engineers could have chosen other rendering technologies, but it would not have significantly impacted the outcome. We have compared a &lt;a href="https://www.builder.io/blog/movies-app-in-7-frameworks-which-is-fastest-and-why"&gt;movie app written in seven different frameworks&lt;/a&gt;, and the result was mostly the same for all CSR applications. The main winners were the HTML-first frameworks such as &lt;a href="https://astro.build/"&gt;Astro&lt;/a&gt; and &lt;a href="https://qwik.builder.io/"&gt;Qwik&lt;/a&gt; because those deliver primarily HTML rather than JavaScript — more on that later.&lt;/p&gt;

&lt;h2&gt;
  
  
  23 third-party scripts
&lt;/h2&gt;

&lt;p&gt;At this point, stepping back and seeing the big picture is important. A single tweet has lowered our site score to 69. Four tweets to 39! But this is but one third-party script. Google reports that an average site has &lt;a href="https://almanac.httparchive.org/en/2021/third-parties"&gt;23 different third-party scripts&lt;/a&gt;! So this is but one of many more scripts to be embedded into your site. If one third-party script fares so badly, what do you think a site with 23 different third-party scripts will do? There is just no hope that the site will perform well. The site will have a bad user experience, and people will leave.&lt;/p&gt;

&lt;p&gt;It is paramount that we, as site developers, pay attention to third-party scripts and do a better job shielding ourselves from their consequences.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's just another CSR app
&lt;/h2&gt;

&lt;p&gt;The big realization is that each third-party script is yet another application on your site besides your application. We do things to optimize our application, such as SSR (server-side render)/SSG(static site generation), so why don't third-party scripts do that as well?&lt;/p&gt;

&lt;p&gt;Third-party scripts are primarily concerned with the ease of embedding. The primary goal for the Twitter embed is easy embedding for the site developer. When the site developer recognizes that the embed has destroyed the site’s performance, it is too late, and they are unlikely to do much about that. See [3 people problem] later in this article. Because ease of embedding is a priority, the most straightforward thing to do is to cut and paste a JavaScript tag into your site. The CSR (Client Side Rendering) approach will work with any existing solution you use for the site because all the work is done on the client rather than on the server. But precisely, this do-all-work-on-the-client shortcut makes embedding easy. However, the performance of the third-party scripts is poor.&lt;/p&gt;

&lt;p&gt;What we need is a way to embed third-party applications in a cut-and-paste way that actually renders using SSR/SSG (rather than CSR). The problem is that most of our frameworks/libraries are CSR-centric, with SSR as an add-on using meta-frameworks. Notable exceptions are &lt;a href="https://astro.build/"&gt;Astro&lt;/a&gt; and &lt;a href="https://qwik.builder.io/"&gt;Qwik&lt;/a&gt;, which focus on SSR/SSG as a primary delivery mechanism.&lt;/p&gt;

&lt;h2&gt;
  
  
  It all comes down to JavaScript
&lt;/h2&gt;

&lt;p&gt;Once you dig into site performance for long enough, &lt;a href="https://www.builder.io/blog/how-to-improve-website-performance-in-2023"&gt;you realize it all comes down to JavaScript&lt;/a&gt;. Actually, it is three things, but two of them have a well-understood solution, so we are left with JavaScript.&lt;/p&gt;

&lt;p&gt;To make your site fast, it needs three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To send HTML to the client&lt;/li&gt;
&lt;li&gt;To optimize images and CSS&lt;/li&gt;
&lt;li&gt;To minimize the amount of JavaScript on the startup&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most meta-frameworks can do SSR/SSG, so they can send HTML to the client. Meta-frameworks also have good support for Image and CSS optimization. It is not an automatically solved problem, but with a little bit of work on the developer's side, the HTML, Image, and CSS are well-understood problems with well-understood solutions. So if a site fails to deliver on these, it really comes down to the site developer not doing their job or not being aware of how to do it.&lt;/p&gt;

&lt;p&gt;The remaining problem is executing less JavaScript on startup. We don't have good solutions for sending less JavaScript to the client. That is because most meta-frameworks and frameworks use &lt;a href="https://www.builder.io/blog/hydration-is-pure-overhead"&gt;hydration to recover their state&lt;/a&gt;, which results in too much JavaScript execution on the client. That is why solutions such as &lt;a href="https://astro.build/"&gt;Astro&lt;/a&gt;, &lt;a href="https://www.11ty.dev/"&gt;Eleventy&lt;/a&gt;, and &lt;a href="https://qwik.builder.io/"&gt;Qwik&lt;/a&gt; are becoming more popular because they are focusing on addressing the JavaScript problem.&lt;/p&gt;

&lt;p&gt;So the Twitter engineer implementing the Twitter embed fell into the JavaScript problem because most of our solutions are JavaScript-centric.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTML-first embedding
&lt;/h2&gt;

&lt;p&gt;To get good performance, third-party scripts need to send HTML and delay the execution of JavaScript for as long as possible. When the site starts up, there is always some amount of JavaScript that needs to run on the main thread, which is the bottleneck. Unfortunately, third-party scripts' current status quo is that each adds even more JavaScript to the startup cost. Some tools such as &lt;a href="https://partytown.builder.io/"&gt;Partytown&lt;/a&gt; try to help with this, but overall this is not a solved problem. Third-party script providers should strive to improve.&lt;/p&gt;

&lt;p&gt;But remember that third-party providers are really just packaging their applications into an easily embeddable script tag. They themselves usually use existing frameworks/libraries. These frameworks/libraries are CSR-centric with limited ability to do SSR and delay hydration. So while it is easy to blame third parties for slow site startup performance, in the end, the third parties rely on the same frameworks/libraries as we all do, and most of these frameworks are not focused on minimizing the amount of JavaScript at startup.&lt;/p&gt;

&lt;p&gt;In the end, third-party providers don't provide HTML-first solutions because, as an industry, we don't have good HTML-first frameworks to use to deliver those solutions. Sure we have &lt;a href="https://astro.build/"&gt;Astro&lt;/a&gt; and &lt;a href="https://www.11ty.dev/"&gt;Eleventy&lt;/a&gt;, but these frameworks are more meant for static site generation rather than interactive application delivery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our proof of concept for tweet embeds
&lt;/h2&gt;

&lt;p&gt;Let's build the same solution with an HTML-first approach.&lt;/p&gt;

&lt;p&gt;What we are trying to do is to do a client-side include of HTML.&lt;/p&gt;

&lt;p&gt;Ideally, we want this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
   Your content
   &lt;span class="nt"&gt;&amp;lt;include&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;https://qwik-twitter.builder.io/tweet/1606438382561026049.html&amp;gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/include&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, HTML does not have an &lt;code&gt;&amp;lt;include&amp;gt;&lt;/code&gt; tag, so we are cheating with a bit of JavaScript.&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&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;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
Your content
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://qwik-twitter.builder.io/tweet/1606438382561026049.js"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&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;body&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;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where the &lt;code&gt;https://qwik-twitter.builder.io/tweet/1606438382561026049.js&lt;/code&gt; returns:&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="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&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;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentScript&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;div&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;div&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;html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;div&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="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertBefore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;div&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;script&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="s2"&gt;`
   &amp;lt;!-- HTML we want to insert --&amp;gt;
   &amp;lt;div&amp;gt;my tweet&amp;lt;/div&amp;gt;
`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above is HTML wrapped as JavaScript, with very little actual JavaScript.&lt;/p&gt;

&lt;p&gt;The above code allows us to achieve two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It is still easy to embed the tweet into your website as it is a simple cut and paste.&lt;/li&gt;
&lt;li&gt;The embedding code delivers HTML, not JavaScript (Even though it is wrapped in JavaScript to work around the browser limitations.) The fact that we are delivering HTML (instead of JavaScript) has a huge impact on the site startup performance.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Generating HTML first content
&lt;/h2&gt;

&lt;p&gt;So there are many frameworks that can do SSR/SSG and hence generate HTML for the client. But most of them come with hydration costs. So for our example, we have chosen &lt;a href="https://qwik.builder.io/"&gt;Qwik&lt;/a&gt; because it uses &lt;a href="https://www.builder.io/blog/resumability-vs-hydration"&gt;resumability instead of hydration&lt;/a&gt; to make the application interactive. &lt;a href="https://astro.build/"&gt;Astro&lt;/a&gt; would have also been a good choice because it delays the hydration cost until the island is ready. Anything which does not add JavaScript on startup and produces HTML would have been a great choice.&lt;/p&gt;

&lt;p&gt;The nice thing about &lt;a href="https://qwik.builder.io/"&gt;Qwik&lt;/a&gt; is that you get to write your application in a familiar &lt;a href="https://qwik.builder.io/docs/cheat/qwik-react/"&gt;React-like style&lt;/a&gt;, but &lt;a href="https://qwik.builder.io/"&gt;Qwik&lt;/a&gt; automatically generates HTML and delays the loading of JavaScript until it is needed (the same application written with React, as we see in Twitter embedded in the example above, results in a lot of JavaScript on startup).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it performs so much better
&lt;/h2&gt;

&lt;p&gt;Let's examine the performance improvements with the new approach.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o3qfSwbS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F003b2e540ef04d878cd5804189ca4905%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o3qfSwbS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F003b2e540ef04d878cd5804189ca4905%3Fwidth%3D800" alt="a screenshot of a comparison table between regular twitter embed and the new solution qwik embed." width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;WOW! That’s quite a difference! As you can tell from the above, embedding HTML (even if wrapped in JavaScript) has almost no impact on the startup performance of your site! Even adding multiple tweets does not negatively impact the startup's performance. The only minor negative impact is from CLS (Commutative Layout Shift), which is due to serving images without size information, something that should be a straightforward fix.&lt;/p&gt;

&lt;p&gt;The key thing to notice is that all of this is driven by the amount of JavaScript which needs to execute. By reducing the amount of JavaScript, the page became performant. The hard part is not knowing that JavaScript needs to be reduced but knowing how to use existing tools to deliver a minimal amount of JavaScript. This requires a paradigm shift.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it for yourself
&lt;/h2&gt;

&lt;p&gt;If your site uses Twitter Embed and you would like to try this approach, you can do so here: &lt;a href="https://qwik-twitter.builder.io/"&gt;https://qwik-twitter.builder.io/&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find a tweet that you would like to embed&lt;/li&gt;
&lt;li&gt;Paste it into the &lt;code&gt;Tweet URL&lt;/code&gt; and submit.&lt;/li&gt;
&lt;li&gt;Copy the appropriate level of the script to your site.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What the differences are
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;JS only&lt;/code&gt; is by far the smallest amount of code to paste, but it means that the end user will first see a page without a tweet, and a fraction of a second later, the tweet will show up. This has several shortcomings. The small delay will negatively impact the CLS, and the lack of content will prevent the search engine from indexing the tweet content.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HTML + JS&lt;/code&gt; includes HTML in addition to JavaScript. While this tweet will still have a flash of unstyled content, it does have the content, which means the search engine will correctly index it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HTML + JS + CSS&lt;/code&gt; is the best way to inline the content so that there is no flash of unstyled content and the search engine can index it. The JS on end can update the tweet reply, retweets, and favorite stats once it executes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The three people problem
&lt;/h2&gt;

&lt;p&gt;Any system which is not a closed loop will go out of sync. The best systems are such that there is a feedback loop that self-corrects. In the case of a third-party ecosystem, there are three separate people involved and very little feedback between them.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Third-party developer: in our case, the Twitter engineer that created the Twitter embed code.&lt;/li&gt;
&lt;li&gt;First-party developer: this is you creating a site for your users and deciding to embed the third-party code because it provides value.&lt;/li&gt;
&lt;li&gt;End user: the person using the site.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The problem is that the person feeling the slowness is the end user. The person who can do something about it is the third-party developer, but they are not feeling the problem. The first-party developer is aware of the problem but needs the value of the third-party script, so they keep using it as there are few alternatives.&lt;/p&gt;

&lt;p&gt;The above creates very little incentive for the problem to get fixed. Add to it the realization that the third-party developer needs better tools for creating the third-party code in an HTML-first manner, and we have a bit of a stalemate in the industry.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the industry can do to aim higher
&lt;/h2&gt;

&lt;p&gt;So what can we do to improve this?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We need to empathize with the end user and care more about performance as an industry.&lt;/li&gt;
&lt;li&gt;We need examples (like this one) showing that it is possible to do better. This is a mental model shift where we need to understand that it is about leaning more toward HTML and less toward JavaScript.&lt;/li&gt;
&lt;li&gt;We need tooling that allows developers to create HTML-first sites without sacrificing development speed. The easy path needs to be the performant path; otherwise, corners will be cut in the name of deadlines.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Average sites have 23 third-party scripts. We add these scripts because they provide value for our sites, whether as social proof or insights into user behavior. To make the scripts easy to embed, they are usually written as CSR (client-side rendered) applications. CSRs come with high startup cost, which is often hidden from the site developer. Most of these third-party scripts are written as CSR applications, meaning they are JavaScript-heavy and need to execute on startup, negatively impacting our site. Multiply this by 23 scripts per page, and the site has little hope of being fast, let alone “blazingly™ fast”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4d3YvHpD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F27950220bff7422cb8e0aa7c1cd2d492%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4d3YvHpD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F27950220bff7422cb8e0aa7c1cd2d492%3Fwidth%3D800" alt="an image of a man (the primeagen) with a green screen behind him with the caption blazing fast." width="498" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is an alternative way to provide value. Instead of CSR, we need HTML-first third-party scripts that delay JavaScript for as long as possible. Such third-party scripts are possible, but they require different kinds of approaches to the problem. This requires support from tools and educating developers. We need to make sure that the easy way to build a site or third-party scripts is also the performant way to build it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visually build with your components
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.builder.io/m/developers"&gt;Builder.io&lt;/a&gt; is a headless CMS that lets you &lt;a href="https://www.builder.io/m/products"&gt;drag and drop&lt;/a&gt; with &lt;a href="https://www.builder.io/m/developers"&gt;your components&lt;/a&gt; right within your existing site.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://builder.io/signup"&gt;Try it out&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/m/developers"&gt;Learn more&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Dynamically render your components&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BuilderComponent&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;registerComponents&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;MyHero&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyProducts&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>performance</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Challenges of Lazy Loading in JavaScript</title>
      <dc:creator>Miško Hevery</dc:creator>
      <pubDate>Thu, 02 Mar 2023 15:26:52 +0000</pubDate>
      <link>https://dev.to/builderio/the-challenges-of-lazy-loading-in-javascript-7j6</link>
      <guid>https://dev.to/builderio/the-challenges-of-lazy-loading-in-javascript-7j6</guid>
      <description>&lt;p&gt;So your site has too much JavaScript. No problem, say the experts, just lazy load your application! Well, I am here to tell you that lazy-loading is harder than you think!&lt;/p&gt;

&lt;p&gt;Let's start with building a simple app to demonstrate the problem. We will have three components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A component for state&lt;/li&gt;
&lt;li&gt;A component for the interaction&lt;/li&gt;
&lt;li&gt;And a component for displaying user data.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For this simple example, we are about to show you the breakdown is overkill, but we designed the simple application in this way to demonstrate the problem of real-world applications better.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: We use React in these examples because of its concise syntax and popularity. But the issues described here are in no way specific to React. All Hydration based frameworks face these issues. So please don't take this as a negative reflection on React specifically.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;File: &lt;code&gt;main.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyApp&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;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Display&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="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&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;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;OverSize&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Incrementor&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="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&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;Display&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/count&lt;/span&gt;&lt;span class="err"&gt;&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;OverSize&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;too&lt;/span&gt; &lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&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;Incrementor&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyApp&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;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementyById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For brevity, the application is small. But let's imagine that there are many sub-components behind each of our components and those sub-components have a lot of JavaScript. So our application is large and therefore slow to start. We consulted &lt;a href="https://pagespeed.web.dev/"&gt;PageSpeed&lt;/a&gt;, and their primary recommendation was to reduce the amount of JavaScript.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LwchAk_A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F6c350d5b10654afea4f5707587ff2f5e%3Fwidth%3D705" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LwchAk_A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F6c350d5b10654afea4f5707587ff2f5e%3Fwidth%3D705" alt="screenshots from pagespeed insights laid on top of each other." width="705" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lazy loading a component
&lt;/h2&gt;

&lt;p&gt;File: &lt;code&gt;main.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Suspense&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
   &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./display&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;Display&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;Incrementor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
   &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./incrementor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;Incrementor&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;OverSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
   &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./oversize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;OverSize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyApp&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;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Display&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="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;Suspense&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;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;OverSize&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Suspense&amp;gt; : null&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Incrementor&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="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;createRoot&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;getElementyById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;File: &lt;code&gt;display.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Display&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/count&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;File: &lt;code&gt;oversize.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;OverSize&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;too&lt;/span&gt; &lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;File: &lt;code&gt;incrementor.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Incrementor&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is straightforward, even though it is quite wordy. We had to create multiple files and give them names. And as we all know, naming is one of the hardest problems in computer science. And this is where the problems start. Our hard work of breaking up the application into separate files will be undermined by Hydration, coalescing, and prefetching problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hydration
&lt;/h3&gt;

&lt;p&gt;On application, startup Hydration requires that the framework descends into each component to rebuild the component state (&lt;code&gt;useState&lt;/code&gt;) and check to see if the component has any listeners that need to be attached for interactivity. The fact that we descend into each component completely undoes the lazy-loading work we put in. Both &lt;code&gt;Display&lt;/code&gt; and &lt;code&gt;Incrementor&lt;/code&gt; will be fetched eagerly as part of the application startup. Here lazy-loading made the situation arguably worse since the browser will have to make multiple HTTP trips to the server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lGkEU8Q_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F8a26dd513af84f0a96b0b8feb74c8ebb%3Fwidth%3D705" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lGkEU8Q_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F8a26dd513af84f0a96b0b8feb74c8ebb%3Fwidth%3D705" alt="an illustration of multiple http server requests and responses." width="594" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only component where lazy-loading helped is the &lt;code&gt;OverSized&lt;/code&gt; component. This is the only component not needed as part of Hydration, so lazy-loading it made sense. The problem is that as a developer, you don't know which set of components your application will need because that is oftentimes dependent on the application state and may change as the application adds new features. So while in the above example, it is easy to reason about which components will be needed eagerly, in a large-scale application, the problem quickly goes beyond what developers can keep track of and requires some sort of automation, which needs to be custom-built.&lt;/p&gt;

&lt;p&gt;From the above example, it should be apparent that lazy-loading is only useful for components not currently part of the render tree. That is because the components part of the render tree require Hydration to become interactive, and Hydration requires the eager walking of the component tree. So lazy loading is great for route changes (new components not part of the current render tree) but not so much for lowering the amount of JS which is required for Hydration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Merging components
&lt;/h3&gt;

&lt;p&gt;It may very well be that the &lt;code&gt;Display&lt;/code&gt; and Incrementor components need to be loaded together. In that case, they should be placed in the same lazy-loaded chunk. Not all bundlers will know how to merge &lt;code&gt;display.tsx&lt;/code&gt; and &lt;code&gt;incrementor.tsx&lt;/code&gt; into the same file because they are accessed through a separate dynamic import. And even if they know how to merge dynamic imports, it is not immediately clear to the bundler which dynamic imports should be merged and which should not. This is a problem because now the developer needs to make bundling choices about which chunk each symbol should be placed in. Such information may not be apparent at the time of writing the application or may change as the application adds new functionality.&lt;/p&gt;

&lt;p&gt;A corollary to the above is that bundling is not an implementation detail of the application but a configuration detail of the bundler. Our bundler systems are not set up for this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prefetching
&lt;/h3&gt;

&lt;p&gt;We want to ensure that the user has a smooth experience. That means that we don't want to start fetching a JS chunk on user interaction. Instead, the chunk should be prefetched eagerly. But prefetching is outside of the scope of frameworks, as well as bundlers. Prefetching now falls onto the developer's responsibility. This is tricky because the developer now needs to determine all of the potential entry points chunks, in which order they should be prefetched, and when in the application lifecycle is a good time to do the prefetching. For example, is chunk &lt;code&gt;A&lt;/code&gt; needed now or only on route change? How does the developer communicate that information to the pre-fetcher? What mechanisms should be used for prefetching? And many more questions which now fall on the developer's responsibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lazy-loading on interactions
&lt;/h2&gt;

&lt;p&gt;As written, our code can only lazy-load components. Components include event handlers, but because components are often loaded eagerly due to Hydration, we often lazy-load behavior before it is needed. Loading the component behavior eagerly can be seen on PageSpeed as “Reduce unused JavaScript” code coverage (event handlers are downloaded but not executed as part of hydration.). It is the code which downloaded but was not executed as part of Hydration. The not-executed code is mostly event handlers. So let's try to lazy load the event handler.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1TtEQD9b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252Ff161e003dc224518aebc9475c3289edb%3Fwidth%3D705" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1TtEQD9b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252Ff161e003dc224518aebc9475c3289edb%3Fwidth%3D705" alt='a screenshot from a PageSpeed report showing the "reduce unused javascript" section.' width="705" height="755"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We start by breaking up the &lt;code&gt;incrementor.tsx&lt;/code&gt; into even smaller files by pulling out the event handler like so:&lt;/p&gt;

&lt;p&gt;File: &lt;code&gt;incrementor.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Incrementor&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./incrementor-on-click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;File: &lt;code&gt;incrementor-on-click.tsx&lt;/code&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;incrementorOnClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But here we run into more issues regarding hydration trampoline closure; async nature of lazy-loading; prefetching; its a lot of work; (And we have not even gotten into the issue of flowing types across lazy loading boundaries)&lt;/p&gt;

&lt;h3&gt;
  
  
  Hydration trampoline closure
&lt;/h3&gt;

&lt;p&gt;The issue is that when Hydration collects all of the listeners, it expects a closure to invoke when the listener fires on user interaction. In our example, the listener-closure closes over &lt;code&gt;setCount&lt;/code&gt; and &lt;code&gt;count&lt;/code&gt;, and that code for creating the closure needs to be executed eagerly, as shown here for the &lt;code&gt;onClick&lt;/code&gt; case.&lt;/p&gt;

&lt;p&gt;File: &lt;code&gt;incrementor.tsx&lt;/code&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Incrementor&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./incrementor-on-click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another way to look at it is from the handler file.&lt;/p&gt;

&lt;p&gt;File: &lt;code&gt;incrementor-on-click.tsx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The above function needs to get a hold of &lt;code&gt;setCount&lt;/code&gt; and &lt;code&gt;count&lt;/code&gt; to perform its job. Without &lt;code&gt;setCount&lt;/code&gt; and count the &lt;code&gt;IncrementorOnClick&lt;/code&gt; can't do anything useful. So how does it get a hold of it? Well, it expects that data to be passed in when it is invoked.&lt;/p&gt;

&lt;p&gt;This is the reason why the &lt;code&gt;&amp;lt;button onClick={...}/&amp;gt;&lt;/code&gt; has an eager closure that captures the &lt;code&gt;setCount&lt;/code&gt; and &lt;code&gt;count&lt;/code&gt; on Hydration and then makes it available to the lazy-loaded function on invocation.&lt;/p&gt;

&lt;p&gt;Another way to think about it is that lazy-loading listeners do not help with startup performance, as we still need to allocate the event handlers (It may help with the amount of JS we download, but not in this case, as the ceremony of lazy loading contains more code than the actual lazy-loaded chunk.).&lt;/p&gt;

&lt;h3&gt;
  
  
  Async nature of lazy-loading
&lt;/h3&gt;

&lt;p&gt;Lazy-loading is asynchronous by its nature. The issue is that the event handler oftentimes has to synchronously call &lt;code&gt;preventDefault&lt;/code&gt; or call other APIs which are only available synchronously. This complicates the writing of code as the developer now needs to take that into account. It may not be possible to just refactor the code for lazy-loading and assume it will work, as doing so introduces lazy-loading boundaries, which may break the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prefetching
&lt;/h3&gt;

&lt;p&gt;Again prefetching is an issue with lazy-loading on interactivity, and all of the issues we discussed above apply here as well. But in the case of interactivity, prefetching is a lot more important because while Hydration causes eager loading of components, interactivity will not eagerly load until the user interacts, and by that point, it may be too late (user will experience slow network delay on the first interaction.) So prefetching of interactivity code is a must!&lt;/p&gt;

&lt;h3&gt;
  
  
  It is a lot of work
&lt;/h3&gt;

&lt;p&gt;The amount of work to create lazy interactions is astounding!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;create a new file&lt;/li&gt;
&lt;li&gt;insert dynamic import()&lt;/li&gt;
&lt;li&gt;ensure that the code is prefetched&lt;/li&gt;
&lt;li&gt;repeat for each component/function&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most of the time, the developer will not do all of this extra work for a relatively small win. The issue with event handlers is not that any one event handler adds a lot of code. It is that applications usually have a lot of event handlers, and so it adds up. It’s like &lt;strong&gt;death by a thousand cuts.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Application startup performance is tied to the amount of JS that the browser needs to download and execute. Lazy-loading code is often suggested as the solution to improve startup performance. While this may sound straightforward at first, it is much harder than you think.&lt;/p&gt;

&lt;p&gt;Lazy-loading adds extra ceremonies to your code and workflow. It requires the developer to think about how the application should be broken up. It creates new problems around prefetching of code, which is not solved out of the box and requires more engineering.&lt;/p&gt;

&lt;p&gt;And finally, a lot of benefits of lazy-loading is destroyed by the eager nature of Hydration, and so most benefits of lazy-loading can only be achieved with components that are not currently in the render tree (components that need to be loaded on route-change.) It’s easy to say that lazy loading will solve your performance problems, but the actual engineering part of the developer is a lot more than it may seem. For this reason, it rarely gets done. When an application grows too large and lazy-loading becomes necessary, the refactoring process may be extremely difficult.&lt;/p&gt;

&lt;h2&gt;
  
  
  About Qwik
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://qwik.builder.io/"&gt;Qwik&lt;/a&gt; is a framework that eliminates the need for developers to manually handle lazy-loading, bundling, and prefetching. It functions seamlessly out of the box. Furthermore, Qwik does not undo the advantages of Hydration for components in the render tree, as it does not perform Hydration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dFNarYu5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F83677fb912dd4a539a3f3bb5c0c82de1%3Fwidth%3D405" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dFNarYu5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F83677fb912dd4a539a3f3bb5c0c82de1%3Fwidth%3D405" alt="" width="405" height="143"&gt;&lt;/a&gt;&lt;/p&gt;


  


&lt;h2&gt;
  
  
  Visually build with your components
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.builder.io/m/developers"&gt;Builder.io&lt;/a&gt; is a headless CMS that lets you &lt;a href="https://www.builder.io/m/products"&gt;drag and drop&lt;/a&gt; with &lt;a href="https://www.builder.io/m/developers"&gt;your components&lt;/a&gt; right within your existing site.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://builder.io/signup"&gt;Try it out&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/m/developers"&gt;Learn more&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Dynamically render your components&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BuilderComponent&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;registerComponents&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;MyHero&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyProducts&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>programming</category>
    </item>
    <item>
      <title>Our current frameworks are O(n); we need O(1)</title>
      <dc:creator>Miško Hevery</dc:creator>
      <pubDate>Wed, 18 May 2022 18:56:56 +0000</pubDate>
      <link>https://dev.to/builderio/our-current-frameworks-are-on-we-need-o1-4545</link>
      <guid>https://dev.to/builderio/our-current-frameworks-are-on-we-need-o1-4545</guid>
      <description>&lt;div class="ltag__user ltag__user__id__647890"&gt;
    &lt;a href="/mhevery" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F647890%2Fa89c8fc1-ceb2-46d2-b354-9ad0d91d7654.jpeg" alt="mhevery image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/mhevery"&gt;Miško Hevery&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/mhevery"&gt;CTO at Builder.io, empower anyone to create blazing fast sites. Previously at Google, where he created Angular, AngularJS and was co-creator of Karma.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Original: &lt;a href="https://www.builder.io/blog/our-current-frameworks-are-on-we-need-o1" rel="noopener noreferrer"&gt;https://www.builder.io/blog/our-current-frameworks-are-on-we-need-o1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today, websites are more interactive and useful than ever, which also means they’re more complex than ever. Users have come to expect the new interactivity and usefulness, and they’re not going to want to give it up. All of this means more JavaScript is being sent to the browser on page load than ever, which isn’t likely to slow down anytime soon. We can expect that sites will continue to keep getting better and more complex, but what should we do about JavaScript?&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How did we get here?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;It’s well understood that the amount of JavaScript being sent to browsers is steadily increasing, as shown in this graph from &lt;a href="https://httparchive.org/reports/page-weight?start=earliest&amp;amp;end=latest&amp;amp;view=list" rel="noopener noreferrer"&gt;httparchive.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F70e125f16c4c48f985f91ca13c9da790%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F70e125f16c4c48f985f91ca13c9da790%3Fwidth%3D800" alt="Graph Showing the increase of JavaScript over time"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some people like to argue that the site we served ten years ago and the one we serve today are the same. But it’s not a fair comparison. The sites of today are way more complex. &lt;/p&gt;

&lt;p&gt;And while some of the complexity comes from better interactions and functionality for the end-users, a lot of it comes from helping us gain insight into our users' behavior, which helps us build even better sites. Our sites ultimately get bigger because they do more stuff not only for our end-users, but for us as well. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;CPUs have stalled.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Every year, the CPUs are getting faster, but most of the speedup comes from improved parallelism. And in recent years the performance improvements per core have been slowing down. We’re approaching the limits of how fast CPU clocks can run and how much cleverness the CPUs can do per clock cycle. As a result, we see more multi-core CPUs pop up (It is not uncommon for your phone to have 4 CPU cores and 4 GPU cores). So the main driver of CPU performance improvement these days comes from parallelism of multiple cores, not from improvements in a single core.&lt;/p&gt;

&lt;p&gt;So, why are we talking about CPU speed and cores? As our sites get bigger and download more JavaScript, the CPU has more work to do. And because JavaScript is single-threaded, all of the additional work falls onto a single core. Therefore, this is not a problem that will get better by waiting a few years and expecting the hardware to catch up.&lt;/p&gt;

&lt;p&gt;Ultimately, our current JS load is increasing faster than the rate of single CPU core performance. This is not sustainable.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Frameworks were not designed for this.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Frameworks for desktop applications have existed way before the web. So when the web came, we just took our desktop framework philosophy of what the framework is and applied it to the web. Desktop frameworks can safely assume that all of the code is already available &lt;em&gt;and&lt;/em&gt; that there is no server. The problem is that those two key points are not true for the web. We can't assume that the code is already available, and server pre-rendering has become an important part of our vocabulary. &lt;/p&gt;

&lt;p&gt;We’re at a stage where the frameworks we have are pretending they’re desktop frameworks. They have not embraced SSR and lazy-loading to the core.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;y=mx+b&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;An application needs to boot up on the client. The bootup consists of a fixed cost of the framework and a variable cost of the application itself (the complexity of the application). So really, we are talking about a linear relationship which can be expressed as “y=mx+b”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F701cce5c7a5f402784b83832c4037071%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F701cce5c7a5f402784b83832c4037071%3Fwidth%3D800" alt="Arrows pointing at each variable in the expression describing what they mean y is bundle, m is marginal size, x is content, b is constant size "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When frameworks argue who is smaller, they can really only compete on two points: the fixed cost of the framework &lt;em&gt;or&lt;/em&gt; the variable cost of the application. So either a smaller “m” or a smaller “b”.&lt;/p&gt;

&lt;p&gt;Ryan Carniato did a nice comparison of different frameworks in his post &lt;a href="https://dev.to/this-is-learning/javascript-framework-todomvc-size-comparison-504f"&gt;JavaScript Framework TodoMVC Size Comparison&lt;/a&gt; (table replicated below).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252Fd4a681e718ba4656afb8f3f75ca9a738%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252Fd4a681e718ba4656afb8f3f75ca9a738%3Fwidth%3D800" alt="A two dimensional chart showing frontend frameworks svelte, solid, preact, vue, react increasing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the sake of my argument, the exact numbers aren’t important, but the table does a good job of illustrating how, as the application size increases, different frameworks have different slopes (“m”) and different initial values (“b”).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F77a7b3543c324498a4eec9b9c931bf8d%3Fwidth%3D536" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F77a7b3543c324498a4eec9b9c931bf8d%3Fwidth%3D536" alt="Graph showing JS size compared to complexity"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Even the smallest “m” is not enough.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The problem is that all frameworks have approximately the same slope. And even if the framework completely compiles away so its “b” becomes zero, the application dominates the download and execution size. The “b” kind of doesn’t matter for sufficiently large applications. &lt;/p&gt;

&lt;p&gt;All of the above lines are “O(n)”. As the application gets bigger, so does the initial bundle size. Applications will continue to get bigger as we continue to build better end-user experiences. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;New goal “O(1)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F8c3a4a6c0ed14e109971f2b55db67eb8%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F8c3a4a6c0ed14e109971f2b55db67eb8%3Fwidth%3D800" alt="2 dimensional graph showing content size on x and initial bundle on y axis. Classical Framework is increasing rapidly Qwik stays flat"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What we need is a new paradigm. We need a framework with a constant load time no matter the application complexity. At first glance, this may sound impossible—surely, the initial bundle is proportional to the application complexity. But what if we lazyload code rather than doing it eagerly? I covered why existing frameworks need to eagerly download code in my post, &lt;a href="https://www.builder.io/blog/hydration-is-pure-overhead" rel="noopener noreferrer"&gt;Hydration is pure overhead&lt;/a&gt;. Here’s what we’re looking for instead:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F38799b4588354a0da0785fb290c989ca%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F38799b4588354a0da0785fb290c989ca%3Fwidth%3D800" alt="2 dimensional graph showing downloaded JS to time of interaction. Old framework start high and stays high. Qwik incrementally increases on interaction."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The current status quo is to download and execute all of the code at once. What’s needed is a way to sip on the JavaScript as the user is interacting with the site. No interaction, no JavaScript; little interaction, little JavaScript. If there’s a lot of interaction, we approach the classical frameworks and download most of the code. But the big deal is that we need to shift our mental model from eagerly downloading code at the beginning to lazily downloading code as the user interacts.&lt;/p&gt;

&lt;p&gt;Current frameworks already know how to do this to some extent, as they all know how to download more code on route change. What’s needed is to extend that paradigm to the interaction level.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F33b3328a4ce94893a4faf8f8539e72b6%3Fwidth%3D640" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F33b3328a4ce94893a4faf8f8539e72b6%3Fwidth%3D640" alt="Image showing regions of page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above image the site is delivered as HTML to the client. Notice that none of the components have the coresponded code loaded. The next image shows which components need to be downloaded and executed on user interectaion. The result is that a lot less code needs to be downloaded and the code which is downloaded is executed later. This offloads the amount of work the CPU has to do on site startup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F15714d60e0c34bdd84fb47c5139c2c95%3Fwidth%3D640" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F15714d60e0c34bdd84fb47c5139c2c95%3Fwidth%3D640" alt="Image highlighting interactive page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Summary&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The amount of JavaScript we download to the browser is going up every year. The problem is that our site's complexity increases as we deliver more complex end-user experiences that require more code. We have already reached a point where we have too much code in the initial download, and our site’s startup performance suffers. This is because the frameworks we use are O(n). This is not scalable. &lt;/p&gt;

&lt;p&gt;While different frameworks have different slopes in the end, any slope is too much. Instead, we need to lazy load on interaction rather than on initial load. Frameworks already know how to lazy load on route change, we just need to go deeper and do it on interaction as well. This is needed so that our initial load size can be O(1) and we can lazy load code on as needed basis. It’s the only way we can continue to build even more complex web applications in the future.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Don't blame the developer for what the frameworks did!</title>
      <dc:creator>Miško Hevery</dc:creator>
      <pubDate>Wed, 04 May 2022 17:59:17 +0000</pubDate>
      <link>https://dev.to/builderio/dont-blame-the-developer-for-what-the-frameworks-did-402g</link>
      <guid>https://dev.to/builderio/dont-blame-the-developer-for-what-the-frameworks-did-402g</guid>
      <description>&lt;div class="ltag__user ltag__user__id__647890"&gt;
    &lt;a href="/mhevery" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BHu9Ddb6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--IO_W7RTM--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/647890/a89c8fc1-ceb2-46d2-b354-9ad0d91d7654.jpeg" alt="mhevery image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/mhevery"&gt;Miško Hevery&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/mhevery"&gt;CTO at Builder.io, empower anyone to create blazing fast sites. Previously at Google, where he created Angular, AngularJS and was co-creator of Karma.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Original: &lt;a href="https://www.builder.io/blog/dont-blame-the-developer-for-what-the-frameworks-did"&gt;https://www.builder.io/blog/dont-blame-the-developer-for-what-the-frameworks-did&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's talk about the tools we have to build web apps and how those tools deceive us.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common story
&lt;/h2&gt;

&lt;p&gt;You’re starting a new greenfield project, and this time, you’ll make sure that the site will be fast and slick! The starting line looks good, but soon your application gets big, and the startup performance starts to suffer. Before you know it, you have a huge app on your hands, and you are feeling powerless to fix it. Where did you go wrong?&lt;/p&gt;

&lt;p&gt;Every tool/framework promises a better, faster result, yet we have the whole internet to tell us that the result is anything but a better, faster web. And who else is there to blame for this but the developers?&lt;/p&gt;

&lt;p&gt;They messed up, cut corners, etc., which is why they ended up with a slow site. Or so we’re told. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/wesbos/status/1297896603286724610"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gTxZEt1E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F50426d91c19246b09d7dfbbc78e4e001%3Fformat%3Dwebp%26width%3D800" alt="Wes Bos Tweet on simple page lighthouse score" width="764" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  It's not your fault
&lt;/h2&gt;

&lt;p&gt;If a few sites are slower, then sure, blaming the developer may make sense. “Look, the other sites are fast; clearly, the rest of the world knows how to do it right.” Something like that. Except that is not the world we live in. All sites are slow! How can you blame the developer when no one is succeeding? The problem is systemic. Perhaps it’s not the developer's fault.&lt;/p&gt;

&lt;p&gt;This is a story of how we build apps, the tools we use, the promises the tools make, and the world of slowness we end up with. There’s only one conclusion. The tools have over promised, and this is a systemic problem in the industry. It’s not just a few bad apples, but the whole world wide web.&lt;/p&gt;

&lt;h2&gt;
  
  
  Too much code
&lt;/h2&gt;

&lt;p&gt;We all know what the problem is: too much code! We got so good at creating code that browsers can't keep up with us. No matter where you look, everyone tells you your site has too much JavaScript, yet no one knows how to shrink it down.&lt;/p&gt;

&lt;p&gt;It's like a YouTube fitness channel telling you that all you need to do to lose weight is eat fewer calories. Easy advice, and yet the success rate is dismal. The reason is that the advice ignores appetite hormones. How can you keep your will to eat fewer calories when you are hungry, weak and all you can think about is food? The situation is stacked against you. The secret to losing weight may not be cutting calories after all, but controlling your appetite. But when was the last time you heard anyone talk about appetite control?&lt;/p&gt;

&lt;p&gt;That’s what it’s like with JavaScript bloat. We know we need less JavaScript, but all of the tools just keep bundling more and more code into your app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UMJE7Px0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F9242129372f0469aaa74b4289c762d97%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UMJE7Px0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F9242129372f0469aaa74b4289c762d97%3Fformat%3Dwebp%26width%3D2000" alt="Graph showing codebase size increase, while performance decreases over time" width="880" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Evolution of bundling
&lt;/h2&gt;

&lt;p&gt;Let's take a look at how we got into this situation first, and then let's discuss a path forward.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gen 0: Concatenation
&lt;/h3&gt;

&lt;p&gt;Before ECMAScript modules, there was nothing. Just files. Bundling was simple. The files were concatenated together and wrapped in IIF. It was as simple as we could get. &lt;/p&gt;

&lt;p&gt;The upside was that it was hard to add more code to your application, so the bundles stayed small. Code reuse just was not a thing with this model. Everyone concatenated code slightly differently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gen 1: Bundlers
&lt;/h3&gt;

&lt;p&gt;Enter ECMAScript modules, a proper syntax for importing and exporting your code. This was awesome, but delivering thousands of files to the browser was a problem. And so, a whole cottage industry of bundlers arose: WebPack, Rollup, CommonJS, etc.&lt;/p&gt;

&lt;p&gt;Now, code reuse has become possible. However, it was a bit too easy to npm install a dependency and bundle it in. Quickly size became a problem.&lt;/p&gt;

&lt;p&gt;To their credit, the bundlers know how to do tree-shaking and dead code elimination. These features make sure that only reachable code gets bundled.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gen 2: Lazy loading
&lt;/h3&gt;

&lt;p&gt;Recognizing the issue of large bundles, the bundlers started to offer lazy loading. Lazy loading is great as it allows code to be broken up into chunks and delivered to the browser on an as-needed basis. This is great because it allows the application to be delivered in parts, starting with the most needed part. It also allows the paralyzation of download, parsing, and execution. &lt;/p&gt;

&lt;p&gt;The problem is that in practice, we build apps using frameworks, and the frameworks have a lot of influence on how bundlers break up our code into lazy loaded chunks. The trouble is that lazy loading a chunk introduces an asynchronous API call—a PROMISE. And if the framework expects a synchronous reference to your code, the bundler can’t introduce a lazy loaded chunk.  &lt;/p&gt;

&lt;p&gt;We are in a bit of a fallacy. Bundlers truthfully claim that they can lazy load code, but unless the framework can accommodate a PROMISE as a developer, you may not have much of a choice. &lt;/p&gt;

&lt;h3&gt;
  
  
  Gen 3: Lazy loading components not in the render tree
&lt;/h3&gt;

&lt;p&gt;Frameworks quickly scrambled to take advantage of the lazy loading capability of the bundlers, and today almost all know how to do lazy loading. But there is a BIG caveat! Frameworks can only lazy load components that are not in the current render tree. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zQL507AM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F77bf2501bfa64d1ebd0028deabe0fd82%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zQL507AM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F77bf2501bfa64d1ebd0028deabe0fd82%3Fformat%3Dwebp%26width%3D2000" alt="Component Diagram showing how the effects of top components dictate other components shaded in green" width="513" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is the render tree? It’s a set of components that make up the current page. An application usually has many more components than are on the current page. A portion of the render tree is the view. It’s what you currently see in the browser viewport. But a render tree encompasses the whole DOM, even the components outside of the current view.&lt;/p&gt;

&lt;p&gt;Suppose a component is in the render tree. In that case, the framework must download the component because the framework needs to rebuild the render tree of components as part of &lt;a href="https://www.builder.io/blog/why-progressive-hydration-is-harder-than-you-think"&gt;&lt;strong&gt;Hydration&lt;/strong&gt;&lt;/a&gt; or update. Frameworks can only lazy load components that are currently NOT in the render tree. &lt;/p&gt;

&lt;p&gt;Another point is that the frameworks can lazy load components but that always includes behavior. The component unit is too large because it encompasses the behavior. It would be better if the lazy loading unit were smaller. Rendering a component should not require the download of the component's event handlers. The framework should only download the event handlers on user interaction and not as part of the component render method. Depending on the kind of application you are building, the event handlers may represent the bulk of your code. So coupling the download of component's render and behavior is suboptimal.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core of the problem
&lt;/h2&gt;

&lt;p&gt;It would be great to lazy load the component render function only when the component needs to be rerendered and lazy load the event handlers only if the user is interacting with them. The default should be that everything is lazy loaded.&lt;/p&gt;

&lt;p&gt;But there is a big problem with that approach. The issue is that the frameworks need to reconcile their internal state with the DOM. And that means that at least once on application &lt;a href="https://www.builder.io/blog/why-progressive-hydration-is-harder-than-you-think"&gt;&lt;strong&gt;Hydration&lt;/strong&gt;&lt;/a&gt;, they need to be able to do a full render to rebuild the framework's internal state. After the first render, the frameworks can be more surgical about their updates, but the damage has been done, the code has been downloaded. So we have two issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Frameworks need to download and execute components to rebuild the render tree on startup. (See &lt;a href="https://www.builder.io/blog/why-progressive-hydration-is-harder-than-you-think"&gt;&lt;strong&gt;Hydration&lt;/strong&gt;&lt;/a&gt;) This forces eager download and execution of all components in the render tree.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The event handlers come with the components even though they are not needed at the time of rendering. The inclusion of event handlers forces the download of unnecessary code. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So the status quo of frameworks today is that every component (and their handlers) in the SSR/SSG render tree must be eagerly downloaded and executed. Lazy loading with today's frameworks is a bit of a lie because you can't do lazy loading on the initial page render. &lt;/p&gt;

&lt;p&gt;It’s worth pointing out that even if a developer introduces lazy loaded boundaries into the SSR/SSG initial page, it does not help. The framework will still have to download and execute all of the components in the SSR/SSG response; therefore, as long as the component is in the render tree, the framework will have to eagerly load the components that the developer tried to lazy load. &lt;/p&gt;

&lt;p&gt;The eager download of the components in the render tree is the core of the problem, and there is nothing the developer can do about it. Still, that doesn’t stop the developer from getting blamed for how slow the site is. Fun!&lt;/p&gt;

&lt;h2&gt;
  
  
  Next-Gen: Fine-grained lazy loading
&lt;/h2&gt;

&lt;p&gt;So, where do we go from here? The obvious answer is that we need to go more fine-grained. The solution is both obvious and difficult to implement. We would need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Change the frameworks so they don't eagerly load the render tree on hydration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allow the component render function to be loaded independently from the component event handlers.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your framework can do the two parts above, the user would see huge benefits. The application would have lite startup requirements because no rendering would need to happen on startup (the content is already rendered at SSR/SSG). Less code is downloaded. And when the framework determines that a particular component needs to be rerendered, the framework can do so by downloading the render function without downloading all of the event handlers.&lt;/p&gt;

&lt;p&gt;Fine-grained lazy loading would be a huge win for site startup performance. It’s much faster because the amount of code downloaded would be proportional to the user interactivity instead of being proportional to the initial render tree complexity. Your sites would become faster, not because we got better at making the code small, but we got better at only downloading what we need rather than downloading everything up front. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8zWHoCrF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F3bc32a492a1d489191aff2ecc9f09dcb%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8zWHoCrF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.builder.io/api/v1/image/assets%252FYJIGb4i01jvw0SRdL5Bt%252F3bc32a492a1d489191aff2ecc9f09dcb%3Fformat%3Dwebp%26width%3D2000" alt="Graph with arrow for performance flat, and arrow for codebase size increase over time" width="880" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Entry points
&lt;/h2&gt;

&lt;p&gt;It’s not enough to have a framework that can do fine-grained lazy loading. Because, to take advantage of fine-grained lazy loading, you must first have bundles to lazy load. &lt;/p&gt;

&lt;p&gt;For bundlers to create lazy loadable chunks, bundlers need an entry point for each chunk. If all you have is a single entry point to your application, bundlers can't create chunks. And if that’s true, even if your framework could do fine-grained lazy loading, it would have nothing to lazy load.&lt;/p&gt;

&lt;p&gt;Creating entry points is cumbersome today because it requires that the developer writes extra code. When developing the application, we can really only think about one thing, which is the feature. It’s simply unfair to developers to make them think about the feature they’re building and lazy loading at the same time. So in practice, creating entry points for bundlers is not a thing. &lt;/p&gt;

&lt;p&gt;What’s needed is a framework that creates the entry points without the developer thinking about it. Creating entry points for the bundlers is a framework’s responsibility, NOT the developer’s responsibility. The developer's responsibility is to build features. The framework's responsibility is to think about the low-level implications of how the feature should be accomplished. If the framework doesn’t do that, then it’s not fully serving the developer's needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overproduction of entry points
&lt;/h2&gt;

&lt;p&gt;The goal should be to create as many entry points as possible. But, some might ask, wouldn’t that cause the download of lots of small chunks rather than a few big ones? The answer is a resounding “no”.&lt;/p&gt;

&lt;p&gt;Without an entry point, a bundler can’t create a new chunk. But nothing stops the bundler from putting several entry points into a single chunk. The more entry points you have, the more freedom you have to assemble the bundles in the most optimal way. The entry points give you the freedom to optimize your bundles. The more of them, the better.&lt;/p&gt;

&lt;h2&gt;
  
  
  The framework of the future
&lt;/h2&gt;

&lt;p&gt;The next-gen frameworks will need to solve these problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Have a DX that people love (existing frameworks are there today).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do fine-grain lazy loading of code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automatically generate lots of entry points to support the fine-grained lazy loading.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The developers will build their sites, just as they do today, but the sites will not overwhelm the browser with huge bundles and execution on application startup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://qwik.builder.io/guide/overview"&gt;&lt;strong&gt;Qwik&lt;/strong&gt;&lt;/a&gt; is a framework that is designed with these principles in mind. Qwik fine-grained lazy loading is per event handler, render function and effect.&lt;/p&gt;

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

&lt;p&gt;Our sites are getting bigger, with no end in sight. They are big because the sites do more today than before—more functionality, animation, etc. We can assume that the trend will continue.&lt;/p&gt;

&lt;p&gt;The solution to the above problem is to do fine-grained lazy loading of code so that the browser doesn’t get overwhelmed on the initial page load.&lt;/p&gt;

&lt;p&gt;Our bundling tools support fine-grained lazy loading, but our frameworks don’t. Framework hydration forces all components in the render tree to be loaded on hydration. (The only kind of lazy loading framework support today is for components that are currently not in the render tree.) Frameworks also download event handlers with the component even though event handlers can be the bulk of the code and will not be needed for initial hydration.&lt;/p&gt;

&lt;p&gt;Because bundlers can fine-grain lazyload, but our frameworks don’t, we fail to recognize the subtlety in this. The result is that we blame the slow site startup on developers because we mistakenly believe that they could have done something to prevent the situation, even though the reality is that they had very little say in this matter. &lt;/p&gt;

&lt;p&gt;We need new kinds of frameworks that are designed with fine-grained lazy loading as a core feature of the frameworks (such as &lt;a href="https://qwik.builder.io/guide/overview"&gt;&lt;strong&gt;Qwik&lt;/strong&gt;&lt;/a&gt;). We can't expect the developers to take on this responsibility; they’re already overwhelmed with features. The frameworks need to think about both lazy loading runtimes as well as creating the entry points so that the bundlers can create the chunks to lazy load. The benefits of the next-gen frameworks would outweigh the cost of switching to them.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Hydration is Pure Overhead</title>
      <dc:creator>Miško Hevery</dc:creator>
      <pubDate>Wed, 20 Apr 2022 22:51:30 +0000</pubDate>
      <link>https://dev.to/builderio/hydration-is-pure-overhead-33g7</link>
      <guid>https://dev.to/builderio/hydration-is-pure-overhead-33g7</guid>
      <description>&lt;div class="ltag__user ltag__user__id__647890"&gt;
    &lt;a href="/mhevery" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F647890%2Fa89c8fc1-ceb2-46d2-b354-9ad0d91d7654.jpeg" alt="mhevery image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/mhevery"&gt;Miško Hevery&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/mhevery"&gt;CTO at Builder.io, empower anyone to create blazing fast sites. Previously at Google, where he created Angular, AngularJS and was co-creator of Karma.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Original: &lt;a href="https://www.builder.io/blog/hydration-is-pure-overhead" rel="noopener noreferrer"&gt;https://www.builder.io/blog/hydration-is-pure-overhead&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.builder.io/blog/why-progressive-hydration-is-harder-than-you-think" rel="noopener noreferrer"&gt;&lt;strong&gt;Hydration&lt;/strong&gt;&lt;/a&gt; is a solution to add interactivity to server-rendered HTML. This is how Wikipedia defines hydration:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In web development, hydration or rehydration is a technique in which client-side JavaScript converts a static HTML web page, delivered either through static hosting or server-side rendering, into a dynamic web page by attaching event handlers to the HTML elements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The above definition talks about hydration in terms of attaching event handlers to the static HTML. However, attaching event handlers to the DOM is not the challenging or expensive part of the hydration, and so it misses the point of why anyone would call hydration an overhead. For this article, overhead is work that can be avoided and still leads to the same end result. If it can be removed and the result is the same, it is an overhead.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/mhevery/status/1514087689246568448" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F4f48568655904e4586ba34b413beb790%3Fwidth%3D800" alt="Misko Hevery tweet on how Hydration is a horrible workaround"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Digging deeper into hydration&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The hard part of hydration is knowing &lt;code&gt;WHAT&lt;/code&gt; event handlers we need and &lt;code&gt;WHERE&lt;/code&gt; they need to be attached.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;WHAT&lt;/code&gt;: The event handler is a closure that contains the behavior of the event handler. It is what should happen if a user triggers this event.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;WHERE&lt;/code&gt;: The location of the DOM element where the &lt;code&gt;WHAT&lt;/code&gt; needs to be attached to (includes the event type.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The added complication is that &lt;code&gt;WHAT&lt;/code&gt; is a closure that closes over &lt;code&gt;APP_STATE&lt;/code&gt; and &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;APP_STATE&lt;/code&gt;: the state of the application. &lt;code&gt;APP_STATE&lt;/code&gt; is what most people think of as the state. Without &lt;code&gt;APP_STATE&lt;/code&gt;, your application has nothing dynamic to show to the user.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt;: the internal state of the framework. Without &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt;, the framework does not know which DOM nodes to update or when the framework should update them. Examples are component-tree, and references to render functions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So how do we recover &lt;code&gt;WHAT&lt;/code&gt; (&lt;code&gt;APP_STATE&lt;/code&gt; + &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt;) and &lt;code&gt;WHERE&lt;/code&gt;? By downloading and executing the components currently in the HTML. The download and execution of rendered components in HTML is the expensive part.&lt;/p&gt;

&lt;p&gt;In other words, hydration is a hack to recover the &lt;code&gt;APP_STATE&lt;/code&gt; and &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt; by eagerly executing the app code in the browser and involves:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; downloading component code&lt;/li&gt;
&lt;li&gt; executing component code&lt;/li&gt;
&lt;li&gt; recovering the &lt;code&gt;WHAT&lt;/code&gt;(&lt;code&gt;APP_STATE&lt;/code&gt; and &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt;) and &lt;code&gt;WHERE&lt;/code&gt; to get event handler closure&lt;/li&gt;
&lt;li&gt; attaching &lt;code&gt;WHAT&lt;/code&gt; (the event handler closure) to &lt;code&gt;WHERE&lt;/code&gt; (a DOM element)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F0e1bbc52c75747328b846dcfa76c28f2" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F0e1bbc52c75747328b846dcfa76c28f2" alt="Image depicting how getting html, downloading ajj js, parsing &amp;amp; executing JS, and recover state &amp;amp; bind listeners"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's call the first three steps the &lt;code&gt;RECOVERY&lt;/code&gt; phase. &lt;code&gt;RECOVERY&lt;/code&gt; is when the framework is trying to rebuild the application. The rebuild is expensive because it requires downloading and executing the application code. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;RECOVERY&lt;/code&gt; is directly proportional to the complexity of the page being hydrated and can easily take 10 seconds on a mobile device. Since &lt;code&gt;RECOVERY&lt;/code&gt; is the expensive part, most applications have a sub-optimal startup performance, especially on mobile.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RECOVERY&lt;/code&gt; is also pure overhead. Overhead is work done that does not directly provide value. In the context of hydration, &lt;code&gt;RECOVERY&lt;/code&gt; is overhead because it rebuilds information that the server already gathered as part of SSR/SSG. Instead of sending the information to the client, the information was discarded. As a result, the client must perform expensive &lt;code&gt;RECOVERY&lt;/code&gt; to rebuild what the server already had. If only the server had serialized the information and sent it to the client along with HTML, the &lt;code&gt;RECOVERY&lt;/code&gt; could have been avoided. The serialized information would save the client from eagerly downloading and executing all of the components in the HTML. &lt;/p&gt;

&lt;p&gt;The re-execution of code on the client that the server already executed as part of SSR/SSG is what makes hydration pure overhead: that is, a duplication of work by the client that the server already did. The framework could have avoided the cost by transferring information from the server to the client, but instead, it threw the information away.&lt;/p&gt;

&lt;p&gt;In summary, hydration is recovering event handlers by downloading and re-executing all components in the SSR/SSG-rendered HTML. The site is sent to the client twice, once as HTML, and again as JavaScript. Additionally, the framework must eagerly execute the JavaScript to recover &lt;code&gt;WHAT&lt;/code&gt;, &lt;code&gt;WHERE&lt;/code&gt;, &lt;code&gt;APP_STATE&lt;/code&gt;, and &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt;. All this work just to retrieve something the server already had but discarded!!&lt;/p&gt;

&lt;p&gt;To appreciate why hydration forces duplication of work on the client, let's look at an example with a few simple components. &lt;/p&gt;

&lt;p&gt;We'll use a popular syntax understood by many people, but keep in mind that this is a general problem not specific to any one framework.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Greeter&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;

    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Greeter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&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="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Greet
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStore&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="k"&gt;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;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;store&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="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&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;button&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;The above will result in this HTML after the SSR/SSG:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Greet&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;10&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The HTML carries no indication of where event handlers or component boundaries are. The resulting HTML does not contain &lt;code&gt;WHAT&lt;/code&gt;(&lt;code&gt;APP_STATE&lt;/code&gt;, &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt;) or &lt;code&gt;WHERE&lt;/code&gt;. The information existed when the server generated the HTML, but the server did not serialize it. The only thing the client can do to make the application interactive is to recover the information by downloading and executing the code. We do this to recover the event handler closures that close over the state. &lt;/p&gt;

&lt;p&gt;The point here is that the code must be downloaded and executed before any event handler can be attached and events processed. The code execution instantiates the components and recreates the state (&lt;code&gt;WHAT&lt;/code&gt;(&lt;code&gt;APP_STATE&lt;/code&gt;, &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt;) and &lt;code&gt;WHERE&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Once hydration completes, the application can run. Clicking on the buttons will update the UI as expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resumability: a no-overhead alternative to hydration
&lt;/h2&gt;

&lt;p&gt;So how do you design a system without hydration and therefore, without the overhead? &lt;/p&gt;

&lt;p&gt;To remove overhead, the framework must not only avoid &lt;code&gt;RECOVERY&lt;/code&gt; but also step four from above. Step four is attaching the &lt;code&gt;WHAT&lt;/code&gt; to &lt;code&gt;WHERE&lt;/code&gt;, and it's a cost that can be avoided. &lt;/p&gt;

&lt;p&gt;To avoid this cost, you need three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Serialize all of the required information as part of the HTML. The serialized information needs to include &lt;code&gt;WHAT&lt;/code&gt;, &lt;code&gt;WHERE&lt;/code&gt;,&lt;code&gt;APP_STATE&lt;/code&gt;, and &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; A global event handler that relies on event bubbling to intercept all events. The event handler needs to be global so that we are not forced to eagerly register all events individually on specific DOM elements.&lt;/li&gt;
&lt;li&gt; A factory function that can lazily recover the event handler (the &lt;code&gt;WHAT&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F04681212764f4025b2b5f5c6a258ad6e%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F04681212764f4025b2b5f5c6a258ad6e%3Fformat%3Dwebp%26width%3D2000" alt="Hydration gets html, downloads JS , parses and executes JS, and binds listeners. Resumable only gets HTML"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A factory function is the key! Hydration creates the &lt;code&gt;WHAT&lt;/code&gt; eagerly because it needs the &lt;code&gt;WHAT&lt;/code&gt; to attach it to &lt;code&gt;WHERE&lt;/code&gt;. Instead, we can avoid doing unnecessary work by creating the &lt;code&gt;WHAT&lt;/code&gt; lazily as a response to a user event.&lt;/p&gt;

&lt;p&gt;The above setup is resumable because it can resume the execution where the server left off without redoing any work that the server already did. More importantly, the setup has no overhead because all of the work is necessary and none of the work is redoing what the server already did.&lt;/p&gt;

&lt;p&gt;A good way to think about the difference is by looking at push and pull systems. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Push (hydration): Eagerly download and execute code to eagerly register the event handlers, just in case of user interaction.&lt;/li&gt;
&lt;li&gt;  Pull (resumability): Do nothing, wait for a user to trigger an event, then lazily create the handler to process the event.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In hydration, the event handler creation happens before the event is triggered and is therefore eager. Hydration also requires that all possible event handlers be created and registered, just in case the user triggers the event (potentially unnecessary work). So event handler creation is speculative. It is extra work that may not be needed. (The event handler is also created by redoing the same work that the server has already done; hence it is overhead)&lt;/p&gt;

&lt;p&gt;In a &lt;a href="https://www.builder.io/blog/from-static-to-interactive-why-resumability-is-the-best-alternative-to-hydration" rel="noopener noreferrer"&gt;resumable system&lt;/a&gt;, the event handler creation is lazy. Therefore, the creation happens after the event is triggered and is strictly on an as-needed basis. The framework creates the event handler by deserializing it, and thus the client does not redo any work that the server already did. &lt;/p&gt;

&lt;p&gt;The lazy creation of event handlers is how &lt;a href="https://qwik.builder.io/" rel="noopener noreferrer"&gt;Qwik&lt;/a&gt; works, which allows it to create speedy application startup times.&lt;/p&gt;

&lt;p&gt;Resumability requires that we serialize &lt;code&gt;WHAT&lt;/code&gt;(&lt;code&gt;APP_STATE&lt;/code&gt;, &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt;) and &lt;code&gt;WHERE&lt;/code&gt;. A resumable system may generate the following HTML as a possible solution to store &lt;code&gt;WHAT&lt;/code&gt;(&lt;code&gt;APP_STATE&lt;/code&gt;, &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt;) and &lt;code&gt;WHERE&lt;/code&gt;. The exact details are not important, only that all of the information is present.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;q:host&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;q:host&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;"./chunk-a.js#greet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Greet&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;q:host&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;q:obj=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;"./chunk-b.js#count[0]"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;10&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span class="cm"&gt;/* code that sets up global listeners */&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/qwik"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="cm"&gt;/* JSON representing APP_STATE, FRAMEWORK_STATE */&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the above HTML loads in the browser, it will immediately execute the inlined script that sets up the global listener. The application is ready to accept events, but the browser has not executed any application code. This is as close to zero-JS as you can get.&lt;/p&gt;

&lt;p&gt;The HTML contains the &lt;code&gt;WHERE&lt;/code&gt; encoded as attributes on the element. When the user triggers an event, the framework can use the information in the DOM to lazily create the event handler. The creation involves the lazy deserializing of&lt;code&gt;APP_STATE&lt;/code&gt; and &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt; to complete the &lt;code&gt;WHAT&lt;/code&gt;. Once the framework lazily creates the event handler, the event handler can process the event. Notice that the client is not redoing any work that the server has already done.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F3c529b5adb7448d48e05cb04594f1e0c%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F3c529b5adb7448d48e05cb04594f1e0c%3Fformat%3Dwebp%26width%3D2000" alt="How Resumability Works"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  A note on memory usage
&lt;/h2&gt;

&lt;p&gt;The DOM elements retain the event handlers for the lifetime of the element. Hydration eagerly creates all of the listeners. Therefore hydration requires allocating a memory on startup. &lt;/p&gt;

&lt;p&gt;Resumable frameworks do not create the event handlers until after the event is triggered. Therefore, resumable frameworks will consume less memory than hydration. Furthermore, the resumable approach does not retain the event handler after execution. The event handler is released after its execution, returning the memory. &lt;/p&gt;

&lt;p&gt;In a way releasing the memory is the opposite of hydration. It is as if the framework lazily hydrates a specific &lt;code&gt;WHAT&lt;/code&gt;, executes it, and then dehydrates it. There is not much difference between the first and nth execution of the handler. Event handlers' lazy creation and release does not fit the hydration mental model.&lt;/p&gt;

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

&lt;p&gt;Hydration is overhead because it duplicates work. The server builds up the &lt;code&gt;WHERE&lt;/code&gt; and &lt;code&gt;WHAT&lt;/code&gt; (&lt;code&gt;APP_STATE&lt;/code&gt; and &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt;), but the information is discarded instead of being serialized for the client. The client then receives HTML that does not have sufficient information to rebuild the application. The lack of information forces the client to eagerly download the application and execute it to recover the &lt;code&gt;WHERE&lt;/code&gt; and &lt;code&gt;WHAT&lt;/code&gt; (&lt;code&gt;APP_STATE&lt;/code&gt; and &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F6ac78462e04d4761b1beefa4479c4715%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F6ac78462e04d4761b1beefa4479c4715%3Fformat%3Dwebp%26width%3D2000" alt="Just use Resumability for small html"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;An alternative approach is resumability. Resumability focuses on transferring all of the information from the server to the client. The information contains &lt;code&gt;WHERE&lt;/code&gt; and &lt;code&gt;WHAT&lt;/code&gt; (&lt;code&gt;APP_STATE&lt;/code&gt; and &lt;code&gt;FRAMEWORK_STATE&lt;/code&gt;). The additional information allows the client to reason about the application without downloading the application code eagerly. Only a user interaction forces the client to download code to handle that specific interaction. The client is not duplicating any work from the server; therefore, there is no overhead. &lt;/p&gt;

&lt;p&gt;To put this idea into practice, we built &lt;a href="https://qwik.builder.io/" rel="noopener noreferrer"&gt;Qwik&lt;/a&gt;, a framework that is designed around resumabilty and achieves excellent startup performance. We're also excited to hear from you! Let's keep the conversations going and get better as a community at building faster web applications for our users. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;— Love from the&lt;/strong&gt; &lt;a href="https://www.builder.io/m/developers" rel="noopener noreferrer"&gt;&lt;strong&gt;Builder.io team&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PS: Many thanks to&lt;/strong&gt; &lt;a href="https://twitter.com/RyanCarniato" rel="noopener noreferrer"&gt;&lt;strong&gt;Ryan Carniato&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;,&lt;/strong&gt; &lt;a href="http://rich_harris" rel="noopener noreferrer"&gt;&lt;strong&gt;Rich Harris&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;,&lt;/strong&gt; &lt;a href="https://twitter.com/codercatdev" rel="noopener noreferrer"&gt;&lt;strong&gt;Alex Patterson&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;,&lt;/strong&gt; &lt;a href="https://twitter.com/dylan_piercey" rel="noopener noreferrer"&gt;&lt;strong&gt;Dylan Piercey&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;,&lt;/strong&gt; &lt;a href="https://twitter.com/slightlylate" rel="noopener noreferrer"&gt;&lt;strong&gt;Alex Russell&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://twitter.com/Steve8708" rel="noopener noreferrer"&gt;&lt;strong&gt;Steve Sewell&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;who provided constructive feedback for the article. ❤️&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We know you have a few burning questions. That's why we've put together an FAQ to address them all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F71b9ed30c9794f4cb2e4e77f33d674f7%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F71b9ed30c9794f4cb2e4e77f33d674f7%3Fformat%3Dwebp%26width%3D2000" alt="FAQ"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why coin a new term?
&lt;/h3&gt;

&lt;p&gt;Resumability does not have a clear line indicating that component X is or is not hydrated. If you insist on saying that Qwik hydrates, then you have two choices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Qwik apps are hydrated when the global event handler is registered.&lt;/strong&gt; It does not feel right because no app code has been downloaded, and no work has been performed. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Qwik apps are hydrated when the first interaction parses the serialized state.&lt;/strong&gt; Hydration is attaching event listeners for interactivity. Deserializing state is there to recover the application's state and has nothing to do with registering event handlers. There are situations where the deserialization does not need to happen, and when it does, it happens after the event has been triggered. The other problem is that deserialization of state restores state even for components that have not been or will never be downloaded. So while it's tempting to assume that this is the point of hydration, we think of it as just lazy deserialization of app state as it does not directly relate to event processing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Neither of these options feels satisfactory, and so we're coining a new term. You could define hydration as making the app interactive, but such a definition is so broad that it will apply to everyone, which will make it less valuable. So while it may sound like we're splitting hairs, we like to talk about hydration vs. resumability as we believe it better captures the massive difference in the amount of work required to make the application interactive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is resumability just hydration after the event?
&lt;/h3&gt;

&lt;p&gt;It's certainly a valid way to look at it. However, there's one big difference. Resumability does not require that the framework download and execute the components to learn about the component hierarchy. Resumability requires that all of the framework's information be serialized in the HTML, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Location of the event listeners and event types.&lt;/li&gt;
&lt;li&gt;Where to download the event&lt;/li&gt;
&lt;li&gt;Component boundaries&lt;/li&gt;
&lt;li&gt;Component props&lt;/li&gt;
&lt;li&gt;Projection/children&lt;/li&gt;
&lt;li&gt;Where to download the component re-render functions if needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the framework deserializes all of this information and continues the execution where the server left off, resumable is a much better word.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are real world results like?** **Where can I see a site that uses a resumable strategy?
&lt;/h3&gt;

&lt;p&gt;Builder.io used the resumable strategy (and Qwik) to redo our website. We’ve removed 99% of JavaScript from startup and the resulting app feels super snappy even on mobile. Using Qwik and Partytown, we were able to &lt;a href="https://www.builder.io/blog/how-we-cut-99-percent-js-with-qwik-and-partytown" rel="noopener noreferrer"&gt;cut down 99% of the JavaScript in our site and get a PageSpeed score of 100/100&lt;/a&gt;. (You can still visit the &lt;a href="https://www.builder.io/?render=next" rel="noopener noreferrer"&gt;old page using hydration&lt;/a&gt; [&lt;a href="https://pagespeed.web.dev/report?url=https%3A%2F%2Fwww.builder.io%2F%3Frender%3Dnext" rel="noopener noreferrer"&gt;PageSpeed 50/100&lt;/a&gt;] and compare it to the &lt;a href="https://www.builder.io/" rel="noopener noreferrer"&gt;new page using resumability&lt;/a&gt; [&lt;a href="https://pagespeed.web.dev/report?url=https%3A%2F%2Fwww.builder.io%2F" rel="noopener noreferrer"&gt;PageSpeed 100/100&lt;/a&gt;] to experience the performance difference for yourself.)&lt;/p&gt;

&lt;p&gt;Qwik's documentation is running on Qwik. You can look under the hood by opening up the dev tools (incognito) in your browser and notice the lack of Javascript on startup. (The page also uses &lt;a href="https://partytown.builder.io/" rel="noopener noreferrer"&gt;Partytown&lt;/a&gt; to move third-party analytics to web workers.)&lt;/p&gt;

&lt;p&gt;Finally, check out a &lt;a href="https://todo-cloudflare-misko.sethealth.workers.dev/" rel="noopener noreferrer"&gt;to-do app demo&lt;/a&gt; running on Cloudflare edge. This page is ready for interaction in about 50 ms!&lt;/p&gt;

&lt;h3&gt;
  
  
  My framework knows how to do progressive and/or lazy hydration. Is that the same thing?
&lt;/h3&gt;

&lt;p&gt;No, because progressive/lazy hydration still can't continue where the server left off. All component code needs to be downloaded and executed to recover and install the event handlers. &lt;/p&gt;

&lt;p&gt;With resumability, many components will never download because they never change. But these components can pass props to child components or create content that the child component projects. So even if not interactive, the components' state needs to be recovered by re-execution. Recovering props is why islands that enable progressive/lazy hydration can't be arbitrarily small. &lt;/p&gt;

&lt;p&gt;Simply put, resumability requires significantly less code to download and execute to handle a user interaction than hydration. &lt;/p&gt;

&lt;h3&gt;
  
  
  My framework knows how to create islands. Is that the same thing?
&lt;/h3&gt;

&lt;p&gt;The island architecture breaks up the application into islands. Each island can then be hydrated independently. Instead of one big hydration, the total amount of work is now spread over many smaller hydration events. Typically, a trigger causes the island to hydrate lazily instead of eagerly on startup. &lt;/p&gt;

&lt;p&gt;This means island-based hydration is an improvement as it can break the work down into smaller chunks and delay its execution, but it's still hydration and not the same as resumability.&lt;/p&gt;

&lt;h3&gt;
  
  
  My framework knows how to serialize the state. Does it have overhead?
&lt;/h3&gt;

&lt;p&gt;The issue here is that the word state is overloaded. Yes, there are some meta frameworks that can serialize the state. But here, "state" means APP_STATE, not FRAMEWORK_STATE. I'm unaware of any popular framework (or meta-framework) that can serialize FRAMEWORK_STATE. Additionally, even if FRAMEWORK_STATE was serialized, the WHAT and WHERE are not. &lt;/p&gt;

&lt;p&gt;Yes, serialization of state (APP_STATE) is useful and avoids a lot of work on the client. But it still results in hydration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is a component hydrated on first interaction?
&lt;/h3&gt;

&lt;p&gt;If you look at the internal state of a resumable framework, you'll find no difference between the first interaction of the component and subsequent interactions. The only difference is that the framework has parsed the serialized state. And once the state is parsed, it applies to all components, not just the one the user has interacted with. At any point, the framework can serialize the state back to the HTML. Does that mean that the application is no longer hydrated? From that point of view, deserialization of state hydrates all components, even if their code has not been downloaded. &lt;/p&gt;

&lt;h3&gt;
  
  
  How can I take advantage of resumability today?
&lt;/h3&gt;

&lt;p&gt;The framework controls the kind of recovery strategies it uses to make the application interactive. Therefore, to take advantage of resumability, your application needs to be using one of the frameworks which support it. Currently, we are only aware of Qwik which aims explicitly for resumability. The benefits of resumability are too great to be ignored, so I'm sure that other frameworks will start using this strategy in the future, whether they're new frameworks or existing frameworks that choose to migrate to resumability. &lt;/p&gt;

&lt;h3&gt;
  
  
  Is there a delay on first interaction?
&lt;/h3&gt;

&lt;p&gt;Not when you use prefetching. Qwik is unopinionated about prefetching - we have used a variety of strategies for prefetching (eager, on visible, analytics-driven) to great results. In most cases, we find prefetching in a Web Worker, such as with Partytown, leads to the best balance of 0 cost and high speed. We will bake best practices into the framework and provide examples with recommended patterns over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use my React/Angular/Vue/Svelte components with Qwik?
&lt;/h3&gt;

&lt;p&gt;Rewriting an application is a huge undertaking. To lower the barrier to entry, we are looking into creating interoperability with some of today's more popular frameworks. Qwik will be your orchestrator delivering instant applications startup, but it will still work with most of the existing code investment. Think of Qwik can as the orchestrator for your current application. This way, you don't have to rewrite the whole application but still get some benefits. This is a work in progress, so stay tuned.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F9ccc9ec24cda40afab151379e000d443%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F9ccc9ec24cda40afab151379e000d443%3Fformat%3Dwebp%26width%3D2000" alt="One more thing..."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if you are curious what is coming up next for Qwik:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252Fa0bc65c6b2744151a88493206587e657%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252Fa0bc65c6b2744151a88493206587e657%3Fformat%3Dwebp%26width%3D2000" alt="coming shortly use react components in Qwik"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you made it this far, thanks for reading! Learn more about Qwik &lt;a href="https://github.com/builderio/qwik" rel="noopener noreferrer"&gt;here&lt;/a&gt;, or &lt;a href="https://twitter.com/builderio" rel="noopener noreferrer"&gt;follow us on Twitter&lt;/a&gt; to get updates as we have them&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>From Static to Interactive: Why Resumability is the Best Alternative to Hydration</title>
      <dc:creator>Miško Hevery</dc:creator>
      <pubDate>Thu, 31 Mar 2022 01:01:14 +0000</pubDate>
      <link>https://dev.to/builderio/from-static-to-interactive-why-resumability-is-the-best-alternative-to-hydration-3jjp</link>
      <guid>https://dev.to/builderio/from-static-to-interactive-why-resumability-is-the-best-alternative-to-hydration-3jjp</guid>
      <description>&lt;div class="ltag__user ltag__user__id__647890"&gt;
    &lt;a href="/mhevery" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F647890%2Fa89c8fc1-ceb2-46d2-b354-9ad0d91d7654.jpeg" alt="mhevery image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/mhevery"&gt;Miško Hevery&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/mhevery"&gt;CTO at Builder.io, empower anyone to create blazing fast sites. Previously at Google, where he created Angular, AngularJS and was co-creator of Karma.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Original: &lt;a href="https://www.builder.io/blog/from-static-to-interactive-why-resumability-is-the-best-alternative-to-hydration" rel="noopener noreferrer"&gt;https://www.builder.io/blog/from-static-to-interactive-why-resumability-is-the-best-alternative-to-hydration&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No one wants a slow, unresponsive website. Prerendering your site is one of your most powerful tools as a web developer when it comes to website performance optimization.&lt;/p&gt;

&lt;p&gt;Almost all front-end JavaScript (JS) frameworks have a way to prerender content as HTML through server side rendering (SSR) or static site generation (SSG). The result is that the site displays almost instantly as the HTML is streamed into your user’s browser.&lt;/p&gt;

&lt;p&gt;However, there’s a problem. HTML is static whereas websites are usually dynamic and interactive. How do frameworks make pre-rendered HTML interactive on the browser?&lt;/p&gt;

&lt;p&gt;The current generation of frameworks solves this through a client-side process called hydration, a resource-intensive process that adds significant overhead to the page’s startup cost.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252Fae78f1d471d44fb3824615a0ce37391f%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252Fae78f1d471d44fb3824615a0ce37391f%3Fformat%3Dwebp%26width%3D2000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s my controversial opinion: hydration is what happens when you add SSR/SSG as an afterthought to a front-end framework.&lt;/p&gt;

&lt;p&gt;A framework designed from the ground up for prerendering can avoid hydration and its performance penalty by serializing state on the server and resuming it on the client.&lt;/p&gt;

&lt;p&gt;Before diving into serialization and resumability, let’s talk about the problem that hydration solves.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does a framework make a page interactive?
&lt;/h2&gt;

&lt;p&gt;Any front-end framework needs three things to be able to respond to interactivity:&lt;/p&gt;

&lt;p&gt;Associating event handlers: The framework must have a way to associate DOM elements with their corresponding event handlers, which are the functions that respond to user input and enable interaction with your website.&lt;br&gt;
Recovering application state: Once a user event triggers an event handler, the function updates application state.&lt;br&gt;
Recreating the component hierarchy: Once the application state updates, the framework needs to re-render the application view to reflect the state to the user. The framework must understand the relationship between the state and the components to complete rendering.&lt;br&gt;
Let's look deeper into how hydration handles these tasks and why it’s an expensive approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Associating event handlers
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252Fb23ba131d5be4363b88839141f22ce28%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252Fb23ba131d5be4363b88839141f22ce28%3Fformat%3Dwebp%26width%3D2000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Frameworks associate event handlers with specific DOM elements by executing a component template. For example, in React, a button component written in JSX might have an onClick prop with an event handler. Hydration requires that the browser downloads and executes all components’ templates before associating event handlers.&lt;/p&gt;

&lt;p&gt;Unfortunately, the JS bundle’s download size and code execution time is proportional to the complexity of the page. A small demo page will download a small amount of JS and execute quickly, but the bootstrap cost becomes prohibitively expensive when it comes to real-world pages, often leading to multi second times to interactive (TTI).&lt;/p&gt;

&lt;p&gt;Some frameworks mitigate this performance penalty by attempting to delay when certain parts of a page are rendered. This strategy works reasonably well for content-centric pages such as marketing pages. For sites like web apps where components share state in complex ways, however, frameworks still need to download every component in the DOM tree and execute its template.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recovering application state
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F0385d4b50ce94ac69bff2e694eca7f5d%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F0385d4b50ce94ac69bff2e694eca7f5d%3Fformat%3Dwebp%26width%3D2000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Event handlers need an application state to update, which is present on the server during prerendering. Frameworks must reconstruct this state on the client for the DOM to update properly.&lt;/p&gt;

&lt;p&gt;Hydration’s basic approach is to execute the same code that generated the application state on the server again within the browser, which adds to execution time and delays interactivity.&lt;/p&gt;

&lt;p&gt;That’s why many meta-frameworks serialize the application state on the server and include it in the HTML so that state can be restored using &lt;code&gt;JSON.parse()&lt;/code&gt;. Deserialization is significantly faster than reconstructing state by executing application code on the browser, and it works well for simple and complex pages.&lt;/p&gt;

&lt;p&gt;Even when application state is serialized, however, hydration still reconstructs internal framework state by slowly executing code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recreating the component hierarchy
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F65caa495f5074d14a8eb9866b3c5ce57%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F65caa495f5074d14a8eb9866b3c5ce57%3Fformat%3Dwebp%26width%3D2000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the final piece, frameworks need to recreate the component hierarchy, which is part of a framework’s internal state. It keeps track of which components need to be rerendered when your application state changes.&lt;/p&gt;

&lt;p&gt;Similar to how it associates event handlers with DOM elements, hydration must download all of a page’s components and execute their templates to rebuild a component hierarchy, adding still more overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  The alternative to hydration
&lt;/h2&gt;

&lt;p&gt;Front-end frameworks perform hydration to recover event handlers, application state, and the component hierarchy in order to make the page interactive.&lt;/p&gt;

&lt;p&gt;Each step requires downloading and executing code, which is expensive. Code execution time in particular is proportional to your page’s complexity when using hydration. We could roughly model this limitation with an equation:&lt;/p&gt;

&lt;p&gt;Time to interactive = hydration execution cost * page complexity + payload size&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F8c7240165b4c41d290b82209df7eb76e%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F8c7240165b4c41d290b82209df7eb76e%3Fformat%3Dwebp%26width%3D2000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No matter how small your payload, hydration will always be a bottleneck.&lt;/p&gt;

&lt;p&gt;One solution to this problem is to eliminate the need to execute any code to restore a page’s interactivity, which we can do through serialization. As mentioned above, many meta-frameworks already serialize application state. Why not serialize event handler associations and component hierarchies, as well?&lt;/p&gt;

&lt;p&gt;Because it’s really hard!&lt;/p&gt;

&lt;p&gt;Function closures, promises, and resource references, among other structures, are all difficult to serialize. So a framework needs to be designed with serializability and resumability in mind. These aren’t features that can easily be added to existing frameworks without large-scale breaking changes.&lt;/p&gt;

&lt;p&gt;The biggest win of serializing page state into HTML is that making the page interactive doesn’t require downloading or executing any template code. The framework simply resumes the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F73768ea2bcb54fc7826d15de3d3f3019%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F73768ea2bcb54fc7826d15de3d3f3019%3Fformat%3Dwebp%26width%3D2000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The bottom line? Resumable frameworks would reduce execution cost to zero and incur a constant overhead regardless of page complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resumability in Qwik
&lt;/h2&gt;

&lt;p&gt;We at Builder.io have created a resumable front-end framework, Qwik. Our goal is to bring every web page’s time to interactive to its absolute minimum.&lt;/p&gt;

&lt;p&gt;While we got the ball rolling, Qwik is open to the community. Everyone who’s as passionate about web performance as we are is invited to try it out and contribute and comment.&lt;/p&gt;

&lt;p&gt;Head over to Qwik’s repository to learn more, or try our starter: &lt;code&gt;npm init qwik@latest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you have any questions, ask away on our &lt;a href="https://github.com/BuilderIO/qwik/discussions" rel="noopener noreferrer"&gt;discussions forum&lt;/a&gt; and join our &lt;a href="https://discord.com/invite/8rnCeM5e5N" rel="noopener noreferrer"&gt;Discord server&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>qwik</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>frameworks</category>
    </item>
    <item>
      <title>Introducing Qwik starters - get up and running with Qwik now</title>
      <dc:creator>Miško Hevery</dc:creator>
      <pubDate>Tue, 14 Dec 2021 22:25:03 +0000</pubDate>
      <link>https://dev.to/builderio/introducing-qwik-starters-get-up-and-running-with-qwik-now-3ap2</link>
      <guid>https://dev.to/builderio/introducing-qwik-starters-get-up-and-running-with-qwik-now-3ap2</guid>
      <description>&lt;p&gt;Nothing is more satisfying than playing with code and discovering new things! Yes, it is finally here, &lt;code&gt;npm init qwik&lt;/code&gt; for you to try and discover a different way to build web apps that stay lean and performant no matter their size. It is the same technology that is powering &lt;a href="https://www.builder.io" rel="noopener noreferrer"&gt;builder.io&lt;/a&gt; and gets &lt;a href="https://www.builder.io/blog/how-we-cut-99-percent-js-with-qwik-and-partytown" rel="noopener noreferrer"&gt;100/100 PageSpeed&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Qwik starter CLI is a simple starter for you to try experimenting with Qwik first hand and to get a better understanding of just how different it is.&lt;/p&gt;

&lt;p&gt;The CLI consist of these four examples, that will be expanded in the near future:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;starter&lt;/code&gt;: A basic hello world.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;starter-builder&lt;/code&gt;: A basic hello world integrated with Builder's &lt;a href="https://www.builder.io/c/docs/qwik-api" rel="noopener noreferrer"&gt;Qwik API&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;starter-partytown&lt;/code&gt;: A basic hello world showing how expensive tasks can be run on web-worker with &lt;a href="https://github.com/BuilderIO/partytown" rel="noopener noreferrer"&gt;Partytown&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;todo&lt;/code&gt;: A classic &lt;a href="https://todomvc.com/" rel="noopener noreferrer"&gt;TodoMVC&lt;/a&gt; application. &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Basic starter
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; npm init qwik
💫 Let's create a Qwik project 💫

✔ Project name … qwik-starter
✔ Select a starter › Starter
✔ Select a server › Express

⭐️ Success! Project saved in qwik-starter directory

📟 Next steps:
   cd qwik-starter
   npm install
   npm start

&amp;gt; (cd qwik-starter; npm install; npm start)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F17ab71fc12be4fbb9a8b19415998995f%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F17ab71fc12be4fbb9a8b19415998995f%3Fformat%3Dwebp%26width%3D2000" alt="qwik-starter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try it in &lt;a href="https://stackblitz.com/edit/qwik-starter" rel="noopener noreferrer"&gt;StackBlitz&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starter with Builder Qwik API
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; npm init qwik
💫 Let's create a Qwik project 💫

✔ Project name … qwik-builder
✔ Select a starter › Starter Builder
✔ Select a server › Express

⭐️ Success! Project saved in qwik-builder directory

📟 Next steps:
   cd qwik-builder
   npm install
   npm start

&amp;gt; (cd qwik-builder; npm install; npm start)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F8c4425a663a84a41a85555f53f2665fc%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F8c4425a663a84a41a85555f53f2665fc%3Fformat%3Dwebp%26width%3D2000" alt="qwik-builder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try it in &lt;a href="https://stackblitz.com/edit/qwik-todo-builder" rel="noopener noreferrer"&gt;StackBlitz&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starter with Partytown
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; npm init qwik
💫 Let's create a Qwik project 💫

✔ Project name … qwik-partytown
✔ Select a starter › Starter Partytown
✔ Select a server › Express

⭐️ Success! Project saved in qwik-partytown directory

📟 Next steps:
   cd qwik-partytown
   npm install
   npm start

&amp;gt; (cd qwik-partytown; npm install; npm start) 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F135effed7c724979b0fe246bd9cc20ac%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252F135effed7c724979b0fe246bd9cc20ac%3Fformat%3Dwebp%26width%3D2000" alt="qwik-partytown"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Classic TodoMVC
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; npm init qwik
💫 Let's create a Qwik project 💫

✔ Project name … qwik-todo
✔ Select a starter › Todo
✔ Select a server › Express

⭐️ Success! Project saved in qwik-todo directory

📟 Next steps:
   cd qwik-todo
   npm install
   npm start

&amp;gt; (cd qwik-todo; npm install; npm start)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252Fc7c0ea671c4547ecb2cd7da50843b97f%3Fformat%3Dwebp%26width%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252FYJIGb4i01jvw0SRdL5Bt%252Fc7c0ea671c4547ecb2cd7da50843b97f%3Fformat%3Dwebp%26width%3D2000" alt="qwik-tobo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try it now in &lt;a href="https://stackblitz.com/edit/qwik-todo-demo" rel="noopener noreferrer"&gt;StackBlitz&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Profile away
&lt;/h2&gt;

&lt;p&gt;We encourage you to open the dev tools and put all of the examples through the profiler to see how little time is spent on the main thread.&lt;/p&gt;

&lt;p&gt;Happy coding and please provide feedback:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Star us on &lt;a href="https://github.com/builderio/qwik" rel="noopener noreferrer"&gt;github.com/builderio/qwik&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Follow us on &lt;a href="https://twitter.com/QwikDev" rel="noopener noreferrer"&gt;@QwikDev&lt;/a&gt; and &lt;a href="https://twitter.com/builderio" rel="noopener noreferrer"&gt;@builderio&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Chat us on &lt;a href="https://discord.gg/JHVpZmqSs4" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Join &lt;a href="https://builder-io.rippling-ats.com/" rel="noopener noreferrer"&gt;builder.io&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>qwik</category>
      <category>javascript</category>
      <category>frameworks</category>
      <category>performance</category>
    </item>
    <item>
      <title>How we cut 99% of our JavaScript with Qwik + Partytown</title>
      <dc:creator>Miško Hevery</dc:creator>
      <pubDate>Mon, 06 Dec 2021 15:32:07 +0000</pubDate>
      <link>https://dev.to/builderio/how-we-cut-99-of-our-javascript-with-qwik-partytown-3i3k</link>
      <guid>https://dev.to/builderio/how-we-cut-99-of-our-javascript-with-qwik-partytown-3i3k</guid>
      <description>&lt;p&gt;We’re excited to announce that the &lt;a href="http://builder.io" rel="noopener noreferrer"&gt;builder.io&lt;/a&gt; homepage now achieves a 100/100 score on &lt;a href="https://pagespeed.web.dev/report?url=https%3A%2F%2Fbuilder.io%2F" rel="noopener noreferrer"&gt;PageSpeed Insights&lt;/a&gt;, even on mobile, since we adopted &lt;a href="https://github.com/builderio/qwik" rel="noopener noreferrer"&gt;Qwik&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/builderio/qwik" rel="noopener noreferrer"&gt;Qwik&lt;/a&gt; can achieve this performance no matter how large your application gets. The above numbers were achieved with some cool technology including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pages served with &lt;a href="https://github.com/builderio/qwik" rel="noopener noreferrer"&gt;Qwik&lt;/a&gt; have less than 1kb of JavaScript to boot.&lt;/li&gt;
&lt;li&gt;Our homepage only sends HTML for above-the-fold content.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/BuilderIO/partytown" rel="noopener noreferrer"&gt;Partytown&lt;/a&gt; is used to move all third-party scripts to web-worker.&lt;/li&gt;
&lt;li&gt;This site is created using &lt;a href="https://builder.io" rel="noopener noreferrer"&gt;builder.io&lt;/a&gt;’s  visual no-code editor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Qwik scales to massive sites, with hundreds of components, and MBs of content and continues to be fast. And it provides interactive server-side components that can transition to client components.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmfuty5116bna9h6xyawr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmfuty5116bna9h6xyawr.png" alt="Builder.io after qwik"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where were we before
&lt;/h2&gt;

&lt;p&gt;Our story starts here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fol56o66cw8gpxsbxaixr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fol56o66cw8gpxsbxaixr.png" alt="Builder.io before optimization"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that the performance of the site is average. On mobile, Google PageSpeed estimated that it will take 7.6 seconds before a user can click on a link and expect a response. This is not a great user experience. Additionally, Google is using PageSpeed scores to affect SEO ranking. &lt;/p&gt;

&lt;p&gt;The reason for this is that the site has to execute a lot of Javascript on startup. Today, even a static site is full of JavaScript to add menus, interactivity, and third-party analytics scripts such as Google Tag Manager, Intercom, and CRM services. &lt;/p&gt;

&lt;p&gt;The JavaScript site consists of two sources of slow down, the site itself and third-party scripts. &lt;/p&gt;

&lt;p&gt;The first source of slow down comes from frameworks. When used in conjunction with modern frameworks, sites have a great developer experience and are highly interactive. But this comes at a cost of large JS download and slow startup times as frameworks reconcile the HTML generated on the server with the DOM the frameworks expect. This is known as reconciliation/rehydration, and all frameworks (with exception of Qwik) suffer this fate. The key part of reconciliation/rehydration is when the frameworks attach the listeners to the DOM, making the site interactive. This is the reason why reconciliation/rehydration has to happen as soon as possible. Without this, your site does not work (think menus, chat widgets, etc...)&lt;/p&gt;

&lt;p&gt;The second source of slow down comes from third-party scripts. Yes, there are a lot of demo sites and “new builds” that show good PageSpeed scores, but this is in large part because third-party scripts are not yet included. Here is an example of some of the third-party scripts which are on our site: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google Tag Manager: is a must for any live site to collect usage statistics so that the marketing can gain insight as to how the site is used and how it can be improved. GTM executes at the beginning and it alone can take up all of the CPU time allotted for the site in PageSpeed before it starts being penalized.&lt;/li&gt;
&lt;li&gt;Intercom: Allows the customers to chat with builders in real-time on the site to ask questions and to find out more information.&lt;/li&gt;
&lt;li&gt;Twitter: Testimonials about our product are shown in twitter widgets, which requires that we load Twitter javascript.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of the above third-party scripts run immediately on-site load and compete for CPU with the reconciliation/rehydration step above, resulting in poor user experience.&lt;/p&gt;

&lt;p&gt;The issue is that as developers we have very little control over the above situation. We must use third-party scripts to add analytics and user service features that marketing teams need, and we must use existing frameworks which require expensive reconciliation on-site startup. There just are not a lot of levers under our control. This is the state of our industry and it is why no one can get much better results with the standard approach.&lt;/p&gt;

&lt;p&gt;Qwik and Partytown aim to solve that!&lt;/p&gt;

&lt;h2&gt;
  
  
  Where are we now
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmfuty5116bna9h6xyawr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmfuty5116bna9h6xyawr.png" alt="Builder.io after qwik"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;th&gt;Unit&lt;/th&gt;
&lt;th&gt;%&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Performance Score&lt;/td&gt;
&lt;td&gt;52&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;92%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First Contentfull Paint&lt;/td&gt;
&lt;td&gt;3.4&lt;/td&gt;
&lt;td&gt;1.1&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;309%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speed Index&lt;/td&gt;
&lt;td&gt;3.4&lt;/td&gt;
&lt;td&gt;1.1&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;309%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Largest Contentful Paint&lt;/td&gt;
&lt;td&gt;3.8&lt;/td&gt;
&lt;td&gt;1.2&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;316%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time to Interactive&lt;/td&gt;
&lt;td&gt;7.6&lt;/td&gt;
&lt;td&gt;1.4&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;543%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TTI - LCP (difference)&lt;/td&gt;
&lt;td&gt;3.8&lt;/td&gt;
&lt;td&gt;0.3&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;1,266%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total Blocking Time&lt;/td&gt;
&lt;td&gt;1,300&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;ms&lt;/td&gt;
&lt;td&gt;3,250%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cumulative Layout Shift&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;First, a reminder that these numbers are for mobile, a much harder bar to reach than desktop performance.&lt;/p&gt;

&lt;p&gt;The above table shows where we are now with Qwik and Partytown. The improvements are massive. Time to interactive dropped from 7.6 seconds down to 1.2 seconds. And total blocking time dropped from 1.3 seconds down to 40 milliseconds. The drop in JS execution can directly be attributed to Qwik for framework time and Partytown for third-party time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66w9x8saqkumy3nttv4d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66w9x8saqkumy3nttv4d.png" alt="Previous site startup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above is the performance profile before Qwik/Partytown. (This is emulating mobile)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Page took 1.8 seconds to load.&lt;/li&gt;
&lt;li&gt;The main thread is very busy most of the time with "reconciliation" work (Figuring out where the DOM listeners should be placed.)&lt;/li&gt;
&lt;li&gt;The above results in many dropped frames.&lt;/li&gt;
&lt;li&gt;There is a cascade of JS code loading before the main thread gets busy with "reconciliation". &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4940z1i5ar81b1kq3340.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4940z1i5ar81b1kq3340.png" alt="Qwik / Partytown startup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Compare the previous expensive startup with the Qwik/Partytown combination? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No JS download&lt;/li&gt;
&lt;li&gt;Page took 0.5 seconds to load.&lt;/li&gt;
&lt;li&gt;Main thread is mostly idle.&lt;/li&gt;
&lt;li&gt;Very few dropped frames.&lt;/li&gt;
&lt;li&gt;Party town loads later&lt;/li&gt;
&lt;li&gt;3rd party scripts execute in web worker (rather than main thread)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The comparison between the previous and current performance is night and day.&lt;/p&gt;

&lt;p&gt;The main thing to take away is not that Qwik/Partytown have some clever algorithm. Instead, Qwik/Partytown offloads the main thread from almost all JS, which is why the page loads so fast. But with Qwik, the page remains fully interactive, even with almost no JS. Qwik lets you have your cake and eat it too. Let's look at JavaScript usage.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;minified&lt;/th&gt;
&lt;th&gt;compressed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Baseline (Main Thread JS)&lt;/td&gt;
&lt;td&gt;1,800kB&lt;/td&gt;
&lt;td&gt;326kB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Qwik + Partytown (Main Thread JS)&lt;/strong&gt;*&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.5kB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.5kB&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--&amp;gt; &lt;em&gt;part: Qwikloader&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;&lt;em&gt;.5kB&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;1kB&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--&amp;gt; &lt;em&gt;part: Partytown confg&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;&lt;em&gt;.5kB&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;1kB&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--&amp;gt; &lt;em&gt;part: Partytown&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;&lt;em&gt;2.5kB&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;1.5kB&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;=== Size Improvement ===&lt;/td&gt;
&lt;td&gt;51,429%&lt;/td&gt;
&lt;td&gt;13,000%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebWorker 3rd Party JS&lt;/td&gt;
&lt;td&gt;219kB&lt;/td&gt;
&lt;td&gt;82kB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--&amp;gt; &lt;em&gt;part: Zoominfo&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;&lt;em&gt;1.5kB&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;1.3kB&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--&amp;gt; &lt;em&gt;part: Google Tag Manager&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;&lt;em&gt;167kB&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;60kB&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--&amp;gt; &lt;em&gt;part: Google Analytics&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;&lt;em&gt;50kB&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;21kB&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--&amp;gt; &lt;em&gt;part: site-tracking&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;&lt;em&gt;217kB&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;64kB&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We went from 1.8MB of JavaScript on the Main thread down to 3.5kB. WOW!&lt;/p&gt;

&lt;p&gt;The original site had 1.8MB of JavaScript, out of that 219kB was a third-party scripts which as developers we have no control over. That leaves 1.6MB of JavaScript for the site itself. The 1.6Mb contains the framework, templates, and styling needed to rehydrate the site back to full interactivity. When using standard frameworks your site will download the content twice. Once as HTML and again as JavaScript. The double download is what accounts for 1.6MB of code. (You know it is site templates because it compresses really well down to 244kB.)&lt;/p&gt;

&lt;p&gt;Contrast the baseline with Qwik + Partytown which comes in at 3.5kB (2.5kB compressed.) Let me repeat that to make it clear. With Qwik + Partytown the only JavaScript which needs to execute on the main thread comes to 3.5kB! This is the reason why the site is so fast to load because there is nothing for the MainThread to do. The other thing to point out is that the 3.5kB will stay no matter how complicated your site gets, it is a fixed cost.&lt;/p&gt;

&lt;p&gt;We still have the issue of executing third-party code, but that has been relocated to the WebWorkerThread which runs at a lower priority than MainThred. There all 220kB of third-party code can do its thing without affecting the MainThread performance.&lt;/p&gt;

&lt;p&gt;But there is one more thing to point out. Above we mentioned that existing frameworks need to download the site twice. Once as HTML and again as JavaScript which comes to 1.6MB. Here is where Qwik gets to shine. Qwik takes that 1.6MB and breaks it up into multiple separate chunks. Qwik can then download only a small portion of that whole JavaScript and only on user interaction. Qwik can rehydrate components lazily and out of order. This means there is no JavaScript needed until the user interacts with something on the page. And because the hydration is independent for each component only a small piece of JavaScript needs to be downloaded and executed on user interaction to hydrate only that component that the user interacted with. So there are two benefits: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We don't have to do anything on page startup, and &lt;/li&gt;
&lt;li&gt;when we do have to rehydrate, it is scoped to a single component only (rather than to the whole page). &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The last thing to point out is that the vast majority of the page is static, which means those components will never hydrate and thus the JavaScript for those components will never download.&lt;/p&gt;

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

&lt;p&gt;Qwik is a new kind of web framework that focuses on time-to-interactive. Resumability means that Qwik can start executing on the server, can be serialized into HTML, and sent to the client. On the client, &lt;code&gt;qwikloader.js&lt;/code&gt; (less than 1kb JS on the client) sits idly waiting for user interaction. When a user interacts, Qwik can resume execution where the server left off. Resumability means that Qwik does not have to do reconciliation on startup and only the component you interact with needs to be hydrated. Qwik can create components on the server and then move them to the client in a seamless way. All of the above results in instant-on applications as is demonstrated above.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lazy loading of content below the fold
&lt;/h3&gt;

&lt;p&gt;Qwik keeps all of its state in DOM, which means that Qwik itself is stateless. The stateless property allows for the lazy loading of content below the fold. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F565yei3n8jydkkvs81yr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F565yei3n8jydkkvs81yr.gif" alt="Lazy loading of HTML below the fold"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above is very difficult to do with existing frameworks but is trivial with Qwik.&lt;/p&gt;

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

&lt;p&gt;Partytown allows you to relocate third-party scripts into web-worker. Third-party scripts are often the biggest culprit for making the site how slow time-to-interactive. &lt;/p&gt;

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

&lt;p&gt;We are hard at work on getting Qwik into your hands soon so you can see for yourself what kind of amazing things you can build.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>frameworks</category>
    </item>
    <item>
      <title>Your bundler is doing it wrong</title>
      <dc:creator>Miško Hevery</dc:creator>
      <pubDate>Mon, 30 Aug 2021 15:40:16 +0000</pubDate>
      <link>https://dev.to/builderio/your-bundler-is-doing-it-wrong-ic0</link>
      <guid>https://dev.to/builderio/your-bundler-is-doing-it-wrong-ic0</guid>
      <description>&lt;p&gt;Today's bundlers rely on developers to decide where and when the application code should be lazy loaded. This is done by developers inserting dynamic imports into their codebase like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;doSomething&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;chunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-chunk&lt;/span&gt;&lt;span class="dl"&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;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someSymbol&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;Developer needs to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decide where in code a good place for lazy loading would be.&lt;/li&gt;
&lt;li&gt;Lazy load in a way that is compatible with the existing application workflow. (Lazy loading is inherently asynchronous, and the ideal function to do perform the lazy loading may be synchronous, limiting where the lazy loading code can be placed.)&lt;/li&gt;
&lt;li&gt;Assign a chunk name &lt;code&gt;./my-chunk&lt;/code&gt; which will influence what the bundler can name its chunks, and how it can put chunks together into an application.&lt;/li&gt;
&lt;li&gt;Determine what will go into the chunk (e.g. should &lt;code&gt;symbolA&lt;/code&gt; and &lt;code&gt;symbolB&lt;/code&gt; go into the same chunk, or should they go to separate chunks?).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The issue with the above is that when a developer is writing source code, they have no idea if the location they chose is a good place to have a lazy loaded boundary, or if the chunks have the right symbols. This information is not available until the application is deployed and the results of real-world usage are observed. For example, maybe the settings page is rarely visited and so it should be pulled out of the main bundle. Alternatively, maybe the notification section is lazy loaded but it is the most frequented page by users, so the lazy loading is only making the experience worse.&lt;/p&gt;

&lt;p&gt;To make matters worse, once a developer makes these choices there is very little the bundler can do to compensate for them. The bundler pretty much MUST do what the developer asked for. To give the bundler more freedom, we need to look at the problem in a fresh new way.&lt;/p&gt;

&lt;p&gt;My point is that when we write code we have no idea what the final bundles should look like and, therefore, don't have sufficient information to decide where to put the dynamic imports. On the other hand, by the time we collect sufficient data on what ideal chunks should look like the source code is already written. Inserting dynamically imports retroactively may be a huge undertaking. (Or alternatively, we over lazy loaded and broke the app into far too many small pieces.)&lt;/p&gt;

&lt;p&gt;What we want is the ability to decide what the ideal number of chunks should be and move the code between those chunks based on how real users use our application. We also want to do that without having to go back and refactor our source code. Chunk layout should be configuration information we pass into the bundler, rather than code we embed into our codebase. &lt;/p&gt;

&lt;p&gt;To add even more complexity, all of the current generation of frameworks have synchronous rendering pipelines. This makes it very difficult to insert asynchronous dynamic imports into the application.&lt;/p&gt;

&lt;p&gt;If we want an optimal lazy loading strategy we need to solve the problems above. &lt;/p&gt;

&lt;h2&gt;
  
  
  Enter Qwik
&lt;/h2&gt;

&lt;p&gt;Components are the basic building blocks of Qwik applications. Qwik asks you to breaks up the component into three parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;view&lt;/strong&gt;: Contains the JSX code which renders the visual portion of the component.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;state&lt;/strong&gt; factory: Contains code that creates a new component state.&lt;/li&gt;
&lt;li&gt;event &lt;strong&gt;handlers&lt;/strong&gt;: Contains code used for component behavior/user interactions.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why break up components into three parts?
&lt;/h2&gt;

&lt;p&gt;Most frameworks keep view, state, and handler code together. Here is an example of how a pseudo framework might achieve this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&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="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;step&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt;&lt;span class="kr"&gt;number&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;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&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;step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;step&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onclick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;-&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/botton&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&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;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onclick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/botton&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;Note that the components view, state, and handler are all inlined together. The implication is that all of these parts (view, state, and handler) have to be downloaded, parsed, and executed together. This severely limits our lazy loading capability.&lt;/p&gt;

&lt;p&gt;The example above might be trivial, but imagine a more complex version of the above, which requires many KB worth of code to be downloaded, parsed, and executed together. In such a case, requiring the view, state, and handler to be eagerly loaded together might be a problem. Let's look at some common user usage patterns to get a better idea as to why this is an issue:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User interacts with a component by clicking on it:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;some of the &lt;code&gt;handler&lt;/code&gt;s are needed: Only the specific handler which is triggered needs to be downloaded. All other handlers are not needed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;view&lt;/code&gt; is &lt;strong&gt;not needed&lt;/strong&gt;: View may not be needed because the handler may not cause a re-render on may cause a re-render of a different component.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;state factory&lt;/code&gt; is &lt;strong&gt;not needed&lt;/strong&gt;: The component is being rehydrated and so no state initialization code is needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Component state is mutated:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;handler&lt;/code&gt;s are &lt;strong&gt;not needed&lt;/strong&gt;: No handlers need to execute.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;view&lt;/code&gt; is needed: View is needed because the component needs to be rerendered.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;state factory&lt;/code&gt; is &lt;strong&gt;not needed&lt;/strong&gt;: The component is being rehydrated and so no state initialization code is needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;New component is created by the parent:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;handler&lt;/code&gt;s are &lt;strong&gt;not needed&lt;/strong&gt;: No handlers need to execute.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;view&lt;/code&gt; is needed: View is needed because the component needs to be rendered.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;state factory&lt;/code&gt; is needed: The component is being created and so state initialization code is needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What the above demonstrates is that in each use-case only part of the view, state, handler information is required. The problem is that we have three distinct pieces of information which are all inlined together, but we only need to use them at different times of the component lifecycle. To achieve the optimal performance we need a way to download and execute the component in parts, based on what the component needs to do. The above code, as it is written, is permanently bound together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking up is easy to do
&lt;/h2&gt;

&lt;p&gt;Qwik solves this by only downloading and executing the code that is needed for the task at hand. Keep in mind that while the example above is simple, the complexity of the code is significantly larger in real-world scenarios. Furthermore, more complex code oftentimes contains more imports (which in turn have imports of their own), that adds even more code to the component.&lt;/p&gt;

&lt;p&gt;It is not possible to "tool" our way out of this. It isn’t possible to write a statically analyzable tool that can separate these pieces into parts that can then be lazy loaded as needed. The developer must break up the component into the corresponding parts to allow fine-grain lazy loading.&lt;/p&gt;

&lt;p&gt;Qwik has &lt;code&gt;qrlView&lt;/code&gt;, &lt;code&gt;qrlState&lt;/code&gt; and &lt;code&gt;qrlHandler&lt;/code&gt; marker functions for this purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;file:&lt;/strong&gt; &lt;code&gt;my-counter.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;QComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nx"&gt;qComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nx"&gt;qrlView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nx"&gt;qrlHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nx"&gt;qrlState&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;@builder.io/qwik&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Declare the component type, defining prop and state shape.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;QComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;},&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="kr"&gt;number&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="c1"&gt;// Declare the component's state factory. This will be used &lt;/span&gt;
&lt;span class="c1"&gt;// when new component is being created to initialize the state. &lt;/span&gt;
&lt;span class="c1"&gt;// (It will not be used on rehydration.)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CounterState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;qrlState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&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="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Define the component's view used for rendering the component.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CounterView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;qrlView&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Counter&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;props&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Counter_update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;with&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;:&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="o"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="o"&gt;-&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&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;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Counter_update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;with&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="o"&gt;+&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Component view may need handlers describing behavior.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter_update&lt;/span&gt;
   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;qrlHandler&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="na"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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;params&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;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="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;step&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="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Finally tie it all together into a component.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;qComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CounterState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CounterView&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;Compared to other frameworks, the above is wordier. However, the cost of the explicit break up of components into their parts gives us the benefit of fine-grained lazy loading.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep in mind that this is a relatively fixed DevExp overhead per component. As the component complexity increases, the added overhead becomes less of an issue.&lt;/li&gt;
&lt;li&gt;The benefit of this is that tooling now has the freedom to package up the component in multiple chunks which can be lazy loaded as needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What happens behind the scenes
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;qrlState&lt;/code&gt;, &lt;code&gt;qrlHandler&lt;/code&gt;, &lt;code&gt;qrlView&lt;/code&gt; are all markers for Qwik Optimizer, which tell the tooling that it needs to transform any reference to it into a QRL. The resulting files can be seen here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;my-counter.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;qComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;qrlView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;qrlHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;qrlState&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;@builder.io/qwik&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CounterState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;qrlState&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="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="p"&gt;}));&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CounterView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;qrlView&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/chunk-pqr#Counter_update?direction=-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="c1"&gt;//              ^^^^^^^^^^^^^^^^^ LOOK ^^^^^^^^^^^^^^^^&lt;/span&gt;
       &lt;span class="o"&gt;-&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&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;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/chunk-pqr#Counter_update?direction=1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="c1"&gt;//              ^^^^^^^^^^^^^^^^^ LOOK ^^^^^^^^^^^^^^^^&lt;/span&gt;
       &lt;span class="o"&gt;+&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter_update&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;qrlHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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;params&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;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="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;step&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;qComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/chunk-abc#CounterState&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;&amp;lt;=== LOOK&lt;/span&gt;
 &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/chunk-cde#CounterView&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// &amp;lt;&amp;lt;=== LOOK&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition to the source file transformation, the optimizer removed any static references between the view, state, and handlers. Qwik also generates entry point files for the rollup. These entry points match the QRLs above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;chunk-abc.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CounterState&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;./my-counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;chunk-pqr.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Counter_update&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;./my-counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;chunk-cde.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CounterView&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;./my-counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important thing to note is that Qwik has great freedom on how many entry files should be generated, as well as which export goes into which entry file. This is because the developer never specified where the lazy loading boundaries are. Instead, the framework guided the developer to write code in a way that introduced many lazy loading boundaries in the codebase. This gives Qwik the power to generate optimal file distribution based on actual application usage. For small applications, Qwik can generate a single file. As the application size grows, more entry files can be generated. If a particular feature is rarely used, it can be placed in its own bundle.&lt;/p&gt;

&lt;p&gt;Once Rollup processes the entry files, the resulting files are as seen below:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;chunk-abc.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;qrlState&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;@builder.io/qwik&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CounterState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;qrlState&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="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="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;chunk-pqr.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;qrlHandler&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;@builder.io/qwik&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter_update&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;qrlHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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;params&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;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="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;step&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;chunk-cde.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;qrlView&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;@builder.io/qwik&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CounterView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;qrlView&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;props&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/chunk-pqr#Counter_update?direction=-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="o"&gt;-&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&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;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/chunk-pqr#Counter_update?direction=1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="o"&gt;+&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;Notice that Rollup flattened the contents of files into the entry files and removed any unneeded code, resulting in ideally sized bundles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Constraints
&lt;/h3&gt;

&lt;p&gt;In order for the tooling to be able to move &lt;code&gt;qComponent&lt;/code&gt;, &lt;code&gt;qrlState&lt;/code&gt;, &lt;code&gt;qrlHandler&lt;/code&gt; around the usage of these methods is restricted. (Not every valid JS program is a valid Qwik program.) The constraint is that all of the marker functions must be a top-level function that is &lt;code&gt;export&lt;/code&gt;ed.&lt;/p&gt;

&lt;p&gt;Examples of invalid code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;someFn&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;./some-place&lt;/span&gt;&lt;span class="dl"&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;main&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;MyStateFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;qrlState&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="c1"&gt;// INVALID not top level&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;MyStateFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;qrlState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;someFn&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt; &lt;span class="c1"&gt;// VALID imports OK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tooling has choices
&lt;/h2&gt;

&lt;p&gt;It is possible (and all too common) to break up an application into too many small files, which negatively impacts download performance. For this reason, the tooling may choose to merge files together and over-bundle. This is desirable behavior. If your entire application is relatively small (less than 50KB) then breaking it up into hundreds of files would be counterproductive.&lt;/p&gt;

&lt;p&gt;If your code structure is fine-grained, the tooling can always choose to create larger (and fewer) bundles. The opposite is not true. If your code structure is coarse, there is nothing the tooling can do to break it up. Qwik guides the developer to break up the application into the smallest possible chunks, and then rely on tooling to find the optimal bundle chunks. This way Qwik can provide optimal performance for applications of all sizes. &lt;/p&gt;

&lt;p&gt;Do you find the above exciting? Then &lt;a href="https://builder-io.rippling-ats.com"&gt;join our team&lt;/a&gt; and help us make the web fast!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Try it on &lt;a href="https://stackblitz.com/edit/qwik-todo-demo"&gt;StackBlitz&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Star us on &lt;a href="https://github.com/builderio/qwik"&gt;github.com/builderio/qwik&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Follow us on &lt;a href="https://twitter.com/QwikDev"&gt;@QwikDev&lt;/a&gt; and &lt;a href="https://twitter.com/builderio"&gt;@builderio&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Chat us on &lt;a href="https://discord.gg/JHVpZmqSs4"&gt;Discord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Join &lt;a href="https://builder-io.rippling-ats.com/"&gt;builder.io&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>performance</category>
      <category>bundling</category>
      <category>javascript</category>
      <category>frameworks</category>
    </item>
    <item>
      <title>How to score 100 on Google PageSpeed Insights on Mobile</title>
      <dc:creator>Miško Hevery</dc:creator>
      <pubDate>Mon, 23 Aug 2021 15:08:55 +0000</pubDate>
      <link>https://dev.to/builderio/how-to-score-100-on-google-pagespeed-insights-on-mobile-2e0i</link>
      <guid>https://dev.to/builderio/how-to-score-100-on-google-pagespeed-insights-on-mobile-2e0i</guid>
      <description>&lt;p&gt;&lt;a href="https://developers.google.com/speed/pagespeed/" rel="noopener noreferrer"&gt;Google PageSpeed Insights&lt;/a&gt; is a tool you can use to measure the perceived latency of your website. Getting a good score here is vital because Google has announced that it will use these scores as an input into its search ranking algorithm. &lt;/p&gt;

&lt;p&gt;We set out to see what it would take to score 100 on PageSpeed Insights on mobile. When we embarked on this effort, we already scored 100 on desktop, but modern commerce is mobile commerce, and there we only scored in the mid-60s. In this blog post, we share ways to get your site scoring 100 on mobile as well. Many companies claim 100 on desktop, but 100 on mobile is a bit of a unicorn. So let's dive in.&lt;/p&gt;

&lt;p&gt;Builder.io is a standard Next.js site. Because the site itself is running on the Builder content platform, the content already adheres to all of the best practices for image sizes, preloading, etc. Yet, it still only scored in the 60s. Why?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiy8vyp90ed82l4kmhshx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiy8vyp90ed82l4kmhshx.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It helps to look at the breakdown which makes up the score.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faeaoni0mhgjyttr3utm5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faeaoni0mhgjyttr3utm5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem can be broken down to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TBT/TTI: The JavaScript is causing too much blocking time on the page.&lt;/li&gt;
&lt;li&gt;FCP/LCP: The page has too much content to render for mobile browsers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So we should aim to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Decrease the amount of JavaScript.&lt;/li&gt;
&lt;li&gt;Decrease the amount of content for the initial render.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why so much JavaScript?
&lt;/h2&gt;

&lt;p&gt;Our homepage is essentially a static page. Why does it need JavaScript? Well, the homepage is a Next.js site, which means it is a React application (We use &lt;a href="https://github.com/BuilderIO/mitosis" rel="noopener noreferrer"&gt;Mitosis&lt;/a&gt; to convert the output of our drag and drop editor into React). While the vast majority of the site is static, there are three things that require JavaScript:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigation system: Menus require interactivity and hence JavaScript. Also, different menus are used for desktop and mobile devices. &lt;/li&gt;
&lt;li&gt;We need to load a chat widget&lt;/li&gt;
&lt;li&gt;We need Google analytics.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's dive into each one separately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application bootstrap
&lt;/h2&gt;

&lt;p&gt;Even though this is primarily a static site, it is still an application. To make the menus work, the application needs to be bootstrapped. Specifically, it needs to run rehydration where the framework compares the templates against the DOM and installs all of the DOM listeners. This process makes existing frameworks &lt;a href="https://dev.to/mhevery/a-first-look-at-qwik-the-html-first-framework-af"&gt;replayable&lt;/a&gt;. In other words, even though 95% of the page is static, the framework must download all of the templates and re-execute them to determine listeners' presence. The implication is that the site is downloaded twice, once as HTML and then again in the form of JSX in JavaScript. &lt;/p&gt;

&lt;p&gt;To make matters worse, the rehydration process is slow. The framework must visit each DOM node and reconcile it against the VDOM, which takes time. And the rehydration process can't be delayed, as it is the same process that installs DOM listeners. Delaying rehydration would mean that the menus would not work. &lt;/p&gt;

&lt;p&gt;What we are describing above is a fundamental limitation of every existing framework. You see, they are all &lt;a href="https://dev.to/mhevery/a-first-look-at-qwik-the-html-first-framework-af"&gt;replayable&lt;/a&gt;. This also means that no existing framework will allow you to score 100 on mobile on a real-world site. The amount of HTML and JavaScript is simply too great to fit into the tiny sliver that PageSpeed allots for it on mobile.&lt;/p&gt;

&lt;p&gt;We need to fundamentally rethink the problem. Since most of the site is static, we should not have to re-download that portion in JavaScript, or pay for rehydration of something we don't need. This is where &lt;a href="https://github.com/builderio/qwik" rel="noopener noreferrer"&gt;Qwik&lt;/a&gt; truly shines. Qwik is &lt;a href="https://dev.to/mhevery/a-first-look-at-qwik-the-html-first-framework-af"&gt;resumable not replayable&lt;/a&gt;, and that makes all the difference. As a result, Qwik does not need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Be bootstrapped on page load&lt;/li&gt;
&lt;li&gt;Walk the DOM to determine where the listeners are&lt;/li&gt;
&lt;li&gt;Eagerly download and execute JavaScript to make the menus work&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of the above means that there is practically no JavaScript to execute a site load, and yet we can retain all of the interactivity of the site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intercom
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8v1uurp49y7nlkh7fr3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8v1uurp49y7nlkh7fr3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Intercom is a third-party widget running on our site which allows us to interact with our customers. The standard way of installing it is to drop a piece of JavaScript into your HTML, like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;async=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://widget.intercom.io/widget/abcd1234"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;defer&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;Intercom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;boot&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;app_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abcd1234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;However, there are two issues with the above:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It adds JavaScript that needs to be downloaded and executed. This will count against our TBT/TTI.&lt;/li&gt;
&lt;li&gt;It may cause layout shifts, which counts against CLS. This is because the UI is first rendered without the widget and then again with it as the JavaScript is downloaded and executed. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Qwik solves both issues at the same time. &lt;/p&gt;

&lt;p&gt;First, it grabs the DOM that Intercom uses to render the widget. Next, the DOM is inserted into the actual page, like so: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"intercom-lightweight-app"&lt;/span&gt; &lt;span class="na"&gt;aria-live=&lt;/span&gt;&lt;span class="s"&gt;"polite"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"intercom-lightweight-app-launcher intercom-launcher"&lt;/span&gt;
    &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;
    &lt;span class="na"&gt;tabIndex=&lt;/span&gt;&lt;span class="s"&gt;{0}&lt;/span&gt;
    &lt;span class="na"&gt;arial-abel=&lt;/span&gt;&lt;span class="s"&gt;"Open Intercom Messenger"&lt;/span&gt;
    &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;'ui:boot_intercom'&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    ...
 &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"intercom-lightweight-app-style"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The benefit of this is that the widget renders instantly with the rest of the application. There is no delay or flicker while the browser downloads the Intercom JavaScript and executes the creation of the widget. The result is a better user experience and a faster bootstrap of the website. (It also saves bandwidth on mobile devices.)&lt;/p&gt;

&lt;p&gt;However, we still need a way to detect a click on the widget and some code to replace the mock widget with the actual Intercom widget when the user interacts with it. This is achieved with the &lt;code&gt;on:click="ui:boot_intercom"&lt;/code&gt; attribute. The attribute tells Qwik to download &lt;code&gt;boot_intercom.js&lt;/code&gt; if the user clicks on the mock widget.&lt;/p&gt;

&lt;p&gt;Content of: &lt;code&gt;boot_intercom.js&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://widget.intercom.io/widget/abcd1234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentElement&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;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentElement&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="nf"&gt;removeChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="nc"&gt;Intercom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;boot&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;app_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abcd1234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
 &lt;span class="nc"&gt;Intercom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;show&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;The file above downloads the real Intercom widget, removes the mock, and bootstraps Intercom. All of this happens naturally, without the user ever noticing the switcheroo. &lt;/p&gt;

&lt;h2&gt;
  
  
  Google Analytics
&lt;/h2&gt;

&lt;p&gt;So far, we have fought a good fight in delaying JavaScript and hence improving the website’s performance. Analytics is different, as we can't delay it and must bootstrap it immediately. Bootstrapping analytics alone would prevent us from scoring a 100 on PageSpeed Insights for mobile. To fix this, we will be running GoogleAnalytics in a Web Worker using &lt;a href="https://github.com/adamdbradley/partytown" rel="noopener noreferrer"&gt;PartyTown&lt;/a&gt;. More about this in a later post&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript delayed
&lt;/h2&gt;

&lt;p&gt;The work described above lowers the amount of JavaScript the website has to download and execute to about 1KB, which takes a mere 1ms to execute. Essentially, no time. Such a minimal amount of JavaScript is what allows us to score a perfect score on TBT/TTI.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTML delayed
&lt;/h2&gt;

&lt;p&gt;However, even with essentially no JavaScript we still can't score 100 for mobile if we don't fix the amount of HTML sentto the client for the above fold rendering. To improve FCP/LCP we simply must shrink that to a minimum. This is done by only sending the above the fold HTML.&lt;/p&gt;

&lt;p&gt;This is not a new idea, but it is tough to execute. Theexisting frameworks make this difficult, as there is no easy way to break up your application into pieces that are above and below the fold. VDOM does not help here because the application generates a whole VDOM, even if only a portion of it is projected. The framework would re-create the whole site on rehydration if part of it was missing,would resulting in even more work on the initial bootstrap. &lt;/p&gt;

&lt;p&gt;Ideally, we’d like to not ship the HTML that is below the fold, while  maintaining a fully interactive menu system above the fold. In practice, this is hard to do, as can be seen by the lack of such best practices in the wild. It’s too hard to do, so no one does it.&lt;/p&gt;

&lt;p&gt;Qwik is DOM-centric, which makes all the difference. The entire page is rendered on the server. Then, the portion of the page that does not need to be shipped is located and removed. As the user  scrolls, the missing portion is lazy downloaded and inserted. Qwik doesn’t mind these kind of DOM manipulations, because it is stateless and DOM-centric.&lt;/p&gt;

&lt;p&gt;Here is the actual code on our server that enables lazy loading of the site below the fold:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await &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;vmSandbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./server-index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ServerIndexModule&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;serverIndex&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lazyNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&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="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;section[lazyload=true]&lt;/span&gt;&lt;span class="dl"&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;lazyNode&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;lazyHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lazyNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;lazyNode&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="dl"&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;lazyNode&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;HTMLElement&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="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;999em&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;lazyNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;on:document:scroll&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="s1"&gt;ui:/lazy&lt;/span&gt;&lt;span class="dl"&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;transpiledEsmFiles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lazy.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
        export default (element) =&amp;gt; {
          element.removeAttribute('on:document:scroll');
          element.style.height = null;
          element.innerHTML = &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lazyHTML&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;;
        };`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="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;The code is simple and to the point, yet it would be difficult to achieve with any of the existing frameworks. &lt;/p&gt;

&lt;p&gt;Check out the below fold lazy loading in action:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F565yei3n8jydkkvs81yr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F565yei3n8jydkkvs81yr.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that the page first loads without content below the fold; as soon as the user scrolls, the content is populated. This populationis near-instant since there is no complex code to execute. Just a fast and straightforward &lt;code&gt;innerHTML&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it out
&lt;/h2&gt;

&lt;p&gt;Experience the page for yourself here: &lt;a href="https://www.builder.io/?render=qwik" rel="noopener noreferrer"&gt;https://www.builder.io/?render=qwik&lt;/a&gt;. (And see the score on &lt;a href="https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fwww.builder.io%2F%3Frender%3Dqwik" rel="noopener noreferrer"&gt;PageSpeed&lt;/a&gt;) We are still missing analytics, but that is coming soon. &lt;/p&gt;

&lt;p&gt;Like what you see? Our plan is to make Qwik available for every Builder.io customer, so that their sites are supercharged for speed out of the box. You have never seen a platform that is this fast before.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomha3jqf9hoh9l3vvcgn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomha3jqf9hoh9l3vvcgn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2rgulo7ew94yp06dyevs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2rgulo7ew94yp06dyevs.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fof1f2ztyoiodypiu6kxl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fof1f2ztyoiodypiu6kxl.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do you find the above exciting? Then &lt;a href="https://builder-io.rippling-ats.com" rel="noopener noreferrer"&gt;join our team&lt;/a&gt; and help us make the web fast!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Try it on &lt;a href="https://stackblitz.com/edit/qwik-todo-demo" rel="noopener noreferrer"&gt;StackBlitz&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Star us on &lt;a href="https://github.com/builderio/qwik" rel="noopener noreferrer"&gt;github.com/builderio/qwik&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Follow us on &lt;a href="https://twitter.com/QwikDev" rel="noopener noreferrer"&gt;@QwikDev&lt;/a&gt; and &lt;a href="https://twitter.com/builderio" rel="noopener noreferrer"&gt;@builderio&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Chat us on &lt;a href="https://discord.gg/JHVpZmqSs4" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Join &lt;a href="https://builder-io.rippling-ats.com/" rel="noopener noreferrer"&gt;builder.io&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>performance</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Qwik: the answer to optimal fine-grained lazy loading</title>
      <dc:creator>Miško Hevery</dc:creator>
      <pubDate>Mon, 02 Aug 2021 16:50:10 +0000</pubDate>
      <link>https://dev.to/builderio/qwik-the-answer-to-optimal-fine-grained-lazy-loading-2hdp</link>
      <guid>https://dev.to/builderio/qwik-the-answer-to-optimal-fine-grained-lazy-loading-2hdp</guid>
      <description>&lt;p&gt;Qwik aims to delay the loading and executing of JavaScript for as long as possible and to only do so upon user action, to deliver the fastest loads. This is done during the initial load, as well as during the whole application lifetime. Put differently, Qwik wants to have fine-grained lazy-loading. By "fine-grained," we mean that only the code that is directly required to process user action will be downloaded. In this post, we’ll explore the technical challenges that  need to be solved to achieve fine-grained lazy loading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serialize listeners
&lt;/h2&gt;

&lt;p&gt;The most obvious challenge to solve is the initial page load. We’ve already covered how to do this in &lt;a href="https://dev.to/mhevery/html-first-javascript-last-the-secret-to-web-speed-4ic9"&gt;HTML first, JavaScript last&lt;/a&gt;. The trick is to serialize event name and event action as URL into the DOM attribute. A top-level global event handler can then listen to events and download the code associated with the event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;"./MyComponent_onClick"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;click me&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code achieves that with no JavaScript (outside of a 1kb loader) loaded on the initial page load. This solves the initial time-to-interactive goal, but creates a new issue. We don't want to cause full application download and bootstrap on the first user interaction. Doing so would only move the problem from initial load to initial interaction. (If anything, this would worsen the situation, because it would introduce significant latency to first user interaction.) &lt;/p&gt;

&lt;p&gt;The solution is to ensure that no single user interaction causes a full application download or bootstrap. Instead, we only want to download and bootstrap/rehydrate the code/component which is directly needed to process the interactions. We want fine-grained lazy loading.&lt;/p&gt;

&lt;p&gt;Serializing events into HTML/DOM is what makes this all possible. Without it, it would be impossible to delay the template from loading, because the framework would need to download the template to identify where the events are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Asynchronous, out-of-order component hydration
&lt;/h2&gt;

&lt;p&gt;To ensure that the first interaction does not cause a full application download and bootstrap, it is necessary to rehydrate the components asynchronously and out of order.&lt;/p&gt;

&lt;p&gt;Here asynchronously means that the rendering system can pause rendering to asynchronously download a template for a component, and then continue the rendering process. This is in stark contrast to all of the existing frameworks, which have fully synchronous rendering pipelines. And because the rendering is synchronous, there is no place to insert asynchronous lazy-loading. The consequence  is that all of the templates need to be present ahead of call to render. &lt;/p&gt;

&lt;p&gt;Another issue with existing rehydration strategies is that they start at the root component and synchronously rehydrate all of the components below. The consequence is that all the components must be rehydrated at the same time, forcing the download of every component. This would cause an extended processing time for the first interaction. Out-of-order hydration means that each component can be rehydrated independently from any other component and in any order. This allows Qwik to only rehydrate the minimum number of components that are needed to process the request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;decl:template=&lt;/span&gt;&lt;span class="s"&gt;"./path/MyComponent_template"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ... some content ...
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above case, &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; represents a component associated with &lt;code&gt;MyComponent_template.ts&lt;/code&gt;. Qwik will only download the template if it determines that the component needs to be rerendered, thus further delaying its download. &lt;/p&gt;

&lt;p&gt;Without out-of-order rehydration, the framework is forced to download all the templates and rehydrate them all at once. This would create large download and execution pressure on the first interaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separation of rendering from event handlers
&lt;/h2&gt;

&lt;p&gt;An essential consideration for Qwik is that all of the existing rendering systems inline event listeners into the template. The consequence of the above is that when a component needs to be rerendered (or rehydrated) the browser must also download all of the listeners, regardless of if they are required. The listeners often close over complex code, which further increases the amount of code that is downloaded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;complexFunction&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;./large-dependency&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onclick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;complexFunction&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;rarely&lt;/span&gt; &lt;span class="nx"&gt;clicked&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;click&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="nx"&gt;downloaded&lt;/span&gt; &lt;span class="nx"&gt;eagerly&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&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;Qwik separates the event handles from the template code. This means that either the listeners or template can be downloaded independently, and on an as-needed basis. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;MyComponent_template.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;MyComponent_template&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./MyComponent_onClick&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;rarely&lt;/span&gt; &lt;span class="nx"&gt;clicked&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;click&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="nx"&gt;downloaded&lt;/span&gt; &lt;span class="nx"&gt;lazily&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;MyComponent_onClick.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;complexFunction&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;./large-dependency&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;complexFunction&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;Without the separation of event handlers from the templates, the framework would have to download a lot more code than required to rerender the component. Plus event handlers are often complex and have other dependencies, which adds to the amount of code that needs to be downloaded. &lt;/p&gt;

&lt;h2&gt;
  
  
  Serialization of component state
&lt;/h2&gt;

&lt;p&gt;When a component gets rehydrated, an essential part of the process is to restore the component's state. Existing frameworks don't have a way to serialize the state, as there is no standard way to demarcate where the component's state is.&lt;/p&gt;

&lt;p&gt;Qwik breaks components up into several pieces.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;props&lt;/em&gt;: These are just properties of the components that are reflected in the DOM. For example: &lt;code&gt;&amp;lt;counter min="0" max="100"/&amp;gt;&lt;/code&gt; the props are &lt;code&gt;{min: 0, max: 100}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;state&lt;/em&gt;: Internal state of the component, which can be serialized into the DOM.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;transient state&lt;/em&gt;: Any additional state that component may cache, but which cannot be serialized. This information needs to be recomputed (e.g. temporary promises while the component is talking to the server).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;decl:template=&lt;/span&gt;&lt;span class="s"&gt;"./Conter_template"&lt;/span&gt;
     &lt;span class="na"&gt;:.=&lt;/span&gt;&lt;span class="s"&gt;'{count: 42}'&lt;/span&gt;
     &lt;span class="na"&gt;min=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;max=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;"./Counter_incremente"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;+&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  42
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;"./Counter_decrement"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;+&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the component can’t serialize its state, it won’t be possible to rehydrate the specific component in isolation. (Where would the component get its state?) As a result,  the framework would have to download extra code to compute or download the state from the server. Qwik avoids all of this by &lt;a href="https://dev.to/mhevery/html-first-javascript-last-the-secret-to-web-speed-4ic9"&gt;serializing state in the DOM&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serialization of app/shared state
&lt;/h2&gt;

&lt;p&gt;In addition to the component state, which is private to the component, the application state is also shared between components. It, too, needs to be serialized into the DOM. The shared state is broken down to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;key&lt;/em&gt;: An ID that uniquely identifies a piece of state. The ID is then used as a reference it in the components.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;state&lt;/em&gt;: Shared state between the components which can be serialized into the DOM.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;transient state&lt;/em&gt;: Any additional state that applications may cache, but can't be serialized. This information needs to be able to be recomputed.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;:cart:=&lt;/span&gt;&lt;span class="s"&gt;"./Cart"&lt;/span&gt;
     &lt;span class="na"&gt;cart:432=&lt;/span&gt;&lt;span class="s"&gt;"{items: ['item:789', 'item:987']}"&lt;/span&gt;
     &lt;span class="na"&gt;:item:=&lt;/span&gt;&lt;span class="s"&gt;"./Item"&lt;/span&gt;
     &lt;span class="na"&gt;item:789=&lt;/span&gt;&lt;span class="s"&gt;"{name: 'Shoe' price: '43.21'}"&lt;/span&gt;
     &lt;span class="na"&gt;item:987=&lt;/span&gt;&lt;span class="s"&gt;"{name: 'Sock' price: '12.34'}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ...
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Serializing the application’s state allows the components to render the same information in multiple locations, and communicate with other components. Without the framework understanding and managing the shared state, it would not be possible to hydrate components independently because the framework would not know when the state changes. (For example, Angular and React don't have explicit state management tied to the render function. As a result, the only sensible thing to do when the application state changes is to rerender the entire application, which prevents fine-grained lazy-loading.) &lt;/p&gt;

&lt;h2&gt;
  
  
  Reactive connections between app state and components
&lt;/h2&gt;

&lt;p&gt;The real benefit of having a framework that understands the state is that the framework knows the relationship between state and components. This is important because it tells the framework which component needs to be rehydrated when a given state changes. Or more importantly, it tells the framework which components don't need to be rehydrated when a state changes. For example, adding an item to a shopping cart should only rerender the component that displays the shopping cart count, which is only a tiny portion of the overall page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;:cart:=&lt;/span&gt;&lt;span class="s"&gt;"./Cart"&lt;/span&gt;
     &lt;span class="na"&gt;cart:432=&lt;/span&gt;&lt;span class="s"&gt;"{items: ['item:789', 'item:987']}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;decl:template=&lt;/span&gt;&lt;span class="s"&gt;"./Unrelated"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;decl:template=&lt;/span&gt;&lt;span class="s"&gt;"./ShoppingCart"&lt;/span&gt;
       &lt;span class="na"&gt;bind:cart:432=&lt;/span&gt;&lt;span class="s"&gt;"$cart"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   2 items
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;"./AddItem"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;buy&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal of Qwik is to rehyrate the minimum number of components. When the user clicks on the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; Qwik will download &lt;code&gt;./AddItem&lt;/code&gt;, updating the &lt;code&gt;cart:432&lt;/code&gt; application state. Qwik will then determine that a component with &lt;code&gt;bind:cart:432&lt;/code&gt; is the only component that uses the state, and therefore the only component which needs to be rehydrated and rerendered. Qwik can prune most of the components on the page, allowing it to keep the lazy-loading fine-grained. Knowing which components are connected to which state is a critical property that is not present in other frameworks. It is the property that allows for fine-grained lazy loading during application startup, as well as throughout its lifetime. &lt;/p&gt;

&lt;h2&gt;
  
  
  Component isolation
&lt;/h2&gt;

&lt;p&gt;So far, we have discussed how Qwik supports fine-grained lazy loading of code. All of the above works because Qwik understands the data flow in the application. Qwik uses this information to prune the components that do not need to be rehydrated and only rehydrate the necessary components. The implication is that the components must not talk to other components without Qwik's knowledge. Components can't have secret conversations with other components. &lt;/p&gt;

&lt;p&gt;If the components get a hold of state without Qwik's knowledge, Qwik would not know that the component needs to be rehydrated/rerendered when the state changes. This is why components need to list their dependencies in the component's properties explicitly.&lt;/p&gt;

&lt;p&gt;Without explicit listing, the framework would have no choice but to rerender everything once the state changes. This would cause the whole application to be downloaded and boottraped.&lt;/p&gt;

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

&lt;p&gt;There are many ways in which the approach to building web applications needs to change to structure it for lazy loading. The issue is that the current frameworks do not help with this problem, and sometimes they even make it worse (for example, forcing full-page rehydration, synchronous rendering, etc.). Qwik makes fine-grained lazy loading a reality, so that developers can build sites/apps that load in sub-seconds, no matter how large and complex they become. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Try it on &lt;a href="https://stackblitz.com/edit/qwik-todo-demo"&gt;StackBlitz&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Star us on &lt;a href="https://github.com/builderio/qwik"&gt;github.com/builderio/qwik&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Follow us on &lt;a href="https://twitter.com/QwikDev"&gt;@QwikDev&lt;/a&gt; and &lt;a href="https://twitter.com/builderio"&gt;@builderio&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Chat us on &lt;a href="https://discord.gg/JHVpZmqSs4"&gt;Discord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Join &lt;a href="https://builder-io.rippling-ats.com/"&gt;builder.io&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>performance</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>HTML-first, JavaScript last: the secret to web speed!</title>
      <dc:creator>Miško Hevery</dc:creator>
      <pubDate>Wed, 14 Jul 2021 22:17:40 +0000</pubDate>
      <link>https://dev.to/builderio/html-first-javascript-last-the-secret-to-web-speed-4ic9</link>
      <guid>https://dev.to/builderio/html-first-javascript-last-the-secret-to-web-speed-4ic9</guid>
      <description>&lt;p&gt;All frameworks need to keep state. Frameworks build up the state by executing the templates. Most frameworks keep this state in the JavaScript heap in the form of references and closures. What is unique about &lt;a href="https://github.com/builderio/qwik" rel="noopener noreferrer"&gt;Qwik&lt;/a&gt; is that the state is kept in the DOM in the form of attributes. (Note that neither references nor closures are wire serializable, but DOM attributes, which are strings, are. This is key for resumability!)&lt;/p&gt;

&lt;p&gt;The consequences of keeping state in the DOM have many unique benefits, including:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;DOM has HTML as its serialization format. By keeping state in the DOM in the form of string attributes, the application can be serialized into HTML at any point. The HTML can be sent over the wire and deserialized to DOM on a different client. The deserialized DOM can then be resumed.&lt;/li&gt;
&lt;li&gt;Each component can be resumed independently from any other component. This out-of-order rehydration allows only a subset of the whole application to be rehydrated and limits the amount of code that needs to be downloaded as a response to user action. This is quite different from traditional frameworks.&lt;/li&gt;
&lt;li&gt;Qwik is a stateless framework (all application states are in DOM in the form of strings). Stateless code is easy to serialize, ship over the wire, and resume. It is also what allows components to be rehydrated independently from each other. &lt;/li&gt;
&lt;li&gt;The application can be serialized at any point in time (not just on initial render), and many times over.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's look at a simple &lt;code&gt;Counter&lt;/code&gt; component example, and how state serialization works. (Note that this is the output of the server-side rendered HTML, not necessarily specific code developers would be hand-coding.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;::app-state=&lt;/span&gt;&lt;span class="s"&gt;"./AppState"&lt;/span&gt; 
     &lt;span class="na"&gt;app-state:1234=&lt;/span&gt;&lt;span class="s"&gt;"{count: 321}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;decl:template=&lt;/span&gt;&lt;span class="s"&gt;"./Counter_template"&lt;/span&gt;
       &lt;span class="na"&gt;on:q-render=&lt;/span&gt;&lt;span class="s"&gt;"./Counter_template"&lt;/span&gt;
       &lt;span class="na"&gt;::.=&lt;/span&gt;&lt;span class="s"&gt;"{countStep: 5}"&lt;/span&gt;
       &lt;span class="na"&gt;bind:app-state=&lt;/span&gt;&lt;span class="s"&gt;"state:1234"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;"./MyComponent_increment"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;+5&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    321.
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;"./MyComponent_decrrement"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;-5&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;::app-state&lt;/code&gt; (application state code): Points to a URL where the application state mutation code can be downloaded. The state update code is only downloaded if a state needs to be mutated.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app-state:1234&lt;/code&gt; (application state instance): A pointer to a specific application instance. By serializing the state, the application can resume where it left off, rather than replaying the rebuilding of the state.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;decl:template&lt;/code&gt; (declare template): Points to a URL where the component template can be downloaded. The component template is not downloaded until Qwik determines that the component's state has changed, and needs to be rerendered. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;on:q-render&lt;/code&gt; (component is scheduled for rendering): Frameworks need to keep track of which components need to be rerendered. This is usually done by storing an internal list of invalidated components. With Qwik, the list of invalidated components is stored in the DOM in the form of attributes. The components are then waiting for the &lt;code&gt;q-render&lt;/code&gt; event to broadcast. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;::.="{countStep: 5}"&lt;/code&gt; (Internal state of component instance): A component may need to keep its internal state after rehydration. It can keep the state in the DOM. When the component is rehydrated it has all of the state it needs to continue. It does not need to rebuild its state.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bind:app-state="state:1234"&lt;/code&gt; (a reference to shared application state): This allows multiple components to refer to the same shared application state. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;querySelectorAll&lt;/code&gt; is our friend
&lt;/h2&gt;

&lt;p&gt;A common thing that a framework needs to do is to identify which components need to be rerendered when the state of the application changes. This can happen as a result of several reasons, such as a component has been invalidated explicitly (&lt;code&gt;markDirty()&lt;/code&gt;), or because a component is invalidated implicitly because the application shared state has changed. &lt;/p&gt;

&lt;p&gt;In the example above, the &lt;code&gt;count&lt;/code&gt; is kept in the application state under the key &lt;code&gt;app-state:1234&lt;/code&gt;. If the state is updated it is necessary to invalidate (queue for rerender) the components that depend on that application state. How should the framework know which components to update?&lt;/p&gt;

&lt;p&gt;In most frameworks the answer is to just rerender the whole application, starting from the root component. This strategy has the unfortunate consequence that all the component templates need to be downloaded, which negatively affects latency on user interaction.&lt;/p&gt;

&lt;p&gt;Some frameworks are reactive and keep track of the component that should be rerendered when a given state changes. However, this book-keeping is in the form of closures (see &lt;a href="https://dev.to/mhevery/death-by-closure-and-how-qwik-solves-it-44jj"&gt;Death By Closure&lt;/a&gt;) which close over the templates. The consequence is that all the templates need to be downloaded at the application bootstrap when the reactive connections are initialized.  &lt;/p&gt;

&lt;p&gt;Qwik is component-level reactive. Because it is reactive, it does not need to render starting at the root. However, instead of keeping the reactive listeners in the form of closures, it keeps them in the DOM in the form of attributes, which allows Qwik to be resumable. &lt;/p&gt;

&lt;p&gt;If &lt;code&gt;count&lt;/code&gt; gets updated, Qwik can internally determine which components need to be invalidated by executing this &lt;code&gt;querySelectorAll&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bind&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;:app-state&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;:1234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;markDirty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above query allows Qwik to determine which components depend on the state, and for each component it invokes &lt;code&gt;markDirty()&lt;/code&gt; on it. &lt;code&gt;markDirty()&lt;/code&gt; invalidates the component and adds it to a queue of components which need to be rerendered. This is done to coalesce multiple &lt;code&gt;markDirity&lt;/code&gt; invocations into a single rendering pass. The rendering pass is scheduled using &lt;code&gt;requestAnimationFrame&lt;/code&gt;. But, unlike most frameworks, Qwik keeps this queue in the DOM in the form of the attribute as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;on:q-render=&lt;/span&gt;&lt;span class="s"&gt;"./Counter_template"&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;requestAnimationFrame&lt;/code&gt; is used to schedule rendering. Logically, this means that &lt;code&gt;requestAnimationFrame&lt;/code&gt; broadcasts the &lt;code&gt;q-render&lt;/code&gt; event which the component is waiting on. Again &lt;code&gt;querySelectorAll&lt;/code&gt; comes to the rescue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;on&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;:q-render&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsxRender&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Browsers do not have broadcast events (reverse of event bubbling), but &lt;code&gt;querySelectorAll&lt;/code&gt; can be used to identify all the components which should receive the event broadcast. &lt;code&gt;jsxRender&lt;/code&gt; function is then used to rerender the UI. &lt;/p&gt;

&lt;p&gt;Notice that at no point does Qwik need to keep state outside of what is in the DOM. Any state is stored in the DOM in the form of attributes, which are automatically serialized into HTML. In other words, at any time the application can be snapshot into HTML, sent over the wire, and deserialized. The application will automatically resume where it left off. &lt;/p&gt;

&lt;p&gt;Qwik is stateless, and it is this that makes Qwik applications resumable. &lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits
&lt;/h2&gt;

&lt;p&gt;Resumability of applications is the obvious benefit of storing all framework state in DOM elements. However, there are other benefits which may not be obvious at first glance.&lt;/p&gt;

&lt;p&gt;Skipping rendering for components which are outside of the visible viewport. When a &lt;code&gt;q-render&lt;/code&gt; event is broadcast to determine if the component needs to be rendered, it is easy to determine if the component is visible and simply skip the rendering for that component. Skipping the rendering also means that no template, or any other code, is required to be downloaded.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl7y32eh60iarvc277zl9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl7y32eh60iarvc277zl9.png" alt="Qwik Performance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another benefit of statelessness is that HTML can be lazy loaded as the application is already running. For example, the server can send the HTML for rendering the initial view, but skip the HTML for the view which is not visible. The user can start interacting with the initial view and use the application. As soon as the user starts scrolling the application can fetch more HTML and &lt;code&gt;innerHTML&lt;/code&gt; it at the end of the DOM. Because Qwik is stateless, the additional HTML can be just inserted without causing any issues to the already running application. Qwik does not know about the new HTML until someone interacts with it, and only then it gets lazy hydrated. The use case described above is very difficult to do with the current generation of frameworks.&lt;/p&gt;

&lt;p&gt;We are very excited about the future of Qwik, and the kind of use cases that it opens up.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Try it on &lt;a href="https://stackblitz.com/edit/qwik-todo-demo" rel="noopener noreferrer"&gt;StackBlitz&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Star us on &lt;a href="https://github.com/builderio/qwik" rel="noopener noreferrer"&gt;github.com/builderio/qwik&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Follow us on &lt;a href="https://twitter.com/QwikDev" rel="noopener noreferrer"&gt;@QwikDev&lt;/a&gt; and &lt;a href="https://twitter.com/builderio" rel="noopener noreferrer"&gt;@builderio&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Chat us on &lt;a href="https://discord.gg/JHVpZmqSs4" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Join &lt;a href="https://builder-io.rippling-ats.com/" rel="noopener noreferrer"&gt;builder.io&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it for now, but stay tuned as we continue to write about Qwik and the future of frontend frameworks in the coming weeks!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>frameworks</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
