<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ web performance - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ web performance - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 22:24:40 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/web-performance/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Reduce Round Trip Time (RTT) with Next.js ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever wondered why some websites load almost immediately and others leave you looking at a blank screen, even when your internet connection is fast? In some cases, your internet speed may not be the issue. It is usually because of Round Trip ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-reduce-round-trip-time-rtt-with-nextjs/</link>
                <guid isPermaLink="false">690c78446959d1f714d81d45</guid>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chukwudi Nweze ]]>
                </dc:creator>
                <pubDate>Thu, 06 Nov 2025 10:28:20 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1762424304223/4d818ff7-0fe2-448d-8acd-3da092bc55a4.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever wondered why some websites load almost immediately and others leave you looking at a blank screen, even when your internet connection is fast? In some cases, your internet speed may not be the issue. It is usually because of Round Trip Time (RTT), which is how long it takes your browser to send a request to a server and get a response.</p>
<p>The internet depends on physical infrastructure: fiber-optic cables, satellites, and data centers often located thousands of kilometers away. Network requests travel at high speed, but they are still limited by the speed of light (around 300,000 km/s). For instance, a network request from Lagos, Nigeria to a server in San Francisco, USA travels more than 12,000 km, and takes about 150–200 milliseconds for a single round trip under ideal conditions. Multiply that by the 20–30 requests a typical web page makes (for HTML, CSS, images, APIs and more), and those milliseconds quickly add up to seconds of delay before a page fully loads.</p>
<p>In this article, we’ll explain in detail what Round Trip Time(RTT) is, why it is one of the most overlooked factors in web performance, and how you can use Next.js to minimize the number of RTTs to make your applications feel fast and responsive. You will learn how features like Server-Side Rendering (SSR), React Server Components (RSC), image optimization, and caching all work together to reduce Round Trip Time in a web page.</p>
<h2 id="heading-what-you-will-learn"><strong>What You will Learn</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-you-will-learn">What You will Learn</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-round-trip-time-rtt">What is Round Trip Time (RTT)?</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-how-distance-increases-round-trip-time">How Distance Increases Round Trip Time</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-round-trip-time-affects-web-performance">How Round Trip Time Affects Web Performance</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-why-client-side-rendering-feels-slower">Why Client-Side Rendering Feels Slower</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-reduce-round-trip-time-with-nextjs">How to Reduce Round Trip Time with Next.js</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-server-side-rendering-ssr">Server-Side Rendering (SSR)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-react-server-components-rsc">React Server Components (RSC)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-image-optimization">Image Optimization</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-caching-and-static-rendering">Caching and Static Rendering</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-trade-offs-across-nextjs-rendering-methods">Trade-offs Across Next.js Rendering Methods</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-when-to-use-each-rendering-method">When to Use Each Rendering Method</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-round-trip-time-rtt">What is Round Trip Time (RTT)?</h2>
<p>When you visit a website, the browser makes a network request to a server. The server processes the request and then sends a response back. The Round Trip Time is the complete duration of this journey in milliseconds, which includes:</p>
<ol>
<li><p><strong>Travel Time</strong>: The amount of time it took the network request to get to the server.</p>
</li>
<li><p><strong>Processing Time</strong>: The amount of time the server took to process the request.</p>
</li>
<li><p><strong>Return Time</strong>: The amount of time it took the response get back to the browser.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761405949671/1ceaadf4-5576-41ae-9f25-e846f41b3e67.png" alt="An illustration showing round-trip time (RTT) communication between a client and a server, where the client request takes about 100 ms to reach the server, and the server response takes about 200 ms to return to the client" class="image--center mx-auto" width="990" height="286" loading="lazy"></p>
<h3 id="heading-how-distance-increases-round-trip-time">How Distance Increases Round Trip Time</h3>
<p>Round Trip Time depends heavily on the physical distance between the client and server. For example:</p>
<ul>
<li><p>A user in Lagos, Nigeria making a network request to a server in London that is about 5,000 km away might see a round trip time of 100–150 ms.</p>
</li>
<li><p>A server in San Francisco that is about 12,000 km could push the roundtrip time to 200–300 ms. The farther the server, the higher the round trip time.</p>
</li>
</ul>
<h2 id="heading-how-round-trip-time-affects-web-performance">How Round Trip Time Affects Web Performance</h2>
<p>Modern web pages make multiple network requests to load completely. Imagine loading an e-commerce product page that requires:</p>
<ul>
<li><p>1 network request for HTML (about 200 ms)</p>
</li>
<li><p>5 network requests for CSS/JavaScript (about 1,000 ms)</p>
</li>
<li><p>10 network requests for images (about 2,000 ms)</p>
</li>
<li><p>4 network requests for product data via API (about 800 ms)</p>
</li>
</ul>
<p>That shows that the product page will take 20 network requests to fully load, which is about 4 seconds of network delay.</p>
<p>The probability of bounce increases 32% as page load time goes from 1 second to 3 seconds (<a target="_blank" href="https://www.thinkwithgoogle.com/marketing-strategies/app-and-mobile/page-load-time-statistics/">Google/SOASTA Research, 2017</a>). That means about one-third of visitors leave before the page even loads.</p>
<h3 id="heading-why-client-side-rendering-feels-slower">Why Client-Side Rendering Feels Slower</h3>
<p>In client side rendering applications, each request adds a round trip time, and traditional client-side rendering (CSR) in React apps increases this:</p>
<ul>
<li><p>The browser downloads a minimal HTML shell and a large JavaScript bundle.</p>
</li>
<li><p>The JavaScript runs to fetch data and render the UI, requiring additional network requests.</p>
</li>
<li><p>Each API call adds another RTT, delaying the First Contentful Paint (FCP).</p>
</li>
</ul>
<p>First Contentful Paint (FCP) measures the time from when the user first navigated to the page to when any part of the page's content such as text, images,<code>&lt;svg&gt;</code> or <code>&lt;canvas&gt;</code> elements is rendered on the screen.</p>
<p>In CSR apps, FCP is delayed because the browser cannot display any meaningful content until JavaScript has finished loading, parsing, and executing the code needed to construct the UI. A regular CSR application may need 5 to 10 network round trips to get all the resources needed for the rendering of the UI, which can easily add several seconds of delay.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// pages/index.js (CSR)</span>
<span class="hljs-keyword">import</span> { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [products, setProducts] = useState([])

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Fetch data after page loads</span>
    fetch(<span class="hljs-string">"https://api.example.com/products"</span>)
      .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> res.json())
      .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> setProducts(data))
  }, [])

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Products<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      {products.length ? (
        products.map((product) =&gt; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{product.id}</span>&gt;</span>{product.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>)
      ) : (
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
</code></pre>
<p>In the code above, when the <code>Home</code> component mounts, it initializes the state as an empty array. The <code>useEffect</code> hook then runs once to make an API request. While the request is in progress, the “Loading...” message is displayed on the screen. Once the request completes successfully, React updates the state with the fetched data and re-renders the UI to display the products. This process introduces an extra round trip, which further delays the FCP.</p>
<h2 id="heading-how-to-reduce-round-trip-time-with-nextjs">How to Reduce Round Trip Time with Next.js</h2>
<p>You cannot eliminate round trip time completely. Data must still travel over the network. What Next.js does is to reduce how often those network requests happen and how much data each request carries. It does this through a number of techniques, such as <strong>Server-Side Rendering (SSR)</strong>, <strong>React Server Components (RSC)</strong>, <strong>image optimization</strong>, and <strong>caching or static rendering</strong>.</p>
<h3 id="heading-server-side-rendering-ssr">Server-Side Rendering (SSR)</h3>
<p>Unlike traditional React.js applications, where the browser handles the majority of the work, such as fetching static files, JavaScript, and data required to render a page, the server generates the whole HTML, fetches the data, renders the page, and sends it to the browser in a single round trip time.</p>
<p><strong>Advantages:</strong></p>
<ul>
<li><p><strong>Fewer Round Trips:</strong> Since data fetching and rendering take place on the server, the browser receives a ready-to-display page in one round trip time.</p>
</li>
<li><p><strong>Improved First Contentful Paint:</strong> Low round trip time means content displays on the page almost immediately.</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// pages/index.js (SSR)</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getServerSideProps</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Fetch data on the server</span>
  <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://api.example.com/products'</span>);
  <span class="hljs-keyword">const</span> products = <span class="hljs-keyword">await</span> res.json();

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">props</span>: { products }, <span class="hljs-comment">// Pass data to the page</span>
  };
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params">{ products }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Products<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      {products.map((product) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{product.id}</span>&gt;</span>{product.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>In the code above, <code>getServerSideProps</code> runs entirely on the server. When a user visits or refreshes the page, <code>getServerSideProps()</code> is called to fetch product data from the external API. The fetched data is then pre-rendered on the server, meaning the list of products is included in the HTML before it is sent to the browser to display. This removes the additional round trip seen in CSR and improves the FCP, since users see meaningful content as soon as the page loads.</p>
<h3 id="heading-react-server-components-rsc">React Server Components (RSC)</h3>
<p>Server-Side Rendering is a technique where the whole page gets generated on the server. But imagine if only some portions of a page are to be rendered on the server while others are to be rendered on the client?  </p>
<p>React Server Components allow partition of rendering between the server and the client.  </p>
<p>For example, a <code>ProductList</code> component can be rendered on the server, while a <code>SearchInput</code> component renders on the client to manage user interactions.  </p>
<p><strong>Advantages:</strong><br>RSC reduces the overall round trip time (RTT) and also increases the page first contentful paint.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// app/ProductList.jsx (Server Component)</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ProductList</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Fetch data on the server</span>
  <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://api.example.com/products'</span>);
  <span class="hljs-keyword">const</span> products = <span class="hljs-keyword">await</span> res.json();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Products<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      {products.map((product) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{product.id}</span>&gt;</span>{product.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      ))}
      <span class="hljs-tag">&lt;<span class="hljs-name">ClientSearch</span> /&gt;</span> {/* Client Component */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ProductList;
</code></pre>
<p>In the code above, <code>ProductList</code> is a server component with a <code>ClientSeacrch</code> component as a child component. The <code>ClientSearch</code> renders in the browser while the rest of the <code>ProductList</code> renders on the server. When the page loads, the server runs <code>fetch()</code> to retrieve product data and renders the complete HTML for the product list on the server while <code>ClientSearch</code> renders on the client side to handle user interactions.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// components/ClientSearch.jsx (Client Component)</span>
<span class="hljs-string">'use client'</span>;

<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ClientSearch</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [query, setQuery] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
      <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
      <span class="hljs-attr">value</span>=<span class="hljs-string">{query}</span>
      <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setQuery(e.target.value)}
      placeholder="Search products..."
    /&gt;</span>
  );
}
</code></pre>
<p>The <code>ClientSearch</code> component above handles user interactions, such as updating the search input with <code>useState</code>. It’s marked with <code>'use client'</code>, so it runs entirely in the client side.</p>
<h3 id="heading-image-optimization">Image Optimization</h3>
<p>Images negatively impact round-trip time RTT when they are unoptimized, as larger files take a longer time to transfer from the server to the browser.</p>
<p>Next.js Image component optimizes images automatically:</p>
<p><strong>Resizing</strong>: It adjusts image size based on the user’s device.</p>
<p><strong>Compression</strong>: It uses new formats like WebP to shrink the file size significantly.</p>
<p><strong>Lazy Loading</strong>: Loads images only when they enter the user’s viewport, which reduces the number of initial requests.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// pages/index.js</span>
<span class="hljs-keyword">import</span> Image <span class="hljs-keyword">from</span> <span class="hljs-string">'next/image'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Welcome to Our Store<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Image</span>
        <span class="hljs-attr">src</span>=<span class="hljs-string">"/product.jpg"</span>
        <span class="hljs-attr">alt</span>=<span class="hljs-string">"Product Image"</span>
        <span class="hljs-attr">width</span>=<span class="hljs-string">{500}</span>
        <span class="hljs-attr">height</span>=<span class="hljs-string">{300}</span>
      /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>In the code above, the page uses Next.js built-in <code>Image</code> component to render an optimized image. When the page loads, Next.js optimizes the image resizing, lazy loading, and so on. This means the browser will only download the right image size for the device.</p>
<h3 id="heading-caching-and-static-rendering">Caching and Static Rendering</h3>
<p>With SSR and Server Component, round trip time can still remain high if the server has to process data on every request. Next.js solves this problem with Static Site Generation (SSG) and Incremental Static Regeneration (ISR).  </p>
<p>Here’s how it works:  </p>
<p><strong>Static Site Generation</strong>: Pages are pre-rendered during build time, cached and delivered as static HTML from a CDN.  </p>
<p><strong>Incremental Static Regeneration</strong>: Pages are pre-rendered but can be re-generated in the background after an interval, for example, every 60 seconds.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// app/page.jsx</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> revalidate = <span class="hljs-number">60</span>; <span class="hljs-comment">// Regenerate the page every 60 seconds</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Fetch data on the server</span>
  <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"https://api.example.com/products"</span>, {
    <span class="hljs-attr">next</span>: { <span class="hljs-attr">revalidate</span>: <span class="hljs-number">60</span> }, 
  });
  <span class="hljs-keyword">const</span> products = <span class="hljs-keyword">await</span> res.json();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Products<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      {products.map((product) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{product.id}</span>&gt;</span>{product.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>In the code above, the page uses Incremental Static Regeneration (ISR). The <code>revalidate = 60</code> option is to regenerate the page every 60 seconds. When a user visits the page, the server serves the pre-rendered HTML instantly. The <code>next: { revalidate: 60 }</code> inside the <code>fetch()</code> means that data is cached for 60 seconds. After 60 seconds, the next request will trigger the server to regenerate a fresh data.</p>
<h2 id="heading-trade-offs-across-nextjs-rendering-methods">Trade-offs Across Next.js Rendering Methods</h2>
<p>With <strong>Server-Side Rendering (SSR)</strong>, the browser gets the complete rendered page in only one round round trip. On the other hand, this can also lead to increased server load and a high TTFB. The TTFB (Time to First Byte) is the duration it takes for a user to see the content displayed on their browser.</p>
<p>With <strong>Incremental Static Regeneration (ISR)</strong>, the page is pre-rendered and cached, thus getting an instantaneous response from the server. The page will be re-generated depending on a fixed period (such as every 60 seconds). The downside of this method is that users might see old content before it gets updated.</p>
<p>In <strong>Server Components</strong>, rendering takes place on the server, and only interactive parts are managed on the client. With this, server-side rendering are still maintained while still allowing client interactions. The only drawback is that developers need to be very particular while deciding what to run on the server and what to run on the client.</p>
<h2 id="heading-when-to-use-each-rendering-method">When to Use Each Rendering Method</h2>
<p><strong>Server-Side Rendering (SSR)</strong> should be applied to pages that updates frequently, such as dashboards, user profiles, and so on. SSR guarantee users to always see the latest data.  </p>
<p>As for <strong>Incremental Static Regeneration (ISR)</strong>, it should be applied to pages with infrequent changes, for instance, product listings, marketing pages, or blogs.  </p>
<p>Use <strong>Server Components</strong> when you want part of the page to render on the server while some sections run on the client. For instance, pages that need user interaction like search inputs or filters, while data fetching and rendering takes place on the server.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Round Trip Time (RTT) is one of the hidden factors behind slow page loads. Each network request adds a round trip, and these network delays build up as the browser fetches several resources like scripts, images, and data files. Next.js deals with this issue by minimizing the number of network requests that need to be done before the first content paint.</p>
<ul>
<li><p><strong>Server-Side Rendering (SSR)</strong> and <strong>React Server Components (RSC)</strong> shift data fetching and rendering to the server, which reduces client-side requests.</p>
</li>
<li><p><strong>Image optimization</strong> reduces image size and uses CDNs to deliver content faster from nearby servers.</p>
</li>
<li><p><strong>Caching and static rendering</strong> serve pre-generated pages instantly without further processing from the server.</p>
</li>
</ul>
<p>With these techniques, you can build web applications that load faster and feel more responsive, even for users who are far from your origin server or are on slower networks.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Optimize Next.js Web Apps for Better Performance ]]>
                </title>
                <description>
                    <![CDATA[ As engineers, we often get so carried away with other aspects of development that we overlook how users perceive and interact with our applications. This oversight can result in users leaving the app almost as soon as they arrive, leading to higher b... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/optimize-nextjs-web-apps-for-better-performance/</link>
                <guid isPermaLink="false">6776a323218b455d646035b2</guid>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Performance Optimization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ayantunji Timilehin ]]>
                </dc:creator>
                <pubDate>Thu, 02 Jan 2025 14:30:59 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735828217839/b65374be-d891-4f19-a359-f84f2ac8f3b9.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As engineers, we often get so carried away with other aspects of development that we overlook how users perceive and interact with our applications. This oversight can result in users leaving the app almost as soon as they arrive, leading to higher bounce rates and minimal engagement.</p>
<p>At its core, every business thrives on delivering value to its users. When users are unable to access this value due to poor performance, it ultimately impacts the business's success. Slow load times, among other factors, frustrate users and drive them away before they even get a chance to engage.</p>
<p>Optimizing performance is more than just a technical detail – it’s also a critical part of creating a successful application. Without it, even the best features can go unnoticed if users don’t stick around long enough to see them.</p>
<p>In this article, we’ll explore key approaches to optimize your Next.js application, making it faster and more efficient.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-building-a-performant-app">Building a Performant Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-optimize-your-applications">How to Optimize Your Applications</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-key-techniques-to-optimize-performance">Key Techniques To Optimize Performance</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-using-the-nextjs-image-component">Using The Next.js Image Component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-optimizing-third-party-scripts-with-the-nextjs-script-component">Optimizing Third-Party Scripts with the Next.js Script Component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-remove-unused-packagesdependencies">Remove Unused Packages/Dependencies</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-caching-and-incremental-static-regeneration-isr">Caching and Incremental Static Regeneration (ISR)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-caching-frequently-used-content">Caching Frequently Used Content</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-5-font-optimization-with-nextfont">Font Optimization With next/font</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-6-lazy-loading-and-code-splitting">Lazy Loading And Code Splitting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-lazy-loading-in-nextjs">Lazy Loading in Next.js</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-code-splitting">Code Splitting</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-building-a-performant-application">Building a Performant Application</h2>
<p>Making your apps more performant means striking the right balance between speed, responsiveness, and efficient use of resources. You should strive to create an application that delivers value and keeps users satisfied.</p>
<p>Building a performant app is about making sure the app feels smooth and intuitive so that there are no frustrating lags when a user clicks buttons, scrolls, or navigates around. You’ll also want to make sure that data loads or updates without unnecessary delays.</p>
<h2 id="heading-how-to-optimize-your-applications">How to Optimize Your Applications</h2>
<p>The first step in optimizing your application is identifying problem areas. A number of tools and packages can help you analyze your application's performance effectively. Here's how you can use them:</p>
<h3 id="heading-using-npm-run-build">Using <code>npm run build</code></h3>
<p>When you run <code>npm run build</code>, Next.js creates a production-ready version of your application and gives a detailed breakdown of your pages. This includes:</p>
<ul>
<li><p><strong>Size</strong>: The size of the JavaScript files for each route. Highlighting any routes that are too large and could slow things down. Smaller page sizes generally result in faster load times while large pages might take longer to download, especially for users with slower network connections.</p>
</li>
<li><p><strong>First Load Js</strong>: This column provides information about the total amount of JavaScript the browser needs to download and execute to fully render the page for the first time. Large <strong>First Load JS</strong> values</p>
<p>  cause Slower Time-to-Interactive (TTI).</p>
</li>
</ul>
<p>Running this command produces an analysis like below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734639730677/cfd1f858-a9df-4e6c-af28-454857309156.png" alt="Example result of running npm run build" class="image--center mx-auto" width="984" height="300" loading="lazy"></p>
<h3 id="heading-using-nextbundle-analyzer">Using <code>@next/bundle-analyzer</code></h3>
<p>The <a target="_blank" href="https://www.npmjs.com/package/@next/bundle-analyzer">bundle analyzer</a> is a package provided by Next.js to analyze the size of JavaScript bundles by providing a visual representation of the application’s module and dependencies. Here’s how to use the package:</p>
<p>First, install the package by running this command:</p>
<pre><code class="lang-bash">npm install @next/bundle-analyzer
</code></pre>
<p>Or you can use yarn:</p>
<pre><code class="lang-bash">yarn add @next/bundle-analyzer
</code></pre>
<p>Then add the <code>@next/bundle-analyzer</code> configuration to your <code>next.config.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> withBundleAnalyzer = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@next/bundle-analyzer'</span>)({
  <span class="hljs-attr">enabled</span>: process.env.ANALYZE === <span class="hljs-string">'true'</span>,
});

<span class="hljs-built_in">module</span>.exports = withBundleAnalyzer({
  <span class="hljs-comment">// other Next.js config options here</span>
});
</code></pre>
<p>To analyze your application bundles while generating a production build, run the following command:</p>
<pre><code class="lang-bash">ANALYZE=<span class="hljs-literal">true</span> npm run build
</code></pre>
<p>For a step-by-step guide on how to use the bundle analyzer effectively, check out this detailed <a target="_blank" href="https://www.youtube.com/watch?v=EIGmcxwbbZw">video tutorial</a></p>
<h3 id="heading-browser-tools">Browser tools</h3>
<p>Finally, modern browsers, including Google Chrome, Firefox, and Edge, offer powerful tools to analyze and improve your application's performance. Features like the Performance Tab help you record and visualize how your application runs, pinpointing issues like slow rendering or long tasks.</p>
<p>You can also use tools like Lighthouse (available in Chrome and Edge) to generate automated audits, highlighting problems such as large assets and unoptimized resources.</p>
<p>To access the <strong>Lighthouse</strong> and <strong>Performance</strong> tabs:</p>
<ol>
<li><p>Open your browser's developer tools by right-clicking anywhere on the browser and selecting the <strong>Inspect</strong> option or pressing <strong>Command + Option + I</strong> (on Mac) or <strong>Ctrl + Shift + I</strong> (on Windows).</p>
</li>
<li><p>Look at the top menu in the developer tools.</p>
</li>
<li><p>If you don’t see the <strong>Lighthouse</strong> or <strong>Performance</strong> tabs right away, click the <strong>double right arrow (&gt;&gt;)</strong> to reveal hidden tabs.</p>
</li>
<li><p>Select the desired tab to start analyzing performance or generating a Lighthouse report.</p>
</li>
</ol>
<p>Here is an example of a generated audit in the Performance tab on Chrome</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735616911745/e5f09934-df99-40fc-b194-a292a21a4517.png" alt="image of the performance tab on chrome browser" class="image--center mx-auto" width="1130" height="966" loading="lazy"></p>
<p>Here’s another image showing the generated audit by lighthouse</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735617075187/dfde608b-eeb7-443d-81c6-56ff2a6dd92b.png" alt="dfde608b-eeb7-443d-81c6-56ff2a6dd92b" class="image--center mx-auto" width="1124" height="1522" loading="lazy"></p>
<h2 id="heading-key-techniques-to-optimize-performance">Key Techniques to Optimize Performance</h2>
<h3 id="heading-1-using-the-nextjs-image-component">1.) Using The Next.js <code>Image</code> Component</h3>
<p>Images often account for the largest portion of page weight, directly affecting load times and user experience. Large images slow down rendering and ultimately, increase bandwidth usage.</p>
<p>Next.js has a built-in <code>Image</code> component that automatically optimizes images, making it very useful for web performance. It takes care of resizing, lazy loading, and format optimization, so images are served in the most performant format (like .WebP) when the browser supports it.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Image <span class="hljs-keyword">from</span> <span class="hljs-string">'next/image'</span>;

    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Image</span>
      <span class="hljs-attr">src</span>=<span class="hljs-string">"/house.jpg"</span>
      <span class="hljs-attr">alt</span>=<span class="hljs-string">"House Image"</span>
      <span class="hljs-attr">width</span>=<span class="hljs-string">{700}</span>
      <span class="hljs-attr">height</span>=<span class="hljs-string">{500}</span>
      <span class="hljs-attr">priority</span>=<span class="hljs-string">{false}</span> // <span class="hljs-attr">Lazy</span> <span class="hljs-attr">loads</span> <span class="hljs-attr">the</span> <span class="hljs-attr">image</span> <span class="hljs-attr">by</span> <span class="hljs-attr">default</span>
    /&gt;</span></span>
</code></pre>
<p>In the snippet above,</p>
<ul>
<li><p><code>src="/house.jpg"</code>: This points to the image file's location, which is in the <code>public</code> folder. Images in the <code>/public</code> directory are served statically, so you don’t need extra configuration.</p>
</li>
<li><p><code>alt="House Image"</code>: The <code>alt</code> text (just like in the native HTML <code>image</code> element) provides a description of the image, which is great for accessibility (like screen readers) and also helps with SEO.</p>
</li>
<li><p><code>width &amp; heigh</code>t: By explicitly setting the width and height, Next.js can calculate the space the image will occupy on the page before it loads. This prevents the page layout from shifting as the image loads, which improves user experience and boosts performance metrics like <a target="_blank" href="https://blog.hubspot.com/marketing/cumulative-layout-shift">Cumulative Layout Shift</a> (as shown in the image above).</p>
</li>
<li><p><code>priority={false}</code>: This ensures the image will only load when it's near the user's viewport conserving the bandwidth and improving page load times for non-critical images. However, for important images that should load immediately (like those visible as soon as the page opens), you can set <code>priority={true}</code> to bypass lazy loading and ensure the image loads as quickly as possible.</p>
</li>
</ul>
<p>One of the key advantages of the Next.js <code>Image</code> component is its built-in <strong>lazy loading</strong> feature. This means that images won’t be loaded until they are actually needed (when they enter the viewport). By only loading images that are about to be viewed, performance is improved and pages can load faster, even with many high-quality images.</p>
<h3 id="heading-2-optimizing-third-party-scripts-with-the-nextjs-script-component">2.) Optimizing Third-Party Scripts with the Next.js Script Component</h3>
<p>Third-party scripts, such as analytics tools or advertising networks, can heavily affect your application's performance if not properly managed. Next.js has a <strong>Script</strong> component that makes it easy to load scripts efficiently, giving you control over how and when they load.</p>
<p>The <code>Script</code> component allows you to define a <strong>loading strategy</strong> for scripts, determining when and how they are fetched and executed. By prioritizing or deferring scripts based on their importance, you can improve the overall performance and user experience of your application.</p>
<ul>
<li><p><code>beforeInteractive</code><strong>:</strong> Use this strategy for scripts that must load before the page becomes interactive, like essential analytics or monitoring tools.</p>
</li>
<li><p><code>afterInteractive</code>: When you use this strategy, the script loads after the page becomes interactive, which is the default behavior. This is ideal for scripts that add functionality but aren’t essential for initial rendering.</p>
</li>
<li><p><code>lazyOnload</code>: Defers loading the script until all other page resources have finished loading. This is perfect for non-essential scripts like ads or social media widgets.</p>
</li>
</ul>
<pre><code class="lang-javascript">&lt;Script src=<span class="hljs-string">"https://example.com/non-essential.js"</span> strategy=<span class="hljs-string">"lazyOnload"</span> /&gt; <span class="hljs-comment">//Pass the strategy as a prop to the component</span>
</code></pre>
<p>By leveraging the Next.js <code>Script</code> component, you can prevent scripts from blocking critical rendering, reducing load times and improve <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Time_to_interactive">Time to Interactive</a> (TTI).</p>
<h3 id="heading-3-remove-unused-packagesdependencies">3.) Remove Unused Packages/Dependencies</h3>
<p>Over time, as you build and maintain your project, unused dependencies can pile up in your codebase. These unnecessary packages increase the size of your project, slow down installation times, and make the code harder to maintain. Cleaning up these unused dependencies is essential for optimizing your application's performance and keeping your codebase clean.</p>
<p>The <a target="_blank" href="https://www.npmjs.com/package/depcheck">depcheck</a> tool is a great way to identify and remove unused dependencies from your project. It analyzes your <code>package.json</code> and the project files to find unused dependencies, unused devDependencies, and missing dependencies.</p>
<p>You can run a <code>depcheck</code> like this:</p>
<pre><code class="lang-bash">npx depcheck
</code></pre>
<p>After identifying the unused dependencies, you can remove them by running:</p>
<pre><code class="lang-bash">npm uninstall &lt;package-name&gt;
</code></pre>
<p>or with yarn:</p>
<pre><code class="lang-bash">yarn remove &lt;package-name&gt;
</code></pre>
<p>Regularly running <code>depcheck</code> is a simple yet effective way to keep your project clean and efficient.</p>
<h3 id="heading-4-caching-and-incremental-static-regeneration-isr">4.) Caching and Incremental Static Regeneration (ISR)</h3>
<p>When you find yourself running the same calculations or database queries repeatedly, you should consider caching. It’s a simple yet powerful way to boost your web application's performance, especially for content that doesn’t change often. By storing frequently accessed data in a cache, you can avoid unnecessary processing and speed up load times.</p>
<p>In Next.js, you can take this a step further with Incremental Static Regeneration (ISR), which lets you serve static content instantly while keeping it fresh behind the scenes.</p>
<p><strong>Incremental Static Regeneration (ISR)</strong> in Next.js lets you update static pages without rebuilding the whole site. Here's how it works:</p>
<ol>
<li><p><strong>Build time generation</strong>: ISR generates pages when the site is built.</p>
</li>
<li><p><strong>Caching</strong>: It stores the pages so they load quickly when users visit.</p>
</li>
<li><p><strong>Background updates</strong>: When content changes, ISR updates the pages behind the scenes without affecting users.</p>
</li>
<li><p><strong>Dynamic updates</strong>: It combines the fast loading of static pages with the ability to update content regularly.</p>
</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getStaticProps</span>(<span class="hljs-params"></span>) </span>{

  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetchData();

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">props</span>: { data },
    <span class="hljs-comment">//regenerate the page every 20 seconds.</span>
    <span class="hljs-attr">revalidate</span>: <span class="hljs-number">20</span>,
  };
}

<span class="hljs-comment">//pre-render the page as static content</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyPage</span>(<span class="hljs-params">{ data }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>My Page<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{data}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyPage;
</code></pre>
<h3 id="heading-caching-frequently-used-content">Caching Frequently Used Content</h3>
<p>For websites with pages that get a lot of visitors, like product listings or blog posts, it's important to keep the content fast and up-to-date.</p>
<p>Caching helps achieve this by saving a copy of the page so it doesn't need to be created from scratch each time someone visits. The browser or server will store this cached page for a set amount of time, which is controlled by caching headers. Meanwhile, ISR (Incremental Static Regeneration) ensures that the page can be updated in the background when necessary, without needing to rebuild the entire site.</p>
<p>In applications with lots of data, caching can also speed up the process by storing API responses. This way, when users request the same data again, they can get it quickly from the cache instead of waiting for it to be fetched anew. Tools like Vercel and Content Delivery Networks (CDNs) help by storing these cached pages in multiple locations around the world, so visitors can access them faster.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getStaticProps</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetchData();

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">props</span>: { data },
    <span class="hljs-comment">// Regenerate page at most once every 30 seconds</span>
    <span class="hljs-attr">revalidate</span>: <span class="hljs-number">30</span>,
    <span class="hljs-comment">// Cache for 1 hour at the CDN level</span>
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-string">'Cache-Control'</span>: <span class="hljs-string">'public, max-age=3600, must-revalidate'</span>,
    },
  };
}
</code></pre>
<p>Here, the page regenerates every 30 seconds and is cached at the CDN level for one hour. The <code>Cache-Control</code> header tells the CDN and browser to cache the page for 1 hour and revalidate it afterward.</p>
<p>For a deeper dive into caching and its role in web performance, check out this insightful <a target="_blank" href="https://www.freecodecamp.org/news/caching-vs-content-delivery-network/">freeCodeCamp article on Caching vs. Content Delivery Networks</a>.</p>
<h3 id="heading-5-font-optimization-with-nextfont">5.) Font Optimization With <code>next/font</code></h3>
<p>The <code>next/font</code> module in Next.js automatically handles font loading for improved performance, so you don’t need to manually configure or use extra libraries. It loads only the essential parts of the font, which results in faster page load times.</p>
<p>To further reduce the font file size, you can provide the <code>subsets</code> array which ensures fewer bytes are transferred and pages load quickly.</p>
<p>Here’s how it works:</p>
<ul>
<li><p><strong>Automatic font loading</strong>: The module optimizes font loading automatically, making sure fonts are served in the most efficient way, improving performance without extra effort.</p>
</li>
<li><p><strong>Subsetting fonts</strong>: You can specify the exact font characters needed for your app.</p>
</li>
<li><p><strong>Font display strategy</strong>: The font-display strategy determines how text is shown to the user while fonts are loading. Next.js typically uses the <code>swap</code> strategy by default, but you can manually configure it if necessary. The most common strategies are <code>swap</code> <code>fallback</code> <code>optional</code> and <code>block</code>.</p>
</li>
<li><pre><code class="lang-javascript">  <span class="hljs-keyword">import</span> { Inter } <span class="hljs-keyword">from</span> <span class="hljs-string">'next/font/google'</span>

  <span class="hljs-keyword">const</span> inter = Inter({
    <span class="hljs-attr">subsets</span>: [<span class="hljs-string">'latin'</span>, <span class="hljs-string">'latin-ext'</span>], <span class="hljs-comment">// Load only the Latin and extended Latin subsets</span>
    <span class="hljs-attr">weight</span>: <span class="hljs-string">'400'</span>, <span class="hljs-comment">// Choose the specific weight you need</span>
    <span class="hljs-attr">style</span>: <span class="hljs-string">'normal'</span>, <span class="hljs-comment">// Specify the style if needed</span>
  })

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Page</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{inter.className}</span>&gt;</span>Hello World<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  }
</code></pre>
</li>
</ul>
<p>The snippet above uses the Next.js built-in tool for Google Fonts. Instead of adding the font link in your HTML or using a third-party library, you can import it directly like this for ease and efficiency.s</p>
<ul>
<li><p><strong>subsets:</strong> Tells the app to load only the characters needed. Skipping other character sets like Cyrillic (used in Russian) or Greek, avoids downloading extra, unnecessary data, which keeps your app lightweight and faster to load.</p>
</li>
<li><p><strong>weight:</strong> Instead of loading all font weights (e.g., Bold, Light), you only bring in Regular (400). This reduces the overall size.</p>
</li>
<li><p><strong>style:</strong> Stick with the standard style (no fancy italics). This also trims down what’s downloaded.</p>
</li>
</ul>
<h3 id="heading-6-lazy-loading-and-code-splitting">6.) Lazy Loading and Code Splitting</h3>
<p>When building web apps, you want to make sure your users don’t wait too long for your pages to load. A big part of this involves reducing how much JavaScript is loaded when the page first opens. Two techniques that help with this are <strong>lazy loading</strong> and <strong>code splitting</strong>, both of which Next.js makes easy to use.</p>
<h4 id="heading-lazy-loading-in-nextjs">Lazy Loading in Next.js</h4>
<p>Think of lazy loading like waiting to download a movie only when you decide to watch it. Imagine you have a large component like a chart or a map that users only see after interacting with a page. Instead of loading it upfront, you can tell Next.js to load it only when it’s needed using <code>next/dynamic</code>.</p>
<h4 id="heading-code-splitting-in-nextjs">Code Splitting in Next.js</h4>
<p>Code splitting breaks your JavaScript into smaller pieces (called bundles), so users only load what’s necessary. For example, if a user visits your homepage, there’s no need to load JavaScript for other pages like "About Us" or "Dashboard". It typically happens during the build process or dynamically at runtime.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> dynamic <span class="hljs-keyword">from</span> <span class="hljs-string">'next/dynamic'</span>

<span class="hljs-comment">// Load HeavyComponent only when it’s rendered</span>
<span class="hljs-keyword">const</span> HeavyComponent = dynamic(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./HeavyComponent'</span>), { <span class="hljs-attr">ssr</span>: <span class="hljs-literal">false</span> })

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Welcome Home!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">HeavyComponent</span> /&gt;</span> {/* This loads only when rendered */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
</code></pre>
<p>In the above code, <code>dynamic</code> dynamically imports the component only when needed. <code>ssr: false</code> disables server-side rendering for the component, which can save resources if the component doesn’t need to be pre-rendered.</p>
<p>Next.js automatically splits code by page, meaning each page only loads the necessary JavaScript when accessed, improving load times. For more granular control, <code>next/dynamic</code> allows you to dynamically import specific components, ensuring they are loaded lazily only when needed. While Next.js handles page-level code splitting by default, using <code>next/dynamic</code> gives you the flexibility to apply component-level splitting, optimizing resource loading and enhancing performance.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Creating a high-performance application is a very important aspect of any business. A faster and more efficient application enhances user engagement, lowers bounce rates, and boosts SEO rankings, which all contribute to business growth and customer satisfaction.</p>
<p>By utilizing these techniques we discussed in this guide, you can provide a smooth user experience while maintaining optimal efficiency behind the scenes.</p>
<p>Remember, every second saved in load time translates to happier users and, ultimately, better business outcomes.</p>
<p>Thank you for reading!</p>
<p>Want to connect with me?</p>
<ul>
<li><p>Twitter / X: <a target="_blank" href="https://x.com/Timi471">@timi471</a></p>
</li>
<li><p>Linkedin: <a target="_blank" href="https://www.linkedin.com/in/timilehin-micheal/">Ayantunji Timilehin</a></p>
</li>
<li><p>Email: ayantunjitimilehin@gmail.com</p>
</li>
</ul>
<h3 id="heading-references">References</h3>
<ul>
<li><p><a target="_blank" href="https://nextjs.org/docs/pages/building-your-application/optimizing">Next.Js Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/caching-vs-content-delivery-network/">Caching-vs-content-delivery-network</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=EIGmcxwbbZw">Using next/bundle-analyzer</a></p>
</li>
<li><p><a target="_blank" href="https://blog.hubspot.com/marketing/cumulative-layout-shift">Cumulative layout shift</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Boost Web Performance with Prefetching – Improve User Experience by Reducing Load Time ]]>
                </title>
                <description>
                    <![CDATA[ We've all encountered the frustration of waiting through long loading screens, only to find ourselves stuck with unresponsive pages. You see loading spinners everywhere, but nothing seems to move forward. Let me paint a clearer picture for you: This... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/boost-web-performance-with-prefetching/</link>
                <guid isPermaLink="false">66f18dbb04f1822b270db01b</guid>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Keyur Paralkar ]]>
                </dc:creator>
                <pubDate>Mon, 23 Sep 2024 15:48:11 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/-Vqn2WrfxTQ/upload/0657c02758973f4ea5701f2bd98469a7.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>We've all encountered the frustration of waiting through long loading screens, only to find ourselves stuck with unresponsive pages. You see loading spinners everywhere, but nothing seems to move forward. Let me paint a clearer picture for you:</p>
<p><a target="_blank" href="https://dribbble.com/shots/3358709-Skeleton-Loader#"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726397417280/bc56c517-c63f-433e-93c6-939c3b82c556.gif" alt="Multiple skeleton loader on a dashboard page" class="image--center mx-auto" width="800" height="600" loading="lazy"></a></p>
<p>This typically happens because the website is trying to fetch all the necessary data as soon as you land on the page. It could be that a API request is being processed, or multiple APIs are fetching data sequentially, causing delays in loading the page.</p>
<p>The result? A poor user experience. You might think, "How can such a large company not prioritize user experience? This is disappointing." Consequently, users often leave the site, affecting key metrics and potentially impacting revenue.</p>
<p>But what if you could fetch the data for these heavy pages ahead of time, so that by the time a user lands on the page, they can interact with it instantly?</p>
<p>This is where the concept of prefetching comes in, and that's exactly what we'll be diving into in this blog post. So without further ado, let's get started!</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prefetching-as-a-solution">Prefetching as a Solution</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-prefetching-improves-user-experience">How Prefetching Improves User Experience</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-problem">Understanding The Problem</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-solution-1-prefetching-data-in-the-parent-component">Solution #1: Prefetching Data in the Parent Component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-solution-2-prefetch-data-on-page-load">Solution #2: Prefetch Data on Page load</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-prefetching-with-react">How to Implement Prefetching with React</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-prefetching-with-react">Too much prefetching can also cause</a> <a class="post-section-overview" href="#heading-too-much-prefetching-can-also-cause-slowness">s</a><a class="post-section-overview" href="#heading-how-to-implement-prefetching-with-react">lowness</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary">Summary</a></p>
</li>
</ul>
<h2 id="heading-prefetching-as-a-solution">Prefetching as a Solution</h2>
<p>Here’s the revised version with just the grammar and spelling corrected:</p>
<p>For the problem above, what we want is to fetch the data for a given page before it's loaded onto the website so that the user doesn’t need to fetch the data on page load. This is called prefetching. From a technical perspective, its definition is as follows:</p>
<blockquote>
<p><em>It is a way to fetch the required data beforehand so that the main component doesn’t need to wait for the data, thus enhancing the experience.</em></p>
</blockquote>
<p>This can improve the user experience, boosting the customer’s confidence in your website.</p>
<p>Prefetching is a simple yet elegant solution that is more user-centric than a standard process. To implement prefetching, we need to understand the user’s behavior on the website. That is, the most visited pages, or which components fetch data on small interactions (such as hover).</p>
<p>After analyzing such scenarios, it makes sense to apply prefetching to them. However, as developers, we should be mindful of using this concept. Too much prefetching can also slow down your website since you're trying to fetch a lot of data for future scenarios, which might block the fetching of data for the main page.</p>
<h2 id="heading-how-prefetching-improves-user-experience">How Prefetching Improves User Experience</h2>
<p>Let us look at couple of scenarios where prefetching is beneficial:</p>
<ol>
<li><p>Loading data/page earlier for the most visited link from your landing page. For example, consider that you have a “contact us” link. Let’s assume that this is the link that users mostly check and it contains a lot of data when it loads. Rather than loading the data when the contact us page loads, you can simply fetch the data on the homepage so that you don’t have to wait at the Contact Us page for the data. You can read more about prefetching pages <a target="_blank" href="https://web.dev/articles/link-prefetch">here</a>.</p>
</li>
<li><p>Prefetching table data for later pages.</p>
</li>
<li><p>Fetching data from a parent component and loading it in the child component.</p>
</li>
<li><p>Prefetching data that needs to be displayed in a popover.</p>
</li>
</ol>
<p>These are some of the ways to achieve prefetching in your application and how it helps improve the user experience.</p>
<p>In this blog post we will be discussing about the last scenario: <em>“</em>prefetching data that needs to be displayed in the popover”. This is a classic example where prefetching can be beneficial and provides a smoother experience to the user.</p>
<h2 id="heading-understanding-the-problem">Understanding The Problem</h2>
<p>Let me define the problem here. Imagine the following scenario:</p>
<ol>
<li><p>You have a component that displays specific information.</p>
</li>
<li><p>There is an element inside this component that shows another popover/tooltip when you hover on it.</p>
</li>
<li><p>The popover fetches data when it loads.</p>
</li>
</ol>
<p>Now imagine that the user hovers on the element and needs to wait for the data to be fetched and displayed in the popover. During this wait, they see the skeleton loader.</p>
<p>The scenario will look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726395720567/6ec88fab-ffe2-4f20-b934-94342f9cf3c0.gif" alt="Example of fetching data when the popover component mounts" class="image--center mx-auto" width="600" height="268" loading="lazy"></p>
<p>It’s just frustrating how long the user has to wait whenever they hover on the image:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726395733461/3598da70-e8af-4a1a-b3cf-5c3ed62fe9cc.gif" alt="User hovering images to load popover component that fetches data" class="image--center mx-auto" width="600" height="268" loading="lazy"></p>
<p>To solve this problem, there are two solutions that can help you get started and optimize the solution according to your needs.</p>
<h2 id="heading-solution-1-prefetching-data-in-the-parent-component">Solution #1: Prefetching Data in the Parent Component</h2>
<p>This solution is inspired from <a target="_blank" href="https://martinfowler.com/articles/data-fetch-spa.html?utm_source=cassidoo&amp;utm_medium=email&amp;utm_campaign=until-youre-ready-to-look-foolish-youll-never#prefetching">Martin Fowler’s blogpost</a>. It allows you to fetch the data before the popup appears, instead of fetching on component load.</p>
<p>The popup appears when you hover on it. We can fetch the data when the mouse enters the parent component. Before the actual component—the image—is hovered on, we’ll have the data for the popover and will pass it to the popover component.</p>
<p>This solution doesn’t remove the loading state all together but it helps to significantly lower the chances of seeing the loading state.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726395771616/69b6c536-8b62-4124-837a-f26746f6f305.gif" alt="Improving the UX by fetching the data from the parent component" class="image--center mx-auto" width="600" height="296" loading="lazy"></p>
<h2 id="heading-solution-2-prefetch-data-on-page-load">Solution #2: Prefetch Data on Page load</h2>
<p>This solution is inspired by <a target="_blank" href="http://x.com">x.com</a> where, for the popover component, they fetch the data partially on the main page load and fetch the rest of the data when the component mounts.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726395833198/c7f1fa64-986d-4bfc-83cb-f052cd560f3a.gif" alt="Twitter advertisement by XDevelopers. Text reads: &quot;Calling all #developers! Innovate with our real-time and historical data on the X API. Get started with Pro👇&quot;. Image shows a person in a white shirt with text &quot;Build what's next with our API @XDevelopers&quot; and &quot;Subscribe now!&quot; Used by permission. From twitter.com." class="image--center mx-auto" width="800" height="522" loading="lazy"></p>
<p>As you can see from the above video, the user’s profile details are viewed in the popover. If you look closely, the details related to followers are fetched later.</p>
<p>This technique is highly efficient when you have a lot of data to be displayed in the popover but fetching them can be costly on popover mount or on the main page load.</p>
<p>A better solution would be to partially load the required data on the main page and load the rest of the data when the component mounts.</p>
<p>In our example, we fetched the data for the popover when the cursor entered the image’s parent element. Now imagine that you need to fetch additional details once the popover data is loaded. So based on the above x.com’s method, we can fetch additional data on popover load. Here is the outcome of it:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726395913909/b5f6f231-5a1e-4c44-a4eb-bd5ed863ce3b.gif" alt="GIF explaining how we prefetch data from parent and load additional data on component mount for popover " class="image--center mx-auto" width="1464" height="898" loading="lazy"></p>
<p>Here, we do the following things:</p>
<ul>
<li><p>We fetch the main data which is just necessary to render the popover when mouse enters the parent component of the image.</p>
</li>
<li><p>This gives us enough time to fetch the main data.</p>
</li>
<li><p>On popover load, we fetch another data, which is the album count. While the user reads data like name and email, we’ll have the next data ready to be seen.</p>
</li>
</ul>
<p>This way, we can make small and smart tweaks to minimize the blank staring of loaders on the screen 😊.</p>
<h2 id="heading-how-to-implement-prefetching-with-react">How to Implement Prefetching with React</h2>
<p>In this section we’ll briefly go through the how to implement the above prefetching example app.</p>
<h3 id="heading-project-setup">Project Setup</h3>
<p>To get started with creating the prefetching app, follow the process below:</p>
<p>You can use <a target="_blank" href="https://vitejs.dev/">vitejs</a> (this is what I used) or <a target="_blank" href="https://create-react-app.dev/">create-react-app</a> to create your app. Paste the command below in your terminal:</p>
<pre><code class="lang-bash">yarn create vite prefetch-example --template react-ts
</code></pre>
<p>Once the app has been created, you should have the following folder structure when you open the <strong>prefetch-example</strong> folder with VS Code.</p>
<ul>
<li><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726764168271/2dc9bfa1-07d9-491e-96fd-e780c3623eeb.png" alt="Image of the folder structure once the vitejs app is created" class="image--center mx-auto" width="732" height="996" loading="lazy"></li>
</ul>
<p>Now let us dive into the components that we are going to be building for this app.</p>
<h3 id="heading-components">Components</h3>
<p>In this example we are going to be using 3 components:</p>
<ul>
<li><p><code>PopoverExample</code></p>
</li>
<li><p><code>UserProfile</code></p>
</li>
<li><p><code>UserProfileWithFetching</code></p>
</li>
</ul>
<h3 id="heading-popoverexample-component"><code>PopoverExample</code> Component</h3>
<p>Let us start with the first component which is the <code>PopoverExample</code>. This component displays an image avatar and some text to the right side of it. It should look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727002319443/bcc28972-fce0-42ba-899c-274513c4a7c6.png" alt="Image of the PopoverExample component that contains image to the left and lorem ipsum text to the right" class="image--center mx-auto" width="1376" height="656" loading="lazy"></p>
<p>The purpose of this component is to serve as an example similar to the real life scenarios. The image in this component loads a popover component when it is hovered on.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727002429245/9af8f26e-f149-41f7-b124-3ec2a0f5c80a.png" alt="Image of popover element that contains user information when the image is hovered" class="image--center mx-auto" width="1480" height="950" loading="lazy"></p>
<p>Here’s the code for the component:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useFloating, useHover, useInteractions } <span class="hljs-keyword">from</span> <span class="hljs-string">"@floating-ui/react"</span>;
<span class="hljs-keyword">import</span> ContentLoader <span class="hljs-keyword">from</span> <span class="hljs-string">"react-content-loader"</span>;
<span class="hljs-keyword">import</span> UserProfile <span class="hljs-keyword">from</span> <span class="hljs-string">"./UserProfile"</span>;
<span class="hljs-keyword">import</span> UserProfileWithFetching <span class="hljs-keyword">from</span> <span class="hljs-string">"./UserProfileWithFetching"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> MyLoader = <span class="hljs-function">() =&gt;</span> (
    &lt;ContentLoader
        speed={<span class="hljs-number">2</span>}
        width={<span class="hljs-number">340</span>}
        height={<span class="hljs-number">84</span>}
        viewBox=<span class="hljs-string">"0 0 340 84"</span>
        backgroundColor=<span class="hljs-string">"#d1d1d1"</span>
        foregroundColor=<span class="hljs-string">"#fafafa"</span>
    &gt;
        &lt;rect x=<span class="hljs-string">"0"</span> y=<span class="hljs-string">"0"</span> rx=<span class="hljs-string">"3"</span> ry=<span class="hljs-string">"3"</span> width=<span class="hljs-string">"67"</span> height=<span class="hljs-string">"11"</span> /&gt;
        &lt;rect x=<span class="hljs-string">"76"</span> y=<span class="hljs-string">"0"</span> rx=<span class="hljs-string">"3"</span> ry=<span class="hljs-string">"3"</span> width=<span class="hljs-string">"140"</span> height=<span class="hljs-string">"11"</span> /&gt;
        &lt;rect x=<span class="hljs-string">"127"</span> y=<span class="hljs-string">"48"</span> rx=<span class="hljs-string">"3"</span> ry=<span class="hljs-string">"3"</span> width=<span class="hljs-string">"53"</span> height=<span class="hljs-string">"11"</span> /&gt;
        &lt;rect x=<span class="hljs-string">"187"</span> y=<span class="hljs-string">"48"</span> rx=<span class="hljs-string">"3"</span> ry=<span class="hljs-string">"3"</span> width=<span class="hljs-string">"72"</span> height=<span class="hljs-string">"11"</span> /&gt;
        &lt;rect x=<span class="hljs-string">"18"</span> y=<span class="hljs-string">"48"</span> rx=<span class="hljs-string">"3"</span> ry=<span class="hljs-string">"3"</span> width=<span class="hljs-string">"100"</span> height=<span class="hljs-string">"11"</span> /&gt;
        &lt;rect x=<span class="hljs-string">"0"</span> y=<span class="hljs-string">"71"</span> rx=<span class="hljs-string">"3"</span> ry=<span class="hljs-string">"3"</span> width=<span class="hljs-string">"37"</span> height=<span class="hljs-string">"11"</span> /&gt;
        &lt;rect x=<span class="hljs-string">"18"</span> y=<span class="hljs-string">"23"</span> rx=<span class="hljs-string">"3"</span> ry=<span class="hljs-string">"3"</span> width=<span class="hljs-string">"140"</span> height=<span class="hljs-string">"11"</span> /&gt;
        &lt;rect x=<span class="hljs-string">"166"</span> y=<span class="hljs-string">"23"</span> rx=<span class="hljs-string">"3"</span> ry=<span class="hljs-string">"3"</span> width=<span class="hljs-string">"173"</span> height=<span class="hljs-string">"11"</span> /&gt;
    &lt;/ContentLoader&gt;
);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">PopoverExample</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [isOpen, setIsOpen] = useState(<span class="hljs-literal">false</span>);
    <span class="hljs-keyword">const</span> [isLoading, setIsLoading] = useState(<span class="hljs-literal">false</span>);
    <span class="hljs-keyword">const</span> [data, setData] = useState({});

    <span class="hljs-keyword">const</span> { refs, floatingStyles, context } = useFloating({
        open: isOpen,
        onOpenChange: setIsOpen,
        placement: <span class="hljs-string">"top"</span>,
    });

    <span class="hljs-keyword">const</span> hover = useHover(context);

    <span class="hljs-keyword">const</span> { getReferenceProps, getFloatingProps } = useInteractions([hover]);

    <span class="hljs-keyword">const</span> handleMouseEnter = <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Object</span>.keys(data).length === <span class="hljs-number">0</span>) {
            setIsLoading(<span class="hljs-literal">true</span>);
            fetch(<span class="hljs-string">"https://jsonplaceholder.typicode.com/users/1"</span>)
                .then(<span class="hljs-function">(<span class="hljs-params">resp</span>) =&gt;</span> resp.json())
                .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
                    setData(data);
                    setIsLoading(<span class="hljs-literal">false</span>);
                });
        }
    };

    <span class="hljs-keyword">return</span> (
        &lt;div
            id=<span class="hljs-string">"hover-example"</span>
            style={{
                display: <span class="hljs-string">"flex"</span>,
                flexDirection: <span class="hljs-string">"row"</span>,
                alignItems: <span class="hljs-string">"center"</span>,
                textAlign: <span class="hljs-string">"left"</span>,
            }}
            onMouseEnter={handleMouseEnter}
        &gt;
            &lt;span
                style={{
                    padding: <span class="hljs-string">"1rem"</span>,
                }}
            &gt;
                &lt;img
                    ref={refs.setReference}
                    {...getReferenceProps()}
                    style={{
                        borderRadius: <span class="hljs-string">"50%"</span>,
                    }}
                    src=<span class="hljs-string">"https://cdn.jsdelivr.net/gh/alohe/avatars/png/vibrent_5.png"</span>
                /&gt;
            &lt;/span&gt;
            &lt;p&gt;
                Lorem Ipsum is simply dummy text <span class="hljs-keyword">of</span> the printing and typesetting
                industry. Lorem Ipsum has been the industry<span class="hljs-string">'s standard dummy text ever
                since the 1500s, when an unknown printer took a galley of type and
                scrambled it to make a type specimen book. It has survived not only five
                centuries, but also the leap into electronic typesetting, remaining
                essentially unchanged. It was popularised in the 1960s with the release
                of Letraset sheets containing Lorem Ipsum passages, and more recently
                with desktop publishing software like Aldus PageMaker including versions
                of Lorem Ipsum.
            &lt;/p&gt;
            {isOpen &amp;&amp; (
                &lt;div
                    className="floating"
                    ref={refs.setFloating}
                    style={{
                        ...floatingStyles,
                        backgroundColor: "white",
                        color: "black",
                        padding: "1rem",
                        fontSize: "1rem",
                    }}
                    {...getFloatingProps()}
                &gt;
                    {isLoading ? (
                        &lt;MyLoader /&gt;
                    ) : (
                        &lt;UserProfile hasAdditionalDetails {...data} /&gt;
                    )}
                    {/* &lt;UserProfileWithFetching /&gt; */}
                &lt;/div&gt;
            )}
        &lt;/div&gt;
    );
}</span>
</code></pre>
<p>There are couple of things happening here, let me explain them step-by-step:</p>
<ul>
<li><p>We have a parent <code>div</code> named <code>hover-example</code> that contains an image and some text.</p>
</li>
<li><p>Next, we conditionally rendered a <code>div</code> with class name of <code>floating</code>. This is the actual popover component that opens when you hover on the image.</p>
<ul>
<li>We made use of the <a target="_blank" href="https://floating-ui.com/"><code>floating-ui</code> library</a> and its <a target="_blank" href="https://floating-ui.com/docs/useHover">basic hover example</a> to achieve the hover effect for the popover.</li>
</ul>
</li>
<li><p>Inside the popover we conditionally loaded the <code>UserProfile</code> and the skeleton loader. This loader appears when we are fetching the data for the user’s profile. More on this later.</p>
</li>
<li><p>We made use of the <a target="_blank" href="https://github.com/danilowoz/react-content-loader">react-content-loader</a> library in the <code>MyLoader</code> component. This library also has a website that helps you to create loaders, you can check it out <a target="_blank" href="https://skeletonreact.com/">here</a>.</p>
</li>
</ul>
<h3 id="heading-userprofile-component"><code>UserProfile</code> Component</h3>
<p>Now that we have defined our <code>Popover</code> example, it is time for us to get into the details of the <code>UserProfile</code> component.</p>
<p>This component appears inside the popover component. The purpose of this component is to load the <code>name</code> <code>email</code> <code>phone</code> <code>website</code> details which are fetched from <a target="_blank" href="https://jsonplaceholder.typicode.com/users/1">JSON placeholder API</a>.</p>
<p>To demonstrate the prefetching example, we have to make sure that the <code>UserProfile</code> component only acts as a presentational component; that is, no explicit fetching logic is present inside of it.</p>
<p>The key thing to note about this component is that fetching the data happens from the parent component which is the <code>PopoverExample</code> component. In this component, we start fetching the data when the mouse enters this component (the <code>mouseenter</code> event). This is the solution #1 we discussed previously.</p>
<p>This gives you enough time for fetching the data until the user hovers on the image. Here’s the code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ContentLoader <span class="hljs-keyword">from</span> <span class="hljs-string">"react-content-loader"</span>;

<span class="hljs-keyword">const</span> MyLoader = <span class="hljs-function">() =&gt;</span> (
    &lt;ContentLoader
        speed={<span class="hljs-number">2</span>}
        viewBox=<span class="hljs-string">"0 0 476 124"</span>
        backgroundColor=<span class="hljs-string">"#d1d1d1"</span>
        foregroundColor=<span class="hljs-string">"#fafafa"</span>
    &gt;
        &lt;rect x=<span class="hljs-string">"4"</span> y=<span class="hljs-string">"43"</span> rx=<span class="hljs-string">"0"</span> ry=<span class="hljs-string">"0"</span> width=<span class="hljs-string">"98"</span> height=<span class="hljs-string">"30"</span> /&gt;
    &lt;/ContentLoader&gt;
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UserProfile</span>(<span class="hljs-params">props: Record&lt;<span class="hljs-built_in">string</span>, <span class="hljs-built_in">string</span> | <span class="hljs-built_in">boolean</span>&gt;</span>) </span>{
    <span class="hljs-keyword">const</span> { name, email, phone, website, hasAdditionalDetails } = props;
    <span class="hljs-keyword">const</span> [isLoading, setIsLoading] = useState(<span class="hljs-literal">false</span>);
    <span class="hljs-keyword">const</span> [additionalData, setAdditionalData] = useState(<span class="hljs-number">0</span>);

    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span> (hasAdditionalDetails) {
            setIsLoading(<span class="hljs-literal">true</span>);
            fetch(<span class="hljs-string">"https://jsonplaceholder.typicode.com/albums"</span>)
                .then(<span class="hljs-function">(<span class="hljs-params">resp</span>) =&gt;</span> resp.json())
                .then(<span class="hljs-function">(<span class="hljs-params">data: <span class="hljs-built_in">Array</span>&lt;unknown&gt;</span>) =&gt;</span> {
                    <span class="hljs-keyword">const</span> albumCount = data.reduce(<span class="hljs-function">(<span class="hljs-params">acc, curr</span>) =&gt;</span> {
                        <span class="hljs-keyword">if</span> (curr.userId === <span class="hljs-number">1</span>) acc += <span class="hljs-number">1</span>;

                        <span class="hljs-keyword">return</span> acc;
                    }, <span class="hljs-number">0</span>);
                    setAdditionalData(albumCount);
                })
                .finally(<span class="hljs-function">() =&gt;</span> {
                    setIsLoading(<span class="hljs-literal">false</span>);
                });
        }
    }, [hasAdditionalDetails]);

    <span class="hljs-keyword">return</span> (
        &lt;div id=<span class="hljs-string">"user-profile"</span>&gt;
            &lt;div id=<span class="hljs-string">"user-name"</span>&gt;name: {name}&lt;/div&gt;
            &lt;div id=<span class="hljs-string">"user-email"</span>&gt;email: {email}&lt;/div&gt;
            &lt;div id=<span class="hljs-string">"user-phone"</span>&gt;phone: {phone}&lt;/div&gt;
            &lt;div id=<span class="hljs-string">"user-website"</span>&gt;website: {website}&lt;/div&gt;
            {hasAdditionalDetails &amp;&amp; (
                &lt;&gt;
                    {isLoading ? (
                        &lt;MyLoader /&gt;
                    ) : (
                        &lt;div id=<span class="hljs-string">"user-albums"</span>&gt;Album Count: {additionalData}&lt;/div&gt;
                    )}
                &lt;/&gt;
            )}
        &lt;/div&gt;
    );
}
</code></pre>
<p>This component makes use of the <code>hasAdditionalDetails</code> prop. The purpose of this <code>prop</code> is to load additional data when the component mounts. It illustrates the solution #2 mentioned above.</p>
<h3 id="heading-userprofilewithfetching-component"><code>UserProfileWithFetching</code> Component</h3>
<p>This component is pretty similar to that of the <code>UserProfile</code> component. It just contains the logic for fetching data when the component loads. The purpose of this component is to show what the general solution without the prefetching technique would look like.</p>
<p>So this component will always load the data when the component mounts, which displays the skeleton loader.</p>
<p>Here is the code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { MyLoader } <span class="hljs-keyword">from</span> <span class="hljs-string">"./PopoverExample"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UserProfileWithFetching</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [isLoading, setIsLoading] = useState(<span class="hljs-literal">false</span>);
    <span class="hljs-keyword">const</span> [data, setData] = useState&lt;Record&lt;<span class="hljs-built_in">string</span>, <span class="hljs-built_in">string</span>&gt;&gt;({});

    useEffect(<span class="hljs-function">() =&gt;</span> {
        setIsLoading(<span class="hljs-literal">true</span>);
        fetch(<span class="hljs-string">"https://jsonplaceholder.typicode.com/users/1"</span>)
            .then(<span class="hljs-function">(<span class="hljs-params">resp</span>) =&gt;</span> resp.json())
            .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
                setData(data);
                setIsLoading(<span class="hljs-literal">false</span>);
            });
    }, []);

    <span class="hljs-keyword">if</span> (isLoading) <span class="hljs-keyword">return</span> &lt;MyLoader /&gt;;

    <span class="hljs-keyword">return</span> (
        &lt;div id=<span class="hljs-string">"user-profile"</span>&gt;
            &lt;div id=<span class="hljs-string">"user-name"</span>&gt;name: {data.name}&lt;/div&gt;
            &lt;div id=<span class="hljs-string">"user-email"</span>&gt;email: {data.email}&lt;/div&gt;
            &lt;div id=<span class="hljs-string">"user-phone"</span>&gt;phone: {data.phone}&lt;/div&gt;
            &lt;div id=<span class="hljs-string">"user-website"</span>&gt;website: {data.website}&lt;/div&gt;
        &lt;/div&gt;
    );
}
</code></pre>
<p>The entire code for this app can be found <a target="_blank" href="https://github.com/keyurparalkar/prefetch-examples">here</a>.</p>
<h2 id="heading-too-much-prefetching-can-also-cause-slowness">Too much prefetching can also cause slowness</h2>
<p>A word of advice, too much prefetching is not good because:</p>
<ul>
<li><p>It might slow your app down.</p>
</li>
<li><p>It can degrade user experience if prefetching is not applied strategically.</p>
</li>
</ul>
<p>Prefetching needs to be applied when you know the behavior of the user. That is, you are able to predict the user movement by metrics and be able to tell if they visit a page often. In that case, prefetching is a good idea.</p>
<p>So remember to always apply prefetching strategically.</p>
<h2 id="heading-summary">Summary</h2>
<p>That’s all folks! Hope you like my blog post. In this blogpost, you learned that implementing prefetching can significantly enhance your web application’s speed and responsiveness, improving user satisfaction.</p>
<p>For further reading, please refer to the below articles:</p>
<ul>
<li><p><a target="_blank" href="https://www.patterns.dev/vanilla/prefetch/">Prefetching pages</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/reloading/preload-prefetch-and-priorities-in-chrome-776165961bbf">Preload, Prefetch And Priorities in Chrome</a></p>
</li>
<li><p><a target="_blank" href="https://addyosmani.com/blog/what-not-to-prefetch-prerender/">What not to prefetch</a></p>
</li>
</ul>
<p>For more content, you can follow me on <a target="_blank" href="https://twitter.com/keurplkar">Twitter</a>, <a target="_blank" href="http://github.com/keyurparalkar">GitHub</a>, and <a target="_blank" href="https://www.linkedin.com/in/keyur-paralkar-494415107/">LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Speedy Web Compiler? SWC Explained With Examples ]]>
                </title>
                <description>
                    <![CDATA[ In the evolving landscape of JavaScript development, the need for efficient and powerful tooling has become increasingly important. Developers rely on tools like compilers and bundlers to transform their code, optimize performance, and ensure compati... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-speedy-web-compiler/</link>
                <guid isPermaLink="false">66d90463e90270a49f64f4c6</guid>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Rust ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Preston Mayieka ]]>
                </dc:creator>
                <pubDate>Thu, 05 Sep 2024 01:07:47 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1725290113209/260f00cb-5bfe-4260-8e45-0c61a1897cae.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In the evolving landscape of JavaScript development, the need for efficient and powerful tooling has become increasingly important.</p>
<p>Developers rely on tools like <a target="_blank" href="https://en.wikipedia.org/wiki/Compiler"><strong>compilers</strong></a> and <a target="_blank" href="https://www.codejourney.net/what-is-a-javascript-bundler/"><strong>bundlers</strong></a> to transform their code, optimize performance, and ensure compatibility across different environments.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725287352931/41e13dc3-100e-4f75-87df-98342df4beb2.png" alt="41e13dc3-100e-4f75-87df-98342df4beb2" class="image--center mx-auto" width="901" height="506" loading="lazy"></p>
<p>These tools are essential for modern JavaScript applications, enabling developers to write clean, maintainable code while leveraging the latest language features.</p>
<p>This article will help you understand what Speedy Web Compiler (SWC) is and how it helps optimize the performance of your web apps.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-speedy-web-compiler">Introduction to Speedy Web Compiler</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-background-of-swc">Background of SWC</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-speedy-web-compiler-works">How Speedy Web Compiler Works</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-benefits-of-using-speedy-web-compiler">Benefits of Using Speedy Web Compiler</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-speedy-web-compiler">How to Set Up Speedy Web Compiler in Your Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-swc-integration-in-popular-frameworks">SWC Integration in Popular Frameworks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-speedy-web-compiler">What is Speedy Web Compiler?</h2>
<p>First, let me break it down.</p>
<p>SWC stands for Speedy Web Compiler, and when broken down:</p>
<p><strong>Speedy</strong> - This means it's fast! SWC processes and transforms JavaScript code, making it efficient to use in big projects.</p>
<p><strong>Web</strong> - It’s all about web development. It focuses on improving how JavaScript (the language of the web) handles it.</p>
<p><strong>Compiler</strong> - It takes code written in one form and transforms it into another form that can be better understood or used by computers.</p>
<h2 id="heading-background-of-swc">Background of SWC</h2>
<p><a target="_blank" href="https://github.com/kdy1">kdy1</a>, a South Korean developer and maintainer of <a target="_blank" href="https://nextjs.org/">Next.js</a>, created SWC as a faster tool for handling JavaScript code.</p>
<p>The motivation was the need for speed and efficiency, as web projects grow larger and more complex.</p>
<p>With numerous websites and apps depending on JavaScript, SWC helps developers save time and work more efficiently.</p>
<h2 id="heading-how-speedy-web-compiler-works">How Speedy Web Compiler Works</h2>
<p>SWC uses <a target="_blank" href="https://www.rust-lang.org/">Rust</a>, a programming language known for its speed and safety.</p>
<p>SWC works by taking your JavaScript or TypeScript code and transforming it into a version that can run efficiently in various environments.</p>
<p>Understanding how SWC achieves this involves examining its core steps: parsing, transforming, and generating code.</p>
<h3 id="heading-how-does-swc-parse-code">How Does SWC Parse Code?</h3>
<p>The first step in the compilation process is parsing.</p>
<p>Begins by <strong>reading</strong> and analyzing the code to understand its structure.</p>
<p>This is akin to taking a complex sentence and breaking it down into its grammatical components—subject, verb, object, etc.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725287153049/b7ec431c-24db-4c7a-9fb0-ef3ce0d92921.png" alt="Illustration of Code parsing into forming abstract syntax tree" class="image--center mx-auto" width="891" height="499" loading="lazy"></p>
<p>In technical terms, SWC converts your code into an <a target="_blank" href="https://en.wikipedia.org/wiki/Abstract_syntax_tree"><strong>Abstract Syntax Tree (AST)</strong>.</a></p>
<p>The AST is a tree-like representation of the source code, where each node in the tree corresponds to a construct occurring in the code, such as expressions, statements, and functions.</p>
<p>This tree structure allows SWC to process and understand the code’s logic in a way that is both efficient and scalable.</p>
<h3 id="heading-how-does-swc-transform-code">How Does SWC Transform Code?</h3>
<p>After creating the AST, SWC moves on to the transformation phase.</p>
<p>This is where the magic happens—SWC applies various optimizations and changes to the code based on the target environment.</p>
<p>For instance, if you're targeting older browsers that don't support modern JavaScript features, SWC will transform your ES6+ code into a backward-compatible version.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725287185279/371d2ac2-e919-4f25-8caf-01d4157fd290.png" alt="Yellow gear with two circular arrows surrounding it, accompanied by the text &quot;Transformation of AST&quot; on a dark background." class="image--center mx-auto" width="888" height="498" loading="lazy"></p>
<p>During this phase, SWC also handles TypeScript transformations. It strips away TypeScript-specific syntax, such as types and interfaces, converting the code into pure JavaScript that gets executed by any JavaScript engine.</p>
<p>SWC can apply custom transformations based on plugins or specific configurations, making it highly versatile.</p>
<h3 id="heading-how-does-swc-generate-optimized-code">How Does SWC Generate Optimized Code?</h3>
<p>After the transformations are complete, SWC proceeds to the final step: code generation.</p>
<p>In this step, SWC takes the transformed AST and converts it back into executable code.</p>
<p>In contrast, this process is not just a reversal of the parsing process.</p>
<p>SWC takes special care to generate code that is both functionally correct and optimized for performance.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725287212996/af724e34-6473-4104-8244-e35c1be6a3c0.png" alt="Yellow line drawing of a coding window with a wrench and gear icon, above text that reads &quot;Generation of Optimized Code&quot; on a black background." class="image--center mx-auto" width="886" height="496" loading="lazy"></p>
<p>For instance, SWC might remove dead code (code that will never be executed) or inline certain functions to reduce overhead.</p>
<p>The goal is to produce code that is as clean and efficient as possible, ensuring that it runs quickly and reliably in production environments.</p>
<h2 id="heading-benefits-of-using-speedy-web-compiler">Benefits of Using Speedy Web Compiler</h2>
<h3 id="heading-performance">Performance</h3>
<p>One of the major benefits of using SWC is its outstanding speed. SWC achieves this exceptional speed by using Rust.</p>
<p>Developers can expect a significant performance improvement when compiling their code for large projects or codebases.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725287254910/9c4827d9-81db-488d-bdb8-6b0806ddfd67.png" alt="Illustration of a stopwatch inside a web browser window, with motion lines indicating speed. The text below reads &quot;Faster Loading Times.&quot;" class="image--center mx-auto" width="893" height="498" loading="lazy"></p>
<p>This speed greatly reduces build times, enhancing the efficiency and responsiveness of the development process. It is so fast, you might think it’s late for a meeting!</p>
<h3 id="heading-optimized-output">Optimized Output</h3>
<p>SWC compiles your code and guarantees that the output is highly optimized for performance in production environment by removing dead code, in-lining functions, and reducing the size of the output.</p>
<p>This makes using SWC cost-effective, saving you from extra expenses during production.</p>
<p>The result is a leaner, faster, and more efficient code that can enhance loading times and performance in web applications.</p>
<h3 id="heading-compatibility">Compatibility</h3>
<p>SWC is fully compatible with modern JavaScript libraries and frameworks.</p>
<p>You do not have to worry about using ES6+ or TypeScript. This makes SWC a versatile choice for your projects.</p>
<h2 id="heading-how-to-set-up-speedy-web-compiler">How to Set Up Speedy Web Compiler</h2>
<h3 id="heading-installation">Installation</h3>
<p>To install SWC in your JavaScript or TypeScript project, follow these steps:</p>
<ol>
<li><strong>Initialize your project:</strong> If you haven't already, start by initializing a new project. In your terminal, run:</li>
</ol>
<pre><code class="lang-bash">npm init -y
</code></pre>
<ol start="2">
<li><strong>Install SWC with npm:</strong> Run the following command to download the pre-built binaries:</li>
</ol>
<pre><code class="lang-bash">npm install -D @swc/cli @swc/core
</code></pre>
<ol start="3">
<li><strong>Create a JavaScript file:</strong> Create a <code>src/index.js</code> file with some code:</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> greet = <span class="hljs-function">(<span class="hljs-params">name</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-string">`Hello, <span class="hljs-subst">${name}</span>!`</span>;
};

<span class="hljs-built_in">console</span>.log(greet(<span class="hljs-string">"World"</span>));
</code></pre>
<ol start="4">
<li><strong>Compile with SWC:</strong> Run SWC from the command line to compile your JavaScript file:</li>
</ol>
<pre><code class="lang-bash">npx swc src/index.js -o dist/index.js
</code></pre>
<ol start="5">
<li><strong>Resulting Code:</strong> The resulting JavaScript code in <code>dist/index.js</code> will look like this:</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-meta">"use strict"</span>;
<span class="hljs-keyword">var</span> greet = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">name</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello, "</span> + name + <span class="hljs-string">"!"</span>;
};
<span class="hljs-built_in">console</span>.log(greet(<span class="hljs-string">"World"</span>));
</code></pre>
<p>This is the transpiled ES5 code produced by SWC, suitable for environments that require backward compatibility with older JavaScript versions.</p>
<h2 id="heading-swc-integration-in-popular-frameworks">SWC Integration in Popular Frameworks</h2>
<p>If you are using Next.js, Deno, Vite, Remix, Parcel, or Turbopack, SWC is already integrated.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725287305286/e0a1e681-4531-402c-ae41-1f8c5f1318c8.png" alt="Logos of various web development frameworks and tools on a black background, which include: Deno, Vite, Next.js, Remix, Turbopack, and an open cardboard box." class="image--center mx-auto" width="896" height="498" loading="lazy"></p>
<blockquote>
<p>Notable improvements were made on Next.js, a popular React framework, since version 12 (Source: <a target="_blank" href="https://nextjs.org/blog/next-12">Next.js 12: The SDK for the Web</a>)</p>
</blockquote>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In the constantly changing realm of JavaScript development, having the correct tools can make a significant difference.</p>
<p>SWC, the <a target="_blank" href="http://swc.rs">Speedy Web Compiler</a>, distinguishes itself as a strong solution for converting and optimizing JavaScript and TypeScript code.</p>
<p>Its impressive speed, owing to its Rust-based implementation, along with its efficient management of code transformations and optimizations, positions it as a powerful tool for modern web development.</p>
<p>If you would like to stay in touch:</p>
<p><a target="_blank" href="https://www.linkedin.com/in/preston-mayieka/">Connect with me on LinkedIn</a></p>
<p><a target="_blank" href="https://mobile.x.com/Preston_Mayieka">Follow me on X</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Optimize Next.js App Performance With Lazy Loading ]]>
                </title>
                <description>
                    <![CDATA[ People don't like using slow applications. And the initial load time matters a lot for web applications and websites.  An application that takes more than 3 seconds to load is considered slow and may cause users to leave the application or website. N... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/next-js-performance-optimization/</link>
                <guid isPermaLink="false">66be00118c9c9099893ce790</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Fri, 19 Jul 2024 22:31:12 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/lazyloading-next.js.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>People don't like using slow applications. And the initial load time matters a lot for web applications and websites. </p>
<p>An application that takes more than 3 seconds to load is considered slow and may cause users to leave the application or website.</p>
<p><code>Next.js</code> is a React-based framework you can use to build scalable, performant, and faster web applications and websites. With the inclusion of <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-react-server-components/">React Server Components</a> in the Next.js app router release, developers have a new mental model for "thinking in a server components" way. It solves the problem with SEO, helps create <code>zero bundle size</code> React components, and the end result is faster loading of UI components.</p>
<p>But your application may not be always about the server components. You may need to use client components as well. Also, you may want to load them either as part of the application's initial load or on demand (say at the click of a button).</p>
<p>Loading a client component on the browser includes downloading the component code into the browser, downloading all the libraries and other components you had imported into that client component, and a few additional things that React takes care of for you to make sure your components are working. </p>
<p>Based on the user's internet connection and other network factors, the entire loading of the client component may take a while, which may keep your users from using the application more quickly.</p>
<p>This is where <code>Lazy Loading</code> techniques can come in handy. They can help save you from a monolithic loading of your client components on the browser. </p>
<p>In this article, we will discuss a couple of lazy loading techniques in Next.js for client component loading optimization. We will also talk about a few edge cases you should know to handle.</p>
<p>If you like to learn from video content as well, this article is also available as a video tutorial here: 🙂</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/gq9bBZru78Y" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>Before we get started, a couple of things for you:</p>
<ul>
<li>We will write a bunch of code to build an app to demonstrate the lazy loading techniques. You can find all the source code from this GitHub repository: <a target="_blank" href="https://github.com/tapascript/nextjs-lazy-load">https://github.com/tapascript/nextjs-lazy-load</a>. But I strongly suggest that you write the code yourself as we proceed and use the repository only as a reference.</li>
<li>You can also access the app deployed publicly <a target="_blank" href="https://nextjs-lazy-load.netlify.app/">on Netlify here</a>.</li>
</ul>
<p>Let's start 🚀. Oh yes, if you are Tom &amp; Jerry cartoon lover, you are going to enjoy this even more!</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-lazy-loading">What is Lazy Loading</a>?</li>
<li><a class="post-section-overview" href="#heading-lazy-loading-techniques-in-nextjs">Lazy Loading Techniques in Next.js</a></li>
<li><a class="post-section-overview" href="#heading-lazy-loading-with-dynamic-import-and-nextdynamic">Lazy Loading with dynamic import and next/dynamic</a></li>
<li><a class="post-section-overview" href="#heading-lazy-loading-with-reactlazy-and-suspense">Lazy Loading with React.lazy() and Suspense</a></li>
<li><a class="post-section-overview" href="#heading-how-to-lazy-load-the-named-exported-components">How to Lazy Load the Named Exported Components</a></li>
<li><a class="post-section-overview" href="#heading-lazy-loading-your-server-components-1">Lazy Loading Your Server Components</a></li>
<li><a class="post-section-overview" href="#heading-lazy-loading-your-server-components-1">Should We Lazy Load All Client Components in Next.js?</a></li>
<li><a class="post-section-overview" href="#heading-whats-next">What's Next?</a></li>
</ul>
<h2 id="heading-what-is-lazy-loading">What is Lazy Loading?</h2>
<p>In modern day web application development, we don't code all the logic in one JavaScript/TypeScript file, or all the styles into one mammoth CSS file. Rather, we split them at the source code level and create logical modules, business logic, presentational components, and style related files. This helps us organize our code better.</p>
<p>Then we use something called a bundler which kicks in at the build phase of the application development process. It creates bundles for our scripts and styles. Some of the famous bundlers are Webpack, Rollup, and Parcel, among others.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-43.png" alt="Image" width="600" height="400" loading="lazy">
<em>Bundler creating bundles from the source code</em></p>
<p>Now, as we have the bundles, if we try to load them on the browser all together, we will encounter some slowness. This is because the complete bundle needs to be loaded into the browser for the user interface to be functional. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-44.png" alt="Image" width="600" height="400" loading="lazy">
<em>Loading a huge bundle results in a poor loading experience</em></p>
<p>So, instead of waiting for the huge bundle to get loaded into the browser, modern web development libraries and tooling systems allow us to load the bundle in chunks. </p>
<p>We may want to load some of the chunks immediately, as users may need them sooner as the application loads. At the same time, we may want to wait to load certain parts of a web page until they're needed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-45.png" alt="Image" width="600" height="400" loading="lazy">
<em>Breaking into chunks and loading what is needed</em></p>
<p>This mechanism of waiting to load part of the pages or application, and loading them only when they are absolutely necessary, is called <code>Lazy Loading</code>. The concept of lazy loading is not React or Next.js-specific. It is a performance optimization technique that you can implement with various libraries and frameworks.</p>
<h2 id="heading-lazy-loading-techniques-in-nextjs">Lazy Loading Techniques in Next.js</h2>
<p>Lazy loading techniques in Next.js is used to reduce the amount of JavaScript needed by a route. This helps the initial load performance of the application be faster. We can defer the load of the client components and imported libraries until they are needed.</p>
<p>There are two ways we can implement lazy loading techniques in Next.js:</p>
<ul>
<li>Using dynamic imports with the help of the <code>next/dynamic</code> package.</li>
<li>Using a combination of <code>React.lazy()</code> and <code>Suspense</code>.</li>
</ul>
<p>Let's understand each of these techniques with code examples.</p>
<h2 id="heading-lazy-loading-with-dynamic-import-and-nextdynamic">Lazy Loading With <code>dynamic import</code> and <code>next/dynamic</code></h2>
<p><code>next/dynamic</code> is a combination of React.lazy() and Suspense from ReactJS. Using a dynamic import with the next/dynamic package is a preferred approach to achieve lazy loading in Next.js.</p>
<p>To demonstrate it, let's first create a Next.js app using the following command:</p>
<pre><code class="lang-bash">npx create-next-app@latest
</code></pre>
<p>You can start the app locally using the following command:</p>
<pre><code class="lang-bash"><span class="hljs-comment">## Using npm</span>
npm run dev

<span class="hljs-comment">## Using yarn</span>
yarn dev

<span class="hljs-comment">## Or use pnpm, bun, whatever you wish!</span>
</code></pre>
<p>Now create a folder called <code>components</code> under the <code>app/</code> directory. We will create all our components under the component folder. Now, create a folder called <code>tom</code> under the <code>app/components/</code>. Finally, create a React component called <code>tom.jsx</code> under the <code>app/components/tom/</code> directory with the following code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// tom.jsx</span>

<span class="hljs-keyword">const</span> LazyTom = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl my-2"</span>&gt;</span>The Lazy Tom<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>
        Tom, named <span class="hljs-symbol">&amp;quot;</span>Jasper<span class="hljs-symbol">&amp;quot;</span> in his debut appearance, is a gray and white
        domestic shorthair cat 🐈. <span class="hljs-symbol">&amp;quot;</span>Tom<span class="hljs-symbol">&amp;quot;</span> is a generic name for a male cat. He is
        usually but not always, portrayed as living a comfortable, or even
        pampered life. Tom is no match for Jerry<span class="hljs-symbol">&amp;apos;</span>s wits.
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>
        Although cats typically chase mice to eat them, it is quite rare for Tom
        to actually try to eat Jerry. He tries to hurt or compete with him just
        to taunt Jerry, even as revenge, or to obtain a reward from a human,
        including his owner(s)/master(s), for catching Jerry, or for generally
        doing his job well as a house cat. By the final <span class="hljs-symbol">&amp;quot;</span>fade-out<span class="hljs-symbol">&amp;quot;</span> of each
        cartoon, Jerry usually gets the best of Tom.
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> LazyTom;
</code></pre>
<p>To explain the above code:</p>
<ul>
<li>We have created a ReactJS component called <code>LazyTom</code>.</li>
<li>It is a simple presentational component which has a heading and a couple of paragraphs talking about the cat, Tom, from the famous <code>Tom &amp; Jerry</code> cartoon.</li>
<li>At the end, we have <code>default</code> exported the component to import it elsewhere.</li>
</ul>
<p>Now, create another file called <code>tom-story.jsx</code> under the <code>app/components/tom/</code> directory with the following code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// tom-story.jsx</span>

<span class="hljs-string">"use client"</span>;

<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> dynamic <span class="hljs-keyword">from</span> <span class="hljs-string">"next/dynamic"</span>;

<span class="hljs-keyword">const</span> LazyTom = dynamic(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">"./tom"</span>), {
    <span class="hljs-attr">loading</span>: <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Loading Tom<span class="hljs-symbol">&amp;apos;</span>s Story...<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>,
});

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TomStory</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [shown, setShown] = useState(<span class="hljs-literal">false</span>);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col m-8 w-[300px]"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>Demonstrating <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>dynamic<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-blue-600 text-white rounded p-1"</span>
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setShown(!shown)}
            &gt;
                Load 🐈 Tom<span class="hljs-symbol">&amp;apos;</span>s Story
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

            {shown &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">LazyTom</span> /&gt;</span>}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TomStory;
</code></pre>
<p>The main magic of lazy loading with <code>dynamic</code> is happening in the above code:</p>
<ul>
<li>We have created a client component called <code>TomStory</code> using the <code>"use client"</code> directive.</li>
<li>First, we have imported the <code>useState</code> hook for managing a toggle state, and the <code>dynamic</code> function from the <code>next/dynamic</code> for the lazy loading of the component we created before.</li>
<li>The <code>dynamic</code> function takes a function as an argument that returns the imported component. You can also configure a custom loading message by providing an optional configuration object as argument to the dynamic function. </li>
<li>The <code>dynamic()</code> function returns the lazily loaded component instance – that is, <code>LazyTom</code> (could be any name). But this component is not loaded yet.</li>
<li>In the JSX, we have a toggle button that shows and hides the <code>LazyTom</code> component. Note that the component will be lazy loaded into the user browser at the first instance of a button click. After that, if you hide and show it again, the <code>LazyTom</code> component will not be reloaded until we hard refresh the browser or clear the browser cache.</li>
<li>Finally, we have default exported the <code>TomStory</code> component.</li>
</ul>
<p>Now we need to test it out. To do that, open the <code>page.js</code> file in the <code>app/</code> directory and replace the content with the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> TomStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/tom/tom-story"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-wrap justify-center "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">TomStory</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>This is a simple ReactJS component that imports the <code>TomStory</code> component and uses it in its JSX. Now open your browser window. Open the browser's DevTools and open the <code>Network</code> tab. Make sure that the <code>All</code> filter is selected.</p>
<p>Now access the app on your browser using <code>http://localhost:3000</code>. You should see the button to load Tom's story. Also a bunch of resources will be listed on the <code>Network</code> tab. These are resources required in the initial load of the application and have been downloaded on your browser.</p>
<p>The <code>LazyTom</code> component from the <code>tom.jsx</code> has not been downloaded yet. This is because we haven't yet clicked on the <code>Load Tom's Story</code> button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-9.21.10-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>The button to lazy load Tom's story</em></p>
<p>Now, click on the button. You should see a loading message for a moment and then the component will be loaded with Tom's story. You can now see the <code>tom.jsx</code> component listed in the <code>Network</code> tab and also the component rendered on the page with the Tom's story.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-9.27.55-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Now Tom's story is lazily loaded</em></p>
<p>Now that you have experienced how the <code>dynamic</code> function from <code>next/dynamic</code> helps us load a component lazily, let's get started with the other technique using <code>React.lazy()</code> and <code>Suspense</code>.</p>
<h2 id="heading-lazy-loading-with-reactlazy-and-suspense">Lazy Loading with <code>React.lazy()</code> and <code>Suspense</code></h2>
<p>To demonstrate this technique, let's start with Jerry's story, my favourite character from the Tom &amp; Jerry cartoon. </p>
<p>First, we'll create a folder called <code>jerry</code> under the <code>app/components/</code> directory. Now, create a file called <code>jerry.jsx</code> under the <code>app/components/jerry/</code> with the following code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// jerry.jsx</span>

<span class="hljs-keyword">const</span> LazyJerry = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col justify-center"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl my-2"</span>&gt;</span>The Lazy Jerry<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>
        Jerry 🐀, whose name is not explicitly mentioned in his debut appearance,
        is a small, brown house mouse who always lives in close proximity to
        Tom. Despite being very energetic, determined and much larger, Tom is no
        match for Jerry<span class="hljs-symbol">&amp;apos;</span>s wits. Jerry possesses surprising strength for his
        size, approximately the equivalent of Tom<span class="hljs-symbol">&amp;apos;</span>s, lifting items such as
        anvils with relative ease and withstanding considerable impacts.
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>
        Although cats typically chase mice to eat them, it is quite rare for Tom
        to actually try to eat Jerry. He tries to hurt or compete with him just
        to taunt Jerry, even as revenge, or to obtain a reward from a human,
        including his owner(s)/master(s), for catching Jerry, or for generally
        doing his job well as a house cat. By the final <span class="hljs-symbol">&amp;quot;</span>fade-out<span class="hljs-symbol">&amp;quot;</span> of each
        cartoon, Jerry usually gets the best of Tom.
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> LazyJerry;
</code></pre>
<p>The content of <code>jerry.jsx</code> is structurally similar to <code>tom.jsx</code>. Here we have posted Jerry's story, instead of Tom's, and default exported the component.</p>
<p>Like the last time, let's create a <code>jerry-story.jsx</code> file to showcase the lazy loading of Jerry's story. Create the file under the <code>app/components/jerry/</code> directory with the following code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// jerry-story.jsx</span>

<span class="hljs-string">"use client"</span>;

<span class="hljs-keyword">import</span> React, { useState, Suspense } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> LazyJerry = React.lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./jerry'</span>));

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">JerryStory</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [shown, setShown] = useState(<span class="hljs-literal">false</span>);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col m-8 w-[300px]"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span> Demonstrating <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>React.lazy()<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-pink-600 text-white rounded p-1"</span>
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setShown(!shown)}
            &gt;
                Load 🐀 Jerry<span class="hljs-symbol">&amp;apos;</span>s Story
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

            {shown &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">h1</span>&gt;</span>Loading Jerry<span class="hljs-symbol">&amp;apos;</span>s Story<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>}&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">LazyJerry</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span>}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> JerryStory;
</code></pre>
<p>Here also we have a client component, and we will be using the <code>lazy()</code> method and <code>Suspense</code> from React, so we have imported them. Like the <code>dynamic()</code> function in the last technique, the <code>lazy()</code> function also takes a function as an argument that retrurns the lazily imported component. We have also provided the relative path to the component that we are trying to load.</p>
<p>Note that with <code>dynamic()</code> we had an opportunity to customize the loading message as part of the function itself. With <code>lazy()</code>, we will be doing that as part of the <code>Suspense</code> fallback. </p>
<p>Suspense uses a fallback when you wait for the data to load. If you would like to understand the Suspense and Error Boundary from ReactJS in-depth, you can <a target="_blank" href="https://www.youtube.com/watch?v=OpHbSHp8PcI">check out this video tutorial</a>. </p>
<p>Here, as our <code>LazyJerry</code> component is loading lazily, we have provided a fallback to show a loading message until the component code is download into the browser successfully and rendered.</p>
<pre><code class="lang-js">{shown &amp;&amp; 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">h1</span>&gt;</span>Loading Jerry<span class="hljs-symbol">&amp;apos;</span>s Story<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>}&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">LazyJerry</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span></span>
}
</code></pre>
<p>Also, as you can see, we are loading the component on the first button click. Here also, the component will not be reloaded every time we click on the button unless we refresh the browser or clear the browser cache.</p>
<p>Let's now test it by importing it into the <code>page.js</code> file and adding the component in its JSX.</p>
<pre><code class="lang-js"><span class="hljs-comment">// page.js</span>

<span class="hljs-keyword">import</span> TomStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/tom/tom-story"</span>;
<span class="hljs-keyword">import</span> JerryStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/jerry/jerry-story"</span>; 

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-wrap justify-center "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">TomStory</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">JerryStory</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Now, you'll see another component appear on the user interface with a button to load Jerry's story. At this stage, you will not see the jerry.jsx component loaded into the browser.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-9.33.36-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>The button to lazy load Jerry's story</em></p>
<p>Now, click on the button. You will see that the component is loaded, and you can see it on the Network tab list. You should be able to read Jerry's story rendered as part of the lazily loaded component.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-9.37.30-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Jerry's story is lazily loaded</em></p>
<h2 id="heading-how-to-lazy-load-the-named-exported-components">How to Lazy Load the Named Exported Components</h2>
<p>So far, with both the techniques we have imported a component that was exported with the <code>default export</code> and then lazy loaded it. In JavaScript (and so in React), you can export and import modules in two different ways:</p>
<ul>
<li>With the <code>default</code> keyword. In this case, the exported module can be imported with any name. You would use this if you wanted to export only one functionality from a module.</li>
<li>Without the <code>default</code> keyword, this is called a <code>named export</code>. In this case, you have to maintain the same module name for the export and import. You also need to enclose the module name in the curly brackets ({...}) while importing. You would use this if you wanted to export multiple functionalities from a module.</li>
</ul>
<p>If you want to get into JavaScript modules and how they work in greater detail, I would suggest going through <a target="_blank" href="https://www.youtube.com/watch?v=KeBxopnhizw">this crash course</a> published on freeCodeCamp's YouTube channel.</p>
<p>To demonstrate the lazy loading of a <code>named export</code> component, let's create another simple presentational React component. This time we will use the angry but cute dog named <code>Spike</code> from the Tom &amp; Jerry cartoon.</p>
<p>Create a folder called <code>spike</code> under the <code>app/components/</code> directory. Now, create a file called <code>spike.jsx</code> under the <code>app/components/spike/</code> directory with the following code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// spike.jsx</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> LazySpike = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl my-2"</span>&gt;</span>The Lazy Spike<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>
        In his attempts to catch Jerry, Tom often has to deal with Spike 🦮, known
        as <span class="hljs-symbol">&amp;quot;</span>Killer<span class="hljs-symbol">&amp;quot;</span> and <span class="hljs-symbol">&amp;quot;</span>Butch<span class="hljs-symbol">&amp;quot;</span> in some shorts, an angry, vicious but easily
        duped bulldog who tries to attack Tom for bothering him or his son Tyke
        while trying to get Jerry. Originally, Spike was unnamed and mute, aside
        from howls and biting noises as well as attacking indiscriminately, not
        caring whether it was Tom or Jerry though usually attacking Tom.
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>
      In
        later cartoons, Spike spoke often, using a voice and expressions,
        performed by Billy Bletcher and later Daws Butler, modeled after
        comedian Jimmy Durante. Spike<span class="hljs-symbol">&amp;apos;</span>s coat has altered throughout the years
        between gray and creamy tan. The addition of Spike<span class="hljs-symbol">&amp;apos;</span>s son Tyke in the
        late 1940s led to both a slight softening of Spike<span class="hljs-symbol">&amp;apos;</span>s character and a
        short-lived spin-off theatrical series called Spike and Tyke.
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>Again, this component is structurally exactly same as the <code>tom.jsx</code> and <code>jerry.jsx</code> components we have seen before, but with two major differences:</p>
<ol>
<li>Here, we have exported the component without the default keyword, hence it is a <code>named export</code>.</li>
<li>We are talking about the dog, Spike.</li>
</ol>
<p>Now, we need to handle the lazy loading of a named exported component and it's going to be a bit different from the default exported component.</p>
<p>Create a file called <code>spike-story.jsx</code> under the <code>app/components/spike/</code> directory with the following code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// spike-story.jsx</span>

<span class="hljs-string">"use client"</span>;

<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> dynamic <span class="hljs-keyword">from</span> <span class="hljs-string">"next/dynamic"</span>;

<span class="hljs-keyword">const</span> LazySpike = dynamic(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">"./spike"</span>).then(<span class="hljs-function">(<span class="hljs-params">mod</span>) =&gt;</span> mod.LazySpike), {
    <span class="hljs-attr">loading</span>: <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Loading Spike<span class="hljs-symbol">&amp;apos;</span>s Story...<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>,
});

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SpikeStory</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [shown, setShown] = useState(<span class="hljs-literal">false</span>);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col m-8 w-[300px]"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>Demonstrating <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Named Export<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-slate-600 text-white rounded p-1"</span>
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setShown(!shown)}
            &gt;
                Load 🦮 Spike<span class="hljs-symbol">&amp;apos;</span>s Story
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

            {shown &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">LazySpike</span> /&gt;</span>}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> SpikeStory;
</code></pre>
<p>Like <code>tom-story</code>, we are using the dynamic import with the next/dynamic. But let's zoom into the following block from the above code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> LazySpike = dynamic(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">"./spike"</span>).then(<span class="hljs-function">(<span class="hljs-params">mod</span>) =&gt;</span> mod.LazySpike), {
    <span class="hljs-attr">loading</span>: <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Loading Spike<span class="hljs-symbol">&amp;apos;</span>s Story...<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>,
});
</code></pre>
<p>The changes you will notice here are that we are resolving the promise explicitly from the <code>import("./spike")</code> function using the the <code>.then()</code> handler function. We get the module first, and then pick the exported component by its actual name – that is <code>LazySpike</code> in this case. The rest of the things remain the same as before as in the <code>tom-story</code>.</p>
<p>Now to test it out, again import the component into the <code>page.js</code> file, and use it in the JSX  like the last two times.</p>
<pre><code class="lang-js"><span class="hljs-comment">// page.js</span>

<span class="hljs-keyword">import</span> TomStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/tom/tom-story"</span>;
<span class="hljs-keyword">import</span> JerryStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/jerry/jerry-story"</span>;
<span class="hljs-keyword">import</span> SpikeStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/spike/spike-story"</span>; 

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-wrap justify-center "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">TomStory</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">JerryStory</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SpikeStory</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>There you go – you should see the new component rendered on the browser with a button to load Spike's story from the <code>spike.jsx</code> file which is not loaded yet.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-9.59.55-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>The button to lazy load Spike's story</em></p>
<p>Clicking on the button will load the file into the browser and render the component to show you Spike's story.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-10.02.01-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Spike's story is lazily loaded</em></p>
<p>Below you can see all three components demonstrating three different techniques and uses cases side-by-side. You can test them together. The image below is showcasing lazy loading of two components in parallel where another component was already lazily loaded.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-10.14.21-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Lazily loading multiple components in parallel</em></p>
<p>Here is another case where all three components were lazy loaded, on demand with the respective button clicks. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-10.05.35-AM-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>All the stories lazy loaded</em></p>
<h2 id="heading-lazy-loading-your-server-components">Lazy Loading Your Server Components</h2>
<p>We spoke about the lazy loading techniques of client components. Can we use the same on server components as well? Well, you can but you don't have to, as server components are already <code>code split</code> and the loading aspect is already been taken care of by Next.js. You are not going to get any kind of error if you are trying to do so, but it would be unnecessary. </p>
<p>In case, you are dynamically importing a server component that has one or more client components as children, those client components will be lazy loaded. But there won't be any impact on the (parent) server component itself.</p>
<p>Here is an example of a server component that has two client components as children:</p>
<pre><code class="lang-js"><span class="hljs-comment">// server-comp.jsx</span>

<span class="hljs-keyword">import</span> ComponentA <span class="hljs-keyword">from</span> <span class="hljs-string">"./a-client-comp"</span>;
<span class="hljs-keyword">import</span> ComponentB <span class="hljs-keyword">from</span> <span class="hljs-string">"./b-client-comp"</span>;

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>

<span class="hljs-keyword">const</span> AServerComp = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col m-8 w-[300px]"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ComponentA</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ComponentB</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AServerComp
</code></pre>
<p>Now, we are dynamically importing the server component into the <code>page.js</code> file and using it in its JSX. The child client components of the dynamically imported server component will be lazy loaded, but not the server component itself.</p>
<pre><code class="lang-js"><span class="hljs-comment">// page.js</span>

<span class="hljs-keyword">import</span> dynamic <span class="hljs-keyword">from</span> <span class="hljs-string">"next/dynamic"</span>;

<span class="hljs-keyword">import</span> TomStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/tom/tom-story"</span>;
<span class="hljs-keyword">import</span> JerryStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/jerry/jerry-story"</span>;
<span class="hljs-keyword">import</span> SpikeStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/spike/spike-story"</span>;

<span class="hljs-keyword">const</span> AServerComp = dynamic(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./components/server-comps/server-comp'</span>), {
  <span class="hljs-attr">loading</span>: <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Loading Through Server Component...<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>,
})


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-wrap justify-center "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">TomStory</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">JerryStory</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SpikeStory</span> /&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">AServerComp</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<h2 id="heading-should-we-lazy-load-all-client-components-in-nextjs">Should We Lazy Load All Client Components in Next.js?</h2>
<p>I had this question when I first started learning about lazy loading. Now that I have gained more experience with this technique, here is my perspective:</p>
<p>You don't have to lazy load all client components. Optimzation is great, but over optimization can have adverse effects. You need to identify where these optimizations are required. </p>
<ul>
<li>Do you have client components that are really bulky? </li>
<li>Are you unnecessarily putting so many things into one component that you should break it down and refactor? </li>
<li>Do you import heavy libraries into your client components? </li>
<li>Have you opted for tree-shaking? </li>
<li>Can you mark bulky client components per route and is it fine not to load some or all of them at the initial load of the page for that route?</li>
</ul>
<p>As you see, these are a bunch of meaningful questions to ask before you step into optimizing things. Once you have answers, and decide you need lazy loading, then you can implement the techniques you learned from this article.</p>
<h2 id="heading-whats-next">What's Next?</h2>
<p>That's all for now. Did you enjoy reading this article and have you learned something new? If so, I would love to know if the content was helpful. I have my social handles provided below.</p>
<p>Up next, if you are willing to learn <code>Next.js</code> and its ecosystem like <code>Next-Auth(V5)</code> with both fundamental concepts and projects, I have a great news for you: you can <a target="_blank" href="https://www.youtube.com/watch?v=VSB2h7mVhPg&amp;list=PLIJrr73KDmRwz_7QUvQ9Az82aDM9I8L_8">check out this playlist on my YouTube</a> channel with 20+ video tutorials and 11+ hours of engaging content so far, for free. I hope you like them as well.</p>
<p>Let's connect.</p>
<ul>
<li>Subscribe to my <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a>.</li>
<li><a target="_blank" href="https://twitter.com/tapasadhikary">Follow me on X (Twitter</a>) or <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of up-skilling tips.</li>
<li>Check out and follow my Open Source work on <a target="_blank" href="https://github.com/atapas">GitHub</a>.</li>
<li>I regularly publish meaningful posts on my <a target="_blank" href="https://blog.greenroots.info/">GreenRoots Blog</a>, you may find them helpful, too.</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself, and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Caching vs Content Delivery Networks – What's the Difference? ]]>
                </title>
                <description>
                    <![CDATA[ By Anamika Ahmed In the world of network optimization, Content Delivery Networks (CDNs) and caching play a vital role in improving website performance and user experience.  And while both aim to speed up website loading times, they have distinct purp... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/caching-vs-content-delivery-network/</link>
                <guid isPermaLink="false">66d45d99680e33282da25e0c</guid>
                
                    <category>
                        <![CDATA[ caching ]]>
                    </category>
                
                    <category>
                        <![CDATA[ content delivery network  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 01 Mar 2024 19:27:51 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/Conducting-Research-Projects-Educational-Presentation-in-Pink-and-Yellow-Colorful-Line-Style-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Anamika Ahmed</p>
<p>In the world of network optimization, Content Delivery Networks (CDNs) and caching play a vital role in improving website performance and user experience. </p>
<p>And while both aim to speed up website loading times, they have distinct purposes and mechanisms. </p>
<p>In this tutorial, we'll dive deep into the details of CDNs and caching to understand their similarities, differences, and how they contribute to enhancing online experiences.</p>
<h3 id="heading-heres-what-well-cover">Here's what we'll cover:</h3>
<ol>
<li><a class="post-section-overview" href="#heading-what-is-caching">What is Caching?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-a-content-delivery-network-cdn">What is a Content Delivery Network (CDN)?</a></li>
<li><a class="post-section-overview" href="#heading-caching-vs-cdns-whats-the-difference">Caching vs CDNs – What's the Difference?</a></li>
<li><a class="post-section-overview" href="#heading-when-to-use-caching">When to Use Caching</a></li>
<li><a class="post-section-overview" href="#heading-when-to-use-cdns">When to use CDNs</a></li>
<li><a class="post-section-overview" href="#heading-combining-caching-and-cdns">Combining Caching and CDNs</a></li>
<li><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></li>
</ol>
<h2 id="heading-what-is-caching">What is Caching?</h2>
<p>Imagine you’re a librarian managing a popular library. Every day, readers come in asking for the same set of books like “Think and Grow Rich” or “The Intelligent Investor.” </p>
<p>Initially, you fetch these books from the main shelves, which takes time and effort. But soon, you notice a pattern: the same set of books are requested repeatedly by different readers. So, what do you do?</p>
<p>You decide to create a special section near the entrance where you keep copies of these frequently requested books. Now, when readers come asking for them, you don’t have to run to the main shelves each time. Instead, you simply hand them the copies from the special section, saving time and making the process more efficient. </p>
<p>This special section represents the cache, storing frequently accessed books for quick retrieval.</p>
<p>Caching is a technique used to store copies of frequently accessed data temporarily. The cached data can be anything from web pages and images to database query results. When a user requests cached content, the server retrieves it from the cache instead of generating it anew, significantly reducing response times.</p>
<p>When a web server receives a request, it can follow different caching strategies to handle it efficiently. One prevalent strategy is known as read-through caching:</p>
<ol>
<li>Request Received: The web server gets a request from a client.</li>
<li>Check Cache: It first looks into the cache to see if the response to the request is already there.</li>
<li>Cache Hit: If the response is in the cache (hit), it sends the data back to the client right away.</li>
<li>Cache Miss: If the response isn’t in the cache (miss), the server queries the database to fetch the required data.</li>
<li>Store in Cache: Once it gets the data from the database, it stores the response in the cache for future requests.</li>
<li>Send Response: Finally, the server sends the data back to the client.</li>
</ol>
<h3 id="heading-what-to-consider-when-implementing-a-cache-system">What to Consider When Implementing a Cache System</h3>
<h4 id="heading-decide-when-to-use-a-cache">Decide When to Use a Cache:</h4>
<ul>
<li>A cache is best for frequently read but infrequently modified data.</li>
<li>Cache servers are not suitable for storing critical data as they use volatile memory.</li>
<li>Important data should be stored in persistent data stores to prevent loss in case of cache server restarts.</li>
</ul>
<h4 id="heading-set-an-expiration-policy">Set an Expiration Policy:</h4>
<ul>
<li>Implement an expiration policy to remove expired data from the cache.</li>
<li>Avoid setting expiration dates too short (to prevent frequent database reloads), and too long (to prevent stale data).</li>
</ul>
<h4 id="heading-maintain-synchronization-between-data-stores-and-cache">Maintain Synchronization Between Data Stores and Cache</h4>
<ul>
<li>Inconsistencies can arise due to separate operations on data storage and cache, especially in distributed environments.</li>
</ul>
<h4 id="heading-mitigate-failures">Mitigate Failures:</h4>
<ul>
<li>Use multiple cache servers across different data centers to avoid single points of failure.</li>
<li>Over-provision memory to accommodate increased usage and prevent performance issues.</li>
</ul>
<h4 id="heading-implement-an-eviction-policy">Implement an Eviction Policy:</h4>
<ul>
<li>When the cache is full, new items may cause existing ones to be removed (cache eviction).</li>
<li>A popular eviction policy is Least Recently Used (LRU), but other policies like Least Frequently Used (LFU) or First In, First Out (FIFO) can be chosen based on specific use cases.</li>
</ul>
<h3 id="heading-real-world-applications-of-caching">Real-World Applications of Caching</h3>
<p><strong>Social Media Platforms:</strong> Imagine scrolling through your Facebook feed. Thanks to caching, you see profile pictures, trending posts, and recently liked content instantly, even if millions of users are accessing the platform simultaneously. </p>
<p>Caching these frequently accessed elements on servers or your device minimizes delays and makes the experience smoother and more engaging.</p>
<p><strong>E-commerce Websites:</strong> When browsing Amazon for a new gadget, you expect a seamless shopping experience. Caching plays a crucial role here. Product images, descriptions, and pricing information are cached, enabling the website to display search results and product pages rapidly. </p>
<p>This is especially crucial during peak seasons like Black Friday or Cyber Monday, where caching helps handle surges in traffic and ensures customers can complete their purchases without encountering delays.</p>
<p><strong>Content Management Systems (CMS):</strong> Millions of websites rely on CMS platforms like WordPress. To ensure smooth performance for all these users, many CMS platforms integrate caching plugins. These plugins cache frequently accessed pages, reducing the load on the server and database. </p>
<p>This translates to faster page loading times, improved SEO ranking due to faster indexing by search engines, and a more responsive website overall, providing a better experience for visitors.</p>
<h2 id="heading-what-is-a-content-delivery-network-cdn">What is a Content Delivery Network (CDN)?</h2>
<p>Now, think of a CDN as a global network of book delivery trucks. Instead of storing all the books in one central library, you have local branches worldwide, each with copies of the most popular books. </p>
<p>When readers request a book, you don’t have to ship it from the main library. Instead, you direct them to the nearest branch, where they can quickly pick up a copy. This cuts down on travel time (data transfer time) and keeps everyone happy with fast access to their favorite books.</p>
<p>In technical terms, a CDN is a network of servers distributed across various locations globally. Its primary purpose is to deliver web content, such as images, videos, scripts, and stylesheets to users more efficiently by reducing the physical distance between the server and the user.</p>
<h3 id="heading-how-cdns-work">How CDNs Work:</h3>
<p>First, imagine that User A wants to see an image on a website. They click on a link provided by the CDN, like “<a target="_blank" href="https://mysite.cloudfront.net/logo.jpg">https://mywebsite.cloudfront.net/image.jpg</a>". This requests the image.</p>
<p>Then, if the image isn’t in the CDN’s storage (cache), the CDN fetches the image from the original source, like a web server or Amazon S3.</p>
<p>In response to that, the original source sends the image back to the CDN. It might include a Time-to-Live (TTL) header, indicating how long the image should stay cached.</p>
<p>Next, the the CDN stores the image and serves it to User A. It stays cached until the TTL expires.</p>
<p>Then let's say that user B requests the same image. At that point, the CDN checks if it’s still in the cache. If the image is still cached (TTL hasn’t expired), the CDN serves it from there (a hit). Otherwise (a miss), it fetches a fresh copy from the origin.</p>
<h3 id="heading-what-to-consider-when-implementing-a-cdn">What to Consider When Implementing a CDN</h3>
<ul>
<li><strong>Cost Management</strong>: CDNs charge for data transfers. It’s wise to cache frequently accessed content, but not everything.</li>
<li><strong>Cache Expiry</strong>: Set appropriate cache expiry times. Too long, and content might be stale. Too short, and it strains origin servers.</li>
<li><strong>CDN Fallback</strong>: Plan for CDN failures. Ensure your website can switch to fetching resources directly from the origin if needed.</li>
<li><strong>Invalidating Files</strong>: You can remove files from the CDN before they expire using various methods provided by CDN vendors.</li>
</ul>
<h3 id="heading-real-world-applications-of-a-cdn">Real-World Applications of a CDN</h3>
<p><strong>Video Streaming Services:</strong> Imagine you're in Sydney, Australia, craving to watch the latest season of your favorite show on Netflix. Without a CDN, the data would have to travel all the way from a server in, say, California, leading to buffering and frustrating delays. </p>
<p>But thanks to CDNs, Netflix caches popular content on edge servers closer to you, in Sydney or its surrounding region. This significantly reduces the distance the data needs to travel, ensuring smooth playback and an uninterrupted viewing experience, regardless of your location. </p>
<p>In fact, studies show that CDNs can <strong>reduce video startup time by up to 50%</strong>, making a significant difference in user satisfaction.</p>
<p><strong>Gaming Content Distribution:</strong> Gamers know the pain of waiting for massive game updates or DLC downloads. But companies like Steam and Epic Games leverage CDNs to make things faster. </p>
<p>These platforms cache game files, updates, and multiplayer assets on edge servers close to gaming communities. This means whether you're downloading a new game in New York or patching your favorite title in Tokyo, the data doesn't have to travel across continents. </p>
<p>Using CDNs can decrease download times quite a bit, leading to quicker access to the games you love and smoother multiplayer experiences with minimal lag.</p>
<p><strong>Global News Websites:</strong> Staying informed about global events shouldn't be hindered by slow loading times. Major news organizations like BBC News and The New York Times use CDNs to ensure their breaking news updates and multimedia content reach audiences worldwide instantly. </p>
<p>By caching critical information like articles, videos, and images on servers across different continents, CDNs enable news websites to deliver real-time updates quickly, keeping readers informed regardless of their location. </p>
<p>During major events or emergencies, this can be especially crucial, as evidenced by a case study where a news organization using a CDN reported a <strong>20% increase in website traffic without any performance issues</strong> during a breaking news event.</p>
<h2 id="heading-caching-vs-cdns-whats-the-difference">Caching vs CDNs – What's the Difference?</h2>
<h3 id="heading-similarities-between-caching-and-cdns">Similarities between caching and CDNs:</h3>
<p><strong>Improved Performance:</strong> Both CDNs and caching aim to enhance website performance by reducing latency and speeding up content delivery.</p>
<p><strong>Efficient Resource Utilization:</strong> By serving cached or replicated content, both approaches help optimize resource utilization and reduce server load.</p>
<p><strong>Enhanced User Experience:</strong> Faster load times lead to a better user experience, whether achieved through CDNs or caching.</p>
<h3 id="heading-differences-between-caching-and-cdns">Differences between Caching and CDNs</h3>
<h4 id="heading-scope">Scope:</h4>
<ul>
<li>CDNs: CDNs are a network of servers located in different geographic locations around the world.</li>
<li>Caching: Caching is a method of storing web content on a user’s local device or server.</li>
</ul>
<h4 id="heading-implementation">Implementation:</h4>
<ul>
<li>CDNs: CDNs require a separate infrastructure and configuration.</li>
<li>Caching: Caching can be implemented within a web application or server using caching rules and directives.</li>
</ul>
<h4 id="heading-geographic-coverage">Geographic Coverage:</h4>
<ul>
<li>CDNs: Designed to deliver web content to users across the world.</li>
<li>Caching: Typically used to improve performance for individual users or within a local network.</li>
</ul>
<h4 id="heading-network-architecture">Network Architecture:</h4>
<ul>
<li>CDNs: Use a distributed network of servers to cache and deliver content.</li>
<li>Caching: This can be implemented using various types of storage such as local disk, memory, or a server-side cache.</li>
</ul>
<h4 id="heading-performance-benefits">Performance Benefits:</h4>
<ul>
<li>CDNs: Provide faster and more reliable content delivery by caching content in multiple locations.</li>
<li>Caching: Improves performance by reducing the number of requests to the origin server and delivering content faster from a local cache.</li>
</ul>
<h4 id="heading-cost">Cost:</h4>
<ul>
<li>CDNs: Can be more expensive to implement and maintain due to the need for a separate infrastructure and ongoing costs for network maintenance.</li>
<li>Caching: Can be implemented using existing infrastructure and server resources, potentially reducing costs.</li>
</ul>
<h2 id="heading-when-to-use-caching">When to use Caching</h2>
<p>Caching is ideal for frequently accessed content that doesn't change frequently. This includes static assets like images, CSS files, and JavaScript libraries.</p>
<p>It's particularly effective for websites with a substantial user base accessing similar content, such as news websites, blogs, and e-commerce platforms.</p>
<p>Caching can also significantly reduce server load and improve response times for users, especially in scenarios where content delivery latency is a concern.</p>
<h2 id="heading-when-to-use-cdns">When to use CDNs</h2>
<p>CDNs are invaluable for delivering content to a global audience, especially when geographical distance between users and origin servers leads to latency issues.</p>
<p>They are well-suited for serving dynamic content, streaming media, and handling sudden spikes in traffic.</p>
<p>CDNs also excel in scenarios where content needs to be delivered reliably and consistently across diverse geographic regions, ensuring optimal user experience regardless of location.</p>
<h2 id="heading-combining-caching-and-cdns">Combining Caching and CDNs</h2>
<p>In many scenarios, employing both caching and CDNs together yields optimal results, particularly for dynamic websites and applications where a mix of static and dynamic content delivery is essential. Let's consider a popular news website as an example.</p>
<p>Imagine a bustling news website that regularly publishes breaking news articles, accompanied by images and videos. While the core news content is dynamic and frequently updated, the images and videos associated with older articles remain relatively static and are accessed repeatedly by users.</p>
<p>To address this, the website can implement a combined strategy:</p>
<ol>
<li><strong>Caching on the Origin Server:</strong> Frequently accessed elements like website templates, navigation menus, and static content are cached directly on the origin server. This caching reduces server load and enhances performance for initial page loads.</li>
<li><strong>CDN Caching:</strong> The website leverages a CDN to cache frequently accessed images and videos associated with news articles on edge servers located worldwide. This ensures that users, regardless of their geographic location, can swiftly access these elements with minimal latency.</li>
</ol>
<p>There are many benefits of the combined approach, such as:</p>
<ul>
<li><strong>Faster Loading Times:</strong> By serving cached content from both the origin server and CDN edge servers, users experience significantly faster loading times, leading to a more engaging browsing experience.</li>
<li><strong>Reduced Server Load:</strong> Caching alleviates pressure on the origin server, enabling it to efficiently process dynamic content updates while serving static elements from cache.</li>
<li><strong>Improved Global Reach:</strong> The CDN ensures that users worldwide can access the website and its content with minimal delays, irrespective of their proximity to the origin server.</li>
</ul>
<p>But there are also some factors to consider:</p>
<ul>
<li><strong>Cache Invalidation:</strong> Regularly updating cached content ensures users access the latest information. Most CDNs offer efficient cache invalidation mechanisms to facilitate this process.</li>
<li><strong>Cost Optimization:</strong> While combining caching and CDNs enhances performance, it's crucial to evaluate the cost-effectiveness of caching specific content. Analyzing user access patterns helps determine the optimal caching strategy.</li>
</ul>
<p>By strategically combining caching and CDNs, you and your team can create a robust content delivery infrastructure that delivers a superior user experience worldwide.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Both CDNs and caching play crucial roles in optimizing website performance and user experience by speeding up content delivery. </p>
<p>While caching stores frequently accessed data locally for quick retrieval, CDNs provide a geographically distributed network of servers to deliver content efficiently to users worldwide. </p>
<p>Understanding their similarities in performance improvement and resource utilization, as well as their key differences in scope, implementation, and cost is crucial for choosing the right approach for your specific needs.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Perform Performance Testing on Your Web Applications ]]>
                </title>
                <description>
                    <![CDATA[ Performance testing is an important yet underrated field of software development. And it’s a must-have skill that can help you prevent common software failures that occur in production applications.  Performance testing is a routine software practice... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/performance-testing-for-web-applications/</link>
                <guid isPermaLink="false">66bb58d1074d8d7b12eae39a</guid>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Mon, 26 Feb 2024 19:52:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/performance-test2.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Performance testing is an important yet underrated field of software development. And it’s a must-have skill that can help you prevent common software failures that occur in production applications. </p>
<p>Performance testing is a routine software practice which is carried out to determine the stability of a system in terms of scalability, reliability, and data management, among other parameters.</p>
<p>In this tutorial, I'll walk you through what performance testing entails, and the common tools used for backend testing. We'll also walk through a demo performance testing project together. </p>
<p>The tutorial is simplified and suitable for beginners, mid-level developers, and professional developers. Being proficient in performance testing is fundamental to growing as a backend developer, and this guide will serve as a good review even if you're more advanced in your career. With that said, let's dive in.</p>
<h3 id="heading-prerequisites">Prerequisites:</h3>
<ul>
<li>Intermediate knowledge of Node.js</li>
<li>Basic knowledge of JavaScript operations</li>
<li>Knowledge of API development\</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents:</h2>
<ol>
<li><a class="post-section-overview" href="#heading-what-is-performance-testing">What is Performance Testing?</a></li>
<li><a class="post-section-overview" href="#heading-examples-of-performance-testing-tools">Examples of Performance Testing Tools</a></li>
<li><a class="post-section-overview" href="#heading-demo-project">Demo Project</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<h2 id="heading-what-is-performance-testing">What is Performance Testing?</h2>
<p>Performance testing serves quite a lot of purposes – one of the most important of which is to test system efficiency in performing and sustaining tasks. It also serves as a standard you can use to compare systems of varying efficiency and builds and enables you to choose the most effective one.</p>
<p>Performance testing also helps reveal vulnerabilities. State-of-the-art testing tools are well optimized to efficiently analyze the code to detect any errors. They're quick to highlight the areas where these errors occur.</p>
<p>The end goal of performance testing is dependent how you're using the application. It might be concurrency-oriented or transaction rate-oriented, depending on whether the app involves end users or not. </p>
<p>Performance testing could also involve load testing, which is usually carried out to evaluate the behavior of a web service under a specific expected load. Other types of testing you can do include integration testing, spike testing, soak testing, and stress testing.</p>
<h2 id="heading-examples-of-performance-testing-tools">Examples of Performance Testing Tools</h2>
<p>There are many tools commonly used to test the efficacy and latency of web applications. In this section, I'll discuss some of the popular tools used, and highlight their strengths and use cases.</p>
<h3 id="heading-jest">Jest</h3>
<p><a target="_blank" href="https://www.npmjs.com/package/jest">Jest</a> is a multi-platform testing tool used to assess the correctness of JavaScript-based applications. It's the one we'll be using in this demo. </p>
<p>Jest was initially created to test the efficiency of React applications, but has since been extended to test the efficiency of Node.js apps as well. It also offers a code coverage feature.</p>
<h3 id="heading-mocha">Mocha</h3>
<p><a target="_blank" href="https://www.npmjs.com/package/mocha">Mocha</a> is a concise asynchronous JavaScript-based testing tool for Node.js applications. It is also used with assertion libraries such as <code>[Chai]( https://www.npmjs.com/package/chai)</code> and <code>[should]( https://www.npmjs.com/package/should)</code>.</p>
<h3 id="heading-pythagora">Pythagora</h3>
<p><a target="_blank" href="https://github.com/Pythagora-io/pythagora">Pythagora</a> offers a unique integrating testing feature to help test how different part of the application works together. It also has a code coverage feature.</p>
<h3 id="heading-artillery">Artillery</h3>
<p><a target="_blank" href="https://artillery.io">Artillery</a> is a stack agnostic testing tool. This means it can be used for multiple web applications based on different programming languages and still produce an optimal test outcome. </p>
<p>This tool provides efficient load testing features which help to determine the optimal status of the application when exposed to a large load of traffic. It also checks the speed at which an app responds to a user request without crashing. </p>
<h3 id="heading-ava">Ava</h3>
<p><a target="_blank" href="https://www.npmjs.com/package/ava">Ava</a> is a JavaScript-based performance unit testing tool used to test the efficacy of Node.js applications. It works asynchronously, running multiple concurrent tests to determine the suitability of multiple code units.</p>
<h3 id="heading-loadtest">Loadtest</h3>
<p><a target="_blank" href="https://www.npmjs.com/package/loadtest">Loadtest</a> is a special Node package which is used to load test Node.js applications. It evaluates their ability to cope with requests of varying volumes and it evaluates for efficiency and concurrency.</p>
<h3 id="heading-apache-j-meter">Apache J-meter</h3>
<p><a target="_blank" href="https://jmeter.apache.org">Apache J-meter</a> offers load-testing features for web applications. It has an in-built IDE to enable interaction with the user. It is multithreaded, increasing its ability to mimic several users.</p>
<p>There are other testing tools which are also useful. But in this tutorial, we will be utilizing <code>Jest</code> to test our back-end application.</p>
<h2 id="heading-demo-project">Demo Project</h2>
<h3 id="heading-install-jest">Install Jest</h3>
<p>We'll now perform a unit test on our code using the <code>Jest</code> testing tool. To do this, you'll need to install the <code>Jest</code> package in your code folder. Type <code>npm install jest</code> in the command prompt. A success message will be displayed when the installation is completed.</p>
<h3 id="heading-configure-packagejson">Configure <code>package.json</code></h3>
<p>In this tutorial, we'll test the efficiency of some selected routes in our Node.js application. This will necessitate writing different unit tests for each route and evaluating its correctness. </p>
<p>Now let’s optimize our file structure to successfully unit test our application. Navigate to the <code>package.json</code> file and edit it to include the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"test"</span>: <span class="hljs-string">" jest"</span>,
    <span class="hljs-string">"start"</span>: <span class="hljs-string">"nodemon index.js"</span>
  },
</code></pre>
<p>Modifying the package.json file to include this code ensures that the Node.js server recognizes Jest as our default unit testing tool for the project. By so doing, any time we enter <code>npm test</code> in the command prompt, Jest gets activated.</p>
<h3 id="heading-set-up-the-test-environment">Set up the test environment</h3>
<p>Create a folder in the <code>root</code> directory named “tests”. This helps the Jest operator locate the specific files housing the routes to be tested. </p>
<p>Within the test folder, create a test file. The file can be named whatever you prefer, but the suffix <code>.test.js</code> should be added to enable <code>Jest</code> to recognize it and execute it.</p>
<p>After completing these steps, let’s get into the core details of unit testing in our project.</p>
<h3 id="heading-run-the-unit-tests">Run the unit tests</h3>
<p>The demo project we'll test in this tutorial is an eBook library application which contains some functions such as a <code>get all books</code> route, <code>Get a single book</code> route, <code>upload a book</code> route, and <code>delete a book</code> route.  We'll create unit tests for the <code>GetAllBooks</code> route in the example below, and then you can try to create your own for the other routes.</p>
<p>So firstly, we'll import the book database into the test.js file like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Book = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../models/Book'</span>)
</code></pre>
<p>The code above imports and initializes our default book MongoDB database model.</p>
<p>Then we'll import the functions that we'll test in each route:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Book =  <span class="hljs-built_in">require</span>(<span class="hljs-string">"../models/Book"</span>)

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">GetAllBooks</span> (<span class="hljs-params">req, res</span>)  </span>{
    <span class="hljs-keyword">try</span> {
<span class="hljs-keyword">const</span> allBooks =  <span class="hljs-keyword">await</span> Book.find();
res.status(<span class="hljs-number">200</span>)
res.send(allBooks)
    }
    <span class="hljs-keyword">catch</span> (err) {
res.status(<span class="hljs-number">500</span>)
res.send(err) 
    }
}
<span class="hljs-built_in">module</span>.exports = {GetAllBooks};
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> {GetAllBooks} = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../controllers/Books"</span>);
</code></pre>
<p>The code above imports the getAllBooks function from a controller folder. </p>
<p>Having imported the function, let's now go ahead to setup our Jest unit test function.</p>
<pre><code class="lang-javascript">jest.mock(<span class="hljs-string">"../models/Book"</span>);

<span class="hljs-keyword">const</span> req = {};
<span class="hljs-keyword">const</span> res = {
  <span class="hljs-attr">status</span>: jest.fn(<span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> x),
  <span class="hljs-attr">send</span>: jest.fn(<span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> x),
};

it(<span class="hljs-string">"it should return all the books in the database"</span>, <span class="hljs-keyword">async</span> () =&gt; {

Book.find.mockImplementationOnce(<span class="hljs-function">() =&gt;</span> ({
    <span class="hljs-attr">Title</span>: <span class="hljs-string">"black is king"</span>,
    <span class="hljs-attr">Author</span>: <span class="hljs-string">"black"</span>,
    <span class="hljs-attr">price</span>: <span class="hljs-string">"$23"</span>,
    <span class="hljs-attr">Summary</span>: <span class="hljs-string">"Hello"</span>,
  }));

  <span class="hljs-keyword">await</span> GetAllBooks(req, res);


expect(res.status).toHaveBeenCalledWith(<span class="hljs-number">200</span>);

expect(res.send).toHaveBeenCalledTimes(<span class="hljs-number">1</span>);
});
</code></pre>
<p>First of all, Jest offers you the ability to create a fake database by copying the structure of the default database. This is known as mocking. This enables the unit test to operate faster and eliminate the lag that comes with getting responses from large databases. </p>
<p>Testing which involves the real database is referred to as end-to-end testing as opposed to unit testing.</p>
<p>Here's how you can do that in Jest:</p>
<pre><code class="lang-javascript">jest.mock(<span class="hljs-string">"../models/Book"</span>);
</code></pre>
<p>The code above illustrates database mocking. In order to get a faster unit test, we have to mock the existing Book database model we're using in our application.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> req = {};
<span class="hljs-keyword">const</span> res = {
  <span class="hljs-attr">status</span>: jest.fn(<span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> x),
  <span class="hljs-attr">send</span>: jest.fn(<span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> x),
};
</code></pre>
<p>The above code contains the default sample requests and response objects. The sample response object contains both the status and send functions, which return a defined output if executed successfully or not.</p>
<pre><code class="lang-javascript">it(<span class="hljs-string">"it should return all the books in the database"</span>, <span class="hljs-keyword">async</span> () =&gt; {
Book.find.mockImplementationOnce(<span class="hljs-function">() =&gt;</span> ({
    <span class="hljs-attr">Title</span>: <span class="hljs-string">"black is king"</span>,
    <span class="hljs-attr">Author</span>: <span class="hljs-string">"black"</span>,
    <span class="hljs-attr">price</span>: <span class="hljs-string">"$23"</span>,
    <span class="hljs-attr">Summary</span>: <span class="hljs-string">"Hello"</span>,
  }));
  <span class="hljs-keyword">await</span> GetAllBooks(req, res); 
expect(res.status).toHaveBeenCalledWith(<span class="hljs-number">200</span>);
expect(res.send).toHaveBeenCalledTimes(<span class="hljs-number">1</span>);
});
</code></pre>
<p>Now the <code>It</code> function contains a short description of what the test should be about. This is then coupled to an anonymous asynchronous function which contains a mock implementation of the database model with some dummy data.</p>
<p>After that, the getAllBooks request is triggered and executed with a null request passed to it and the format of the response object is included.</p>
<p>The <code>expect</code> statement returns <code>passed</code> if the function satisfies the requirements expected. For this code, the requirements are that the <code>response</code> object should return a status code of 200 and the <code>response.send</code> object should be called at least once with the response object included. If it fails, a failed status will be returned.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/test.JPG" alt="Image" width="600" height="400" loading="lazy">
<em>Tests passing</em></p>
<p>You now know the basics of how to unit test functions. You can also try to test the <code>delete book</code> route, <code>upload a book</code> route and <code>find a specific book</code> route.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you've been able to harness the usefulness of testing tools in optimizing your web applications. </p>
<p>You've learned about various testing tools available and their use cases, and you also implemented a unit test in a web application.  </p>
<p>Following the steps highlighted in this tutorial, you will be able to perform unit tests on your coding projects.</p>
<p>I sincerely hope you learned something new and enjoyed this tutorial. Until next time, keep on coding.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Optimize Your CSS Code for Faster Web Pages ]]>
                </title>
                <description>
                    <![CDATA[ CSS is more than just a tool for styling. It also determines how web pages render in a browser. Well-optimized CSS means faster loading times and a smoother user experience. In today's digital landscape, the performance of a website is a key factor i... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-optimize-your-css-code-for-faster-web-pages/</link>
                <guid isPermaLink="false">66c5a33d5e24e23ff2251593</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ophy Boamah ]]>
                </dc:creator>
                <pubDate>Fri, 26 Jan 2024 13:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/csstitle.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>CSS is more than just a tool for styling. It also determines how web pages render in a browser. Well-optimized CSS means faster loading times and a smoother user experience.</p>
<p>In today's digital landscape, the performance of a website is a key factor in its success. Writing efficient CSS code can greatly influence how quickly your web pages load, impacting everything from user experience to search engine rankings. </p>
<p>This guide delves into effective strategies to help you refine your CSS, ensuring that your website not only looks great but also loads swiftly and runs smoothly.</p>
<h2 id="heading-how-css-affects-web-performance">How CSS affects Web Performance</h2>
<p>When a user visits a webpage, the browser retrieves the site's structural HTML and its stylistic CSS. This is a set of detailed instructions on how each part of the webpage should look. </p>
<p>If the CSS is packed with too much information or is too complex, it's like giving the browser a puzzle that takes longer to solve. This can lead to longer waiting times for users, which can be annoying.</p>
<p>That's where the art of streamlining CSS comes into play. It's not just about tidying up the code, but also making sure the browser can get the webpage ready faster. </p>
<p>When CSS is made leaner and simpler, it's like giving the browser a clear, easy-to-follow map. This makes webpages load faster, making everything feel more responsive. </p>
<h2 id="heading-1-write-shorter-css">1. Write Shorter CSS</h2>
<p>When writing CSS, use the popular software development principle Don’t Repeat Yourself (DRY). This advocates for conciseness and clarity in your code. </p>
<p>This is important here, because in practice, CSS involves repeating properties across various selectors. The goal should be to identify and consolidate these repetitive properties. By doing so you eliminate redundancies, leading to cleaner and more manageable CSS.</p>
<p>For instance, in the code below, multiple elements (<code>h1</code>and <code>h2</code>) share the same font-size and color. </p>
<pre><code class="lang-css"><span class="hljs-selector-tag">h1</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
}
<span class="hljs-selector-tag">h2</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
}
</code></pre>
<p>So instead of declaring these properties separately for each selector, you can group them under a common class. This not only streamlines your stylesheet but also makes future updates easier and less error-prone.</p>
<p>You can rewrite the above code to look like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">h1</span>, <span class="hljs-selector-tag">h2</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
}
</code></pre>
<p>Using shorthand properties is another effective strategy for minimizing the size of your CSS, making your code more efficient. It also allows you to set multiple related CSS properties with a single declaration. Here's how you can write effective shorthand CSS:</p>
<p>When all sides of an element have the same value, use that one value.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Before shorthand */</span>
<span class="hljs-selector-class">.same-sides</span> {
    <span class="hljs-attribute">padding-top</span>: <span class="hljs-number">15px</span>;
    <span class="hljs-attribute">padding-right</span>: <span class="hljs-number">15px</span>;
    <span class="hljs-attribute">padding-bottom</span>: <span class="hljs-number">15px</span>;
    <span class="hljs-attribute">padding-left</span>: <span class="hljs-number">15px</span>;
}

<span class="hljs-comment">/* After shorthand */</span>
<span class="hljs-selector-class">.same-sides</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">15px</span>;
}
</code></pre>
<p>When all sides of an element have different values, use all four.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Before shorthand */</span>
<span class="hljs-selector-class">.different-sides</span> {
    <span class="hljs-attribute">padding-top</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">padding-right</span>: <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">padding-bottom</span>: <span class="hljs-number">15px</span>;
    <span class="hljs-attribute">padding-left</span>: <span class="hljs-number">25px</span>;
}

<span class="hljs-comment">/* After shorthand */</span>
<span class="hljs-selector-class">.different-sides</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span> <span class="hljs-number">20px</span> <span class="hljs-number">15px</span> <span class="hljs-number">25px</span>;
}
</code></pre>
<p>When top/bottom and right/left have the same value, use two values.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Before shorthand */</span>
<span class="hljs-selector-class">.two-sides</span> {
    <span class="hljs-attribute">padding-top</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">padding-right</span>: <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">padding-bottom</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">padding-left</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-comment">/* After shorthand */</span>
<span class="hljs-selector-class">.two-sides</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span> <span class="hljs-number">20px</span>;
}
</code></pre>
<p>When only the right/left values are the same but the top and bottom aren't, use three values.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Before shorthand */</span>
<span class="hljs-selector-class">.three-sides</span> {
    <span class="hljs-attribute">padding-top</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">padding-right</span>: <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">padding-bottom</span>: <span class="hljs-number">15px</span>;
    <span class="hljs-attribute">padding-left</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-comment">/* After shorthand */</span>
<span class="hljs-selector-class">.three-sides</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span> <span class="hljs-number">20px</span> <span class="hljs-number">15px</span>;
}
</code></pre>
<h2 id="heading-2-use-shallow-css-selectors">2. Use Shallow CSS Selectors</h2>
<p>Shallow CSS selectors are direct and concise selectors with fewer levels of nested elements that don't dig too deep into the HTML structure. </p>
<p>Simplifying your selectors can significantly speed up your webpage rendering because deeply nested selectors take longer for browsers to evaluate, which results in a slower page render.</p>
<p>Consider the example in the code below: to assign property values to a deeply nested selector like <code>header nav ul li a</code> is cumbersome and will cause rendering delays because the browser needs time to check each level (header, then nav, then ul, and so on) to find the right <strong><code>&lt;a&gt;</code></strong> tag to style). </p>
<p>Alternatively, giving it a direct class <code>.nav-link</code> is straightforward and quicker for browsers to interpret. Class selectors are generally more efficient than nested tags because the browser simply looks for elements with a class and applies the styles, without worrying about their position in the DOM tree.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Less efficient: Deeply nested selector */</span>
<span class="hljs-selector-tag">header</span> <span class="hljs-selector-tag">nav</span> <span class="hljs-selector-tag">ul</span> <span class="hljs-selector-tag">li</span> <span class="hljs-selector-tag">a</span> { 
   <span class="hljs-attribute">color</span>: <span class="hljs-number">#000</span>;
   <span class="hljs-attribute">font-size</span>: <span class="hljs-number">10px</span>;
 }

<span class="hljs-comment">/* More efficient: Class selector */</span>
<span class="hljs-selector-class">.nav-link</span> {
   <span class="hljs-attribute">color</span>: <span class="hljs-number">#000</span>;
   <span class="hljs-attribute">font-size</span>: <span class="hljs-number">10px</span>;
}
</code></pre>
<h2 id="heading-3-segment-css-code">3. Segment CSS Code</h2>
<p>Segmenting your CSS code into smaller, more focused segments like separate files for different website components and creating page-specific styles can greatly improve your website's performance. This approach not only makes it easier to find and edit specific styles but also ensures that webpages load only the CSS they need, avoiding unnecessary bulk.</p>
<p>Enhanced maintainability and faster page loading are the most obvious key benefits. Smaller CSS files are easier to manage, much like a well-organized toolbox where everything is easy to find. But also, by loading only the essential CSS for each page, the browser has less work to do hence improving the user experience.</p>
<h3 id="heading-original-css">Original CSS</h3>
<p>Suppose you have a CSS file that contains styles for various parts of your website:</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Styles for the home page */</span>
<span class="hljs-selector-class">.homepage</span> {
    <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#f0f0f0</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
}

<span class="hljs-comment">/* Styles for the services page */</span>
<span class="hljs-selector-class">.services</span> {
    <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#333</span>;
    <span class="hljs-attribute">color</span>: white;
}

<span class="hljs-comment">/* Styles for the contact page */</span>
<span class="hljs-selector-class">.contact</span> {
    <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#222</span>;
    <span class="hljs-attribute">color</span>: white;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
}
</code></pre>
<h3 id="heading-segmented-css">Segmented CSS</h3>
<p>Now, let's segment this CSS into different files based on their purpose:</p>
<ol>
<li><strong>Home page Styles (homepage.css):</strong></li>
</ol>
<pre><code class="lang-css"><span class="hljs-selector-class">.homepage</span> {
    <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#f0f0f0</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
}
</code></pre>
<ol start="2">
<li><strong>Services page Styles (services.css):</strong></li>
</ol>
<pre><code class="lang-css"><span class="hljs-selector-class">.services</span> {
    <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#333</span>;
    <span class="hljs-attribute">color</span>: white;
}
</code></pre>
<ol start="3">
<li><strong>Contact page Styles (contact.css):</strong></li>
</ol>
<pre><code class="lang-css"><span class="hljs-selector-class">.contact</span> {
    <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#222</span>;
    <span class="hljs-attribute">color</span>: white;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
}
</code></pre>
<p>Each CSS file is focused on a specific part of the website. Now, when a user visits your website, each page loads only the CSS it requires hence enhancing the website's performance.</p>
<h2 id="heading-4-optimize-css-delivery">4. Optimize CSS Delivery</h2>
<p>You can make your CSS files lighter and faster to load by shrinking your CSS – that is, you can remove extra spaces and lines (this is called minifying). Then you can compress these files so they're smaller and quicker for users to download. </p>
<p>Also, make sure the most important styles of your website load first, so people see your page faster. The other styles can load in the background without slowing things down.</p>
<p>You can also make your website faster for people who visit more than once, by saving some of your CSS in their browser (this is known as caching). This means it doesn’t have to load again every time they visit. </p>
<p>Also, if you use a CDN or a network of servers, your CSS files can be stored in many places around the world to load faster no matter where your users are. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/minifycss.png" alt="Image" width="600" height="400" loading="lazy">
<em>Graphic comparing file size between an unminified CSS file at 167KB and a minified CSS file at 92KB</em></p>
<h3 id="heading-original-css-1">Original CSS</h3>
<pre><code class="lang-css"><span class="hljs-comment">/* Main Stylesheet */</span>
<span class="hljs-comment">/* Header Style */</span>
<span class="hljs-selector-tag">header</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#333</span>;
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
}

<span class="hljs-comment">/* Navigation Style */</span>
<span class="hljs-selector-tag">nav</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#444</span>;
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span>;
}
</code></pre>
<p>The above CSS code is readable and well-commented, but it contains extra spaces and comments that increase the file size.</p>
<h3 id="heading-minified-css">Minified CSS</h3>
<pre><code class="lang-css"><span class="hljs-selector-tag">header</span>{<span class="hljs-attribute">background-color</span>:<span class="hljs-number">#333</span>;<span class="hljs-attribute">color</span>:white;<span class="hljs-attribute">padding</span>:<span class="hljs-number">10px</span>}<span class="hljs-selector-tag">nav</span>{<span class="hljs-attribute">background-color</span>:<span class="hljs-number">#444</span>;<span class="hljs-attribute">margin-top</span>:<span class="hljs-number">10px</span>;}
</code></pre>
<p>The minified version combines all the rules into a single line, removing unnecessary spaces and comments, which reduces the file size for quicker loading.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Optimizing your CSS speeds up your website and consequently improves the overall user experience. </p>
<p>By implementing the practices outlined in this article, you can achieve more performant, efficient and maintainable CSS. The performance savings may not be significant from tweaking a few lines but over hundreds more across different stylesheets, the impact will begin to show. </p>
<p>Remember, web performance is an ongoing process. Regularly review and refine your CSS to keep up with best practices and emerging trends.</p>
<h3 id="heading-additional-resources">Additional Resources</h3>
<ul>
<li><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS">MDN Web Docs on CSS</a></li>
<li><a target="_blank" href="https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency">Google Web Fundamentals</a></li>
<li><a target="_blank" href="https://www.oreilly.com/library/view/web-performance-in/9781617293771/">Web Performance In Action</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Lazy Loading Works in Web Development ]]>
                </title>
                <description>
                    <![CDATA[ In the ever-evolving landscape of web development, performance optimization remains a top priority.  Among the plethora of strategies you can use to enhance web performance, lazy loading stands out for its efficiency and impact.  But what exactly is ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-lazy-loading-works-in-web-development/</link>
                <guid isPermaLink="false">66bae6b8db6fa5bf0acac927</guid>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sudheer Kumar Reddy Gowrigari ]]>
                </dc:creator>
                <pubDate>Thu, 04 Jan 2024 01:08:30 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/12/A-simple-banner-image-depicting-the-concept-of-lazy-loading-images.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In the ever-evolving landscape of web development, performance optimization remains a top priority. </p>
<p>Among the plethora of strategies you can use to enhance web performance, lazy loading stands out for its efficiency and impact. </p>
<p>But what exactly is lazy loading, and how does it revolutionize the way we handle web resources? That's what we'll cover in this article.</p>
<h2 id="heading-what-is-lazy-loading">What is Lazy Loading?</h2>
<p>Lazy loading is a web performance optimization strategy that plays a critical role in how resources are loaded on a webpage. </p>
<p>Traditionally, when you go to access a webpage, the browser attempts to load all resources (images, scripts, stylesheets) immediately. This can lead to longer load times, especially if the page contains many large files. </p>
<p>Lazy loading addresses this by marking certain resources as non-blocking or non-critical, loading them only when they are needed. This method is especially effective for elements that aren't immediately visible on the initial page load, such as images and videos that appear further down the page.</p>
<h3 id="heading-key-benefits-of-lazy-loading">Key benefits of lazy loading:</h3>
<ul>
<li><strong>Improved Performance</strong>: By loading only the necessary resources, the initial page load is faster, leading to a better user experience.</li>
<li><strong>Reduced Bandwidth Usage</strong>: Lazy loading minimizes the amount of data that needs to be transferred initially, saving bandwidth for both the user and the server.</li>
<li><strong>Enhanced User Engagement</strong>: Faster load times generally lead to lower bounce rates and higher engagement, as users are less likely to leave a slow-loading site.</li>
</ul>
<p>Lazy loading can be implemented in various ways, with the most common method being JavaScript-based. But modern web development practices have introduced native HTML ways to implement lazy loading, such as the loading attribute for images.</p>
<h2 id="heading-the-role-of-the-image-loading-attribute-in-lazy-loading">The Role of the Image Loading Attribute in Lazy Loading</h2>
<p>As we delve deeper into the practicalities of lazy loading, you'll see that the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#loading">loading</a> attribute in the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a> element is a game-changer. </p>
<p>This attribute, a relatively recent addition to the HTML specification, offers a simple yet powerful way to implement lazy loading natively, without the need for additional JavaScript. By leveraging the loading attribute, you can significantly enhance web performance and user experience, especially in content-heavy websites.</p>
<h3 id="heading-browser-level-lazy-loading">Browser-Level Lazy Loading</h3>
<p>Primarily, browsers like Chrome and Firefox support the loading attribute for <img width="600" height="400" alt="" loading="lazy"> and <div class="embed-wrapper"><iframe title="Embedded content" loading="lazy"> elements. Using loading="lazy", the browser defers the loading of images until they are near the viewport. </iframe></div></p>
<p>This method is efficient and enhances performance by loading images only when they are likely to be viewed by the user. But it's important to note that the lazy value for <div class="embed-wrapper"><iframe title="Embedded content" loading="lazy"> elements is not yet standardized and may undergo changes.</iframe></div></p>
<p>Let's look at some examples to see how this works.</p>
<h4 id="heading-basic-lazy-loading-of-a-single-image">Basic lazy loading of a single image</h4>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"image-1.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"A scenic landscape"</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span>&gt;</span>
</code></pre>
<p>In this example, the <code>loading="lazy"</code> attribute in the <code>&lt;img&gt;</code> tag tells the browser to defer loading this image until it's about to enter the viewport. This means the image won't load when the page initially loads, but only when the user scrolls near it.</p>
<h4 id="heading-lazy-loading-with-high-priority-images">Lazy loading with high-priority images</h4>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"logo.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Company Logo"</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"eager"</span>&gt;</span> 
<span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"featured.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Featured Product"</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span>&gt;</span>
</code></pre>
<p>Here, the first image (logo) uses <code>loading="eager"</code>, which is the default behavior to load the image immediately. It's useful for important images that need to be seen right away. The second image (featured product) uses <code>loading="lazy"</code>, ideal for images that are not critical to see immediately.</p>
<h4 id="heading-lazy-loading-in-a-gallery">Lazy loading in a gallery</h4>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"gallery-image-1.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Gallery Image 1"</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span>&gt;</span> 
<span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"gallery-image-2.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Gallery Image 2"</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"gallery-image-3.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Gallery Image 3"</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span>&gt;</span>
</code></pre>
<p>For image galleries, using <code>loading="lazy"</code> for each image ensures that images load as the user scrolls through the gallery, improving page load time and reducing bandwidth usage.</p>
<p><strong>Combining Lazy Loading with Art Direction</strong></p>
<p>Art direction in web design refers to the practice of adapting the presentation of content to suit different contexts, devices, or demographics. It often involves using different images or visual styles to convey a specific message or feeling that resonates with various audience segments or fits different screen sizes.</p>
<p>For instance, a website might display a detailed, large image on a desktop but a simpler, smaller image on a mobile device – both delivering the same message but optimized for their respective viewing contexts. </p>
<p>Here’s how you can implement this alongside lazy loading:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">picture</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">source</span> <span class="hljs-attr">media</span>=<span class="hljs-string">"(min-width: 800px)"</span> <span class="hljs-attr">srcset</span>=<span class="hljs-string">"large.jpg"</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">source</span> <span class="hljs-attr">media</span>=<span class="hljs-string">"(min-width: 400px)"</span> <span class="hljs-attr">srcset</span>=<span class="hljs-string">"medium.jpg"</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"small.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Responsive Image"</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">picture</span>&gt;</span>
</code></pre>
<p>In this code, the <code>&lt;picture&gt;</code> element contains multiple <code>&lt;source&gt;</code> elements, each with a different <code>srcset</code> attribute for different screen sizes, and a default <code>&lt;img&gt;</code> element. The <code>loading="lazy"</code> attribute is added to each source to enable lazy loading.</p>
<h3 id="heading-intersection-observer-for-polyfilling">Intersection Observer for Polyfilling</h3>
<p>The Intersection Observer API is a modern web API that provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or the viewport. Essentially, it allows you to execute code when an element enters or leaves the viewport, which is perfect for lazy loading images.</p>
<p>Polyfilling is a technique in web development where modern functionality is replicated in older browsers that do not support that functionality natively. A polyfill is a piece of code (usually JavaScript) that provides the technology that developers expect the browser to provide natively.</p>
<p>When it comes to lazy loading, if a browser does not support the <code>loading</code> attribute, we can use the Intersection Observer as a polyfill to achieve lazy loading behavior.</p>
<p>This JavaScript-based method involves observing <code>&lt;img&gt;</code> elements to determine their visibility within the viewport. When an image becomes visible, its <code>src</code> and <code>srcset</code> attributes are updated to load the actual image. </p>
<p>This method requires additional markup, including a class attribute for selection, a <code>src</code> attribute for a placeholder image, and <code>data-src</code> and <code>data-srcset</code> attributes for the actual image URLs</p>
<h4 id="heading-first-the-html-setup">First, the HTML setup:</h4>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"lazy"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"placeholder.jpg"</span> <span class="hljs-attr">data-src</span>=<span class="hljs-string">"actual-image.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Description"</span>&gt;</span>
</code></pre>
<ul>
<li><code>class="lazy"</code>: A class identifier for JavaScript selection.</li>
<li><code>src</code>: A placeholder image URL.</li>
<li><code>data-src</code>: The actual image URL to be loaded.</li>
</ul>
<h4 id="heading-then-the-javascript">Then, the JavaScript:</h4>
<pre><code class="lang-javascript"><span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"DOMContentLoaded"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">var</span> lazyImages = [].slice.call(<span class="hljs-built_in">document</span>.querySelectorAll(<span class="hljs-string">"img.lazy"</span>));

  <span class="hljs-keyword">if</span> (<span class="hljs-string">"IntersectionObserver"</span> <span class="hljs-keyword">in</span> <span class="hljs-built_in">window</span>) {
    <span class="hljs-keyword">let</span> lazyImageObserver = <span class="hljs-keyword">new</span> IntersectionObserver(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">entries, observer</span>) </span>{
      entries.forEach(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">entry</span>) </span>{
        <span class="hljs-keyword">if</span> (entry.isIntersecting) {
          <span class="hljs-keyword">let</span> lazyImage = entry.target;
          lazyImage.src = lazyImage.dataset.src;
          lazyImage.classList.remove(<span class="hljs-string">"lazy"</span>);
          lazyImageObserver.unobserve(lazyImage);
        }
      });
    });

    lazyImages.forEach(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">lazyImage</span>) </span>{
      lazyImageObserver.observe(lazyImage);
    });
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Fallback for browsers without Intersection Observer support</span>
  }
});
</code></pre>
<p>This section of code demonstrates how you can use the Intersection Observer API to implement lazy loading. It checks if the Intersection Observer is supported in the browser and, if so, uses it to load images only when they enter the viewport.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Using lazy loading, particularly through the <strong>loading</strong> attribute in HTML, can significantly help you improve web performance. By selectively deferring the loading of images and iframes until they are needed, this technique not only enhances the speed and efficiency of web pages but also contributes to a more seamless and responsive user experience. </p>
<p>Whether you apply lazy loading to individual images, galleries, or complex responsive layouts, the versatility of the loading attribute allows you to cater to various web development scenarios, ensuring that resources are utilized effectively and efficiently. </p>
<p>As web technologies continue to evolve, adopting such performance-centric strategies will become increasingly vital in delivering content that meets the expectations of modern web users.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Up Message Queues for Async Tasks with RabbitMQ in Nest.js Apps ]]>
                </title>
                <description>
                    <![CDATA[ When you're developing programs, certain services can block or slow down the speed of your application. For example, CPU-intensive tasks like audio transcribing or file processing. So you might wonder – how do you make sure your application runs with... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/message-queues-with-rabbitmq-in-nest-js/</link>
                <guid isPermaLink="false">66bb51f80fc4910f8f7dfba8</guid>
                
                    <category>
                        <![CDATA[ nestjs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ queue ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Okoye Chukwuebuka Victor ]]>
                </dc:creator>
                <pubDate>Thu, 14 Dec 2023 01:20:25 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/12/articlePhoto.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When you're developing programs, certain services can block or slow down the speed of your application. For example, CPU-intensive tasks like audio transcribing or file processing.</p>
<p>So you might wonder – how do you make sure your application runs without breaking? To handle this, you can send tasks to a queue outside your application's flow.</p>
<h2 id="heading-what-is-a-message-queue">What is a Message Queue?</h2>
<p>A message queue is a tool that facilitates the communication and transfer of data between services within a single application (or externally). It stores these data or messages using the First-In-First-Out (FIFO) principle. This means that older data that's passed into these queues gets processed before newer data.</p>
<p>Different components make up a message queue, such as:</p>
<ul>
<li><strong>Messages</strong>: These are the data that are sent to the queue. They are often referred to as jobs.</li>
<li><strong>Queues</strong>: These are the data structures used for storing messages.</li>
<li><strong>Producers</strong>: These are a service that sends messages or data into the queue system.</li>
<li><strong>Consumers</strong>: These are a service that listens to the queue and executes messages passed in it.</li>
</ul>
<h3 id="heading-message-queuing-tools">Message Queuing Tools</h3>
<p>Now, there are various message queuing tools you can use in asynchronous systems, like the following:</p>
<ul>
<li><strong>RabbitMQ</strong>: a reliable and flexible option for implementing message queues in applications.</li>
<li><strong>Apache</strong> <strong>Kafka</strong>: an efficient message queuing tool, also very good at event stream processing.</li>
<li><strong>Redis</strong>: an in-memory store used for message queuing, caching, and data processing.</li>
</ul>
<p>Note that some of these tools are not limited to message queuing but can be used for other purposes as well, like stream processing.</p>
<p>In this article, you will create a simple Nest.js project which will use RabbitMQ as the Message Queue Service Provider.</p>
<p>The tutorial will be divided into 3 parts:</p>
<ul>
<li><a class="post-section-overview" href="#heading-how-to-set-up-a-nestjs-project">How to Set Up a Nest.js Project for Basic User Registration Flow</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-an-email-service-for-user-registration">How to Set Up an Email Service for User Registration</a></li>
<li><a class="post-section-overview" href="#heading-how-to-integrate-a-queue-service-using-rabbitmq">How to Integrate a Queue Service using RabbitMQ</a></li>
</ul>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li>You'll need to have Node installed on your system. If you don't have it, here is its official site: <a target="_blank" href="https://nodejs.org/en">https://nodejs.org/en</a>.</li>
<li>You'll need to have Node Package Manager (NPM) installed, which you can download here if you don't have it: <a target="_blank" href="https://docs.npmjs.com/downloading-and-installing-node-js-and-npm">https://docs.npmjs.com/downloading-and-installing-node-js-and-npm</a>.</li>
<li>You'll need to have installed RabbitMQ. Here is where you can get it in case you haven't yet: <a target="_blank" href="https://www.rabbitmq.com/download.html">https://www.rabbitmq.com/download.html</a></li>
<li>You'll need to have a text editor. For this article, I'll use VSCode. You can download it here: <a target="_blank" href="https://code.visualstudio.com/download">https://code.visualstudio.com/download</a> or use the code editor of your choice.</li>
</ul>
<h2 id="heading-how-to-set-up-a-nestjs-project">How to Set Up a Nest.js Project</h2>
<p>Spinning up a Nest.js application is fast and simple if you use the Nest CLI. Open up your terminal and enter this command below to install the CLI:</p>
<pre><code class="lang-bash"> $ npm install -g @nestjs/cli
</code></pre>
<p>This installs the Nest.js CLI globally on your system, meaning you can call the CLI commands regardless of the directory you are currently in.</p>
<p>Moving forward, to create a simple REST API project, you will enter the command below:</p>
<pre><code class="lang-bash">nest new simple-queue
</code></pre>
<p>Simple-queue here is the directory name that will be created. Inputting this command gives you a prompt to select a package manager.</p>
<p>When that's done, navigate to the created directory and open it in your text editor by entering this command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> simple-queue &amp;&amp; code .
</code></pre>
<p>This opens up your text editor. We want to work on a project that will best show how a message queue can be used in a real-world scenario – so let's set up a basic user registration form. On successful data entry it sends an email to the user, but you'll handle the email service separately by passing it into a queue to improve performance.</p>
<p>For this, we'll be using an SQLite database, TypeOrm, class-validators, and the dotenv package so you can secure your config variables. Go ahead to install them by typing this command in your terminal:</p>
<pre><code class="lang-bash">npm install --save @nestjs/typeorm typeorm sqlite3 class-validator dotenv
</code></pre>
<p>When the installation is complete, go to your root app module, and then include the TypeOrm configuration for your database. </p>
<p>SQLite is a lightweight SQL database which allows us to quickly spin up and test data. It's optimal for this use case – and now we'll configure it.</p>
<h3 id="heading-configuring-the-sqlite-database">Configuring the SQLite Database</h3>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Module } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/common"</span>;
<span class="hljs-keyword">import</span> { TypeOrmModule } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/typeorm"</span>;
<span class="hljs-keyword">import</span> { AppController } <span class="hljs-keyword">from</span> <span class="hljs-string">"./app.controller"</span>;
<span class="hljs-keyword">import</span> { AppService } <span class="hljs-keyword">from</span> <span class="hljs-string">"./app.service"</span>;

<span class="hljs-meta">@Module</span>({
  imports: [
    TypeOrmModule.forRoot({
      <span class="hljs-keyword">type</span>:<span class="hljs-string">'sqlite'</span>,
      database: <span class="hljs-string">'mini-db.sqlite'</span>,
      entities: [__dirname + <span class="hljs-string">'/**/*.entity{.ts,.js}'</span>],
      synchronize: <span class="hljs-literal">true</span>,  
  })],
  controllers: [AppController],
  providers: [AppService],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AppModule {}
</code></pre>
<p>Congrats! You have successfully connected a DB to your project. Now it's time to create the services that will handle the user registration. </p>
<p>In order to do this, you will have to go back to your dear friend the Nest CLI. There, you'll be inputting a different command to help generate a resource folder for the User, which will contain the entity, service, dto, and the controller.</p>
<p>To do this, open your terminal and enter in this command:</p>
<pre><code class="lang-bash">nest generate resource users
</code></pre>
<p>A prompt to select your transport layer will be shown. Select the first one which is the <code>REST API</code>. Then, another prompt will ask if you would like to generate CRUD endpoints – you can type Yes. Then you can make modifications according to your requirements.</p>
<p>To proceed, you first have to define what information each user should have. First, create a User entity. You can do this by navigating to the user entity file in the created entity subfolder in the user folder. Then define the user data like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Entity, PrimaryGeneratedColumn, Column } <span class="hljs-keyword">from</span> <span class="hljs-string">"typeorm"</span>;

<span class="hljs-meta">@Entity</span>(<span class="hljs-string">'users'</span>)
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> User {
  <span class="hljs-meta">@PrimaryGeneratedColumn</span>(<span class="hljs-string">'uuid'</span>)
  id: <span class="hljs-built_in">string</span>;

  <span class="hljs-meta">@Column</span>({ length: <span class="hljs-number">100</span>, unique: <span class="hljs-literal">true</span> })
  username: <span class="hljs-built_in">string</span>;

  <span class="hljs-meta">@Column</span>({ length: <span class="hljs-number">100</span>, unique: <span class="hljs-literal">true</span> })
  email: <span class="hljs-built_in">string</span>;
}
</code></pre>
<p>For this mini-project, you'll use basic user data to make the process faster. The username and email field have been set to be unique, meaning that there won't be a duplicate of the data instance passed in for this user table.</p>
<p>Now having done this, modify the create user dto file that was generated like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { IsNotEmpty, IsString, IsEmail } <span class="hljs-keyword">from</span> <span class="hljs-string">"class-validator"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> CreateUserDto {
    <span class="hljs-meta">@IsNotEmpty</span>()
    <span class="hljs-meta">@IsString</span>()
    username: <span class="hljs-built_in">string</span>;

    <span class="hljs-meta">@IsNotEmpty</span>()
    <span class="hljs-meta">@IsString</span>()
    <span class="hljs-meta">@IsEmail</span>()
    email: <span class="hljs-built_in">string</span>;
  }
</code></pre>
<p>This was created to validate the payload that will be sent in your request by using the class-validator package.</p>
<p>Now, modify the <code>create</code> method in the user service file.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Injectable } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/common"</span>;
<span class="hljs-keyword">import</span> { InjectRepository } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/typeorm"</span>;
<span class="hljs-keyword">import</span> { Repository } <span class="hljs-keyword">from</span> <span class="hljs-string">"typeorm"</span>;
<span class="hljs-keyword">import</span> { CreateUserDto } <span class="hljs-keyword">from</span> <span class="hljs-string">"./dto/create-user.dto"</span>;
<span class="hljs-keyword">import</span> { User } <span class="hljs-keyword">from</span> <span class="hljs-string">"./entities/user.entity"</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersService {
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">
    <span class="hljs-meta">@InjectRepository</span>(User)
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> userRepository: Repository&lt;User&gt;
  </span>) {}
  <span class="hljs-keyword">async</span> create(createUserDto: CreateUserDto): <span class="hljs-built_in">Promise</span>&lt;User&gt; {
    <span class="hljs-keyword">const</span> newUser = <span class="hljs-built_in">this</span>.userRepository.create(createUserDto);
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.userRepository.save(newUser);
  }
}
</code></pre>
<p>Next you'll modify the controller file. You've already defined the <code>create</code> endpoint, so you'll just have to clean up the other endpoints that are not needed.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Controller, Post, Body } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/common"</span>;
<span class="hljs-keyword">import</span> { CreateUserDto } <span class="hljs-keyword">from</span> <span class="hljs-string">"./dto/create-user.dto"</span>;
<span class="hljs-keyword">import</span> { UsersService } <span class="hljs-keyword">from</span> <span class="hljs-string">"./users.service"</span>;

<span class="hljs-meta">@Controller</span>(<span class="hljs-string">'users'</span>)
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersController {
 <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> usersService: UsersService</span>) {}
  <span class="hljs-meta">@Post</span>()
  create(<span class="hljs-meta">@Body</span>() createUserDto: CreateUserDto) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.usersService.create(createUserDto);
  }
}
</code></pre>
<p>Open up the user module file and make some adjustments by adding the import field to the Module decorator and using the TypeOrmModule property.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Module } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { UsersService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./users.service'</span>;
<span class="hljs-keyword">import</span> { UsersController } <span class="hljs-keyword">from</span> <span class="hljs-string">'./users.controller'</span>;
<span class="hljs-keyword">import</span> { TypeOrmModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/typeorm'</span>;
<span class="hljs-keyword">import</span> { User } <span class="hljs-keyword">from</span> <span class="hljs-string">'./entities/user.entity'</span>;

<span class="hljs-meta">@Module</span>({
  imports: [TypeOrmModule.forFeature([User])],
  controllers: [UsersController],
  providers: [UsersService],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersModule {}
</code></pre>
<p>Next, start up your server by entering this command on your terminal: <code>npm run start:dev</code>. Once the server is up and running, open up your API client of choice. For this article, we'll use Postman. Then make a POST request to the endpoint, which will be <code>localhost:3000/users</code>, providing the payload data required.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696695190655/b8b3b246-0961-4655-aaee-081b9ecff35e.png" alt="Image" width="898" height="409" loading="lazy">
<em>A request was made and a user instance was created.</em></p>
<p>Next up is adding an email service to your project which will help notify new users who are registering.</p>
<h2 id="heading-how-to-set-up-an-email-service-for-user-registration">How to Set Up an Email Service for User Registration</h2>
<p>For this, you'll use some packages which are required to create an email service. Open up your terminal and input the command below to install these packages:</p>
<pre><code class="lang-bash">npm install --save @nestjs-modules/mailer nodemailer
</code></pre>
<p>When these packages are installed, you can now implement the mail service. Using the Nest CLI, create a mailer module and service by entering this command in your terminal:</p>
<pre><code class="lang-bash">nest generate module email &amp;&amp; nest generate service email
</code></pre>
<p>When it's done, open up the newly created module file in the mail folder. You'll use the MailerModule property of the <code>@nestjs-modules/mailer</code> package to configure your mail service here. It requires an SMTP client whose keys you'll need to configure this MailerModule. </p>
<p>For that you can use <a target="_blank" href="https://app.elasticemail.com/api/">https://app.elasticemail.com</a> to get these SMTP keys. Sign up and connect to the SMTP API. You'll then be given keys for your private use.</p>
<p>Note that this free mode of the SMTP client has limitations and it cannot send to all emails – so you should use a test email service.</p>
<h3 id="heading-how-to-configure-the-mailer-module">How to Configure the Mailer Module</h3>
<p>Once you have gotten that set up, go back to your application and create a <strong>.env</strong> file. Set your secrets for the SMTP keys. Then configure your MailerModule like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Global, Module } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/common"</span>;
<span class="hljs-keyword">import</span> { EmailService } <span class="hljs-keyword">from</span> <span class="hljs-string">"./email.service"</span>;
<span class="hljs-keyword">import</span> { MailerModule } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs-modules/mailer"</span>;

<span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>).config();
<span class="hljs-meta">@Global</span>()
<span class="hljs-meta">@Module</span>({
  imports: [
    MailerModule.forRoot({
      transport: {
        service: <span class="hljs-string">'QueueTest'</span>,
        host: process.env.SMTP_HOST,
        port: process.env.SMTP_PORT,
        auth: {
          user: process.env.SMTP_USER,
          pass: process.env.SMTP_PASSWORD,
        },
      },
      defaults: {
        <span class="hljs-keyword">from</span>: process.env.FROM_EMAIL,
      },
    }),
  ],
  providers: [EmailService]
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> EmailModule {}
</code></pre>
<p>The global decorator was set in order to make sure the MailModule can be called anywhere in your application. Make sure your secrets are properly loaded and thaqt you have a valid Email set in the <strong>from: process.env.FROM_EMAIL.</strong></p>
<p>Check to make sure that the EmailModule is also imported in the root App Module the same way your UsersModule was imported in the Imports Array of the App Module.</p>
<p>Next, open your email service file – you'll need to make some modifications to the EmailService class. Add a constructor and call the MailService property from the <code>@nestjs-modules/mailer</code> package. Then go ahead and create a function that will handle sending the emails.</p>
<p>Below is a class and method that does this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { MailerService } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs-modules/mailer'</span>;
<span class="hljs-keyword">import</span> { HttpException, HttpStatus, Injectable } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> EmailService {
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> mailerService: MailerService</span>) {}
  <span class="hljs-keyword">async</span> sendEmail(options: { email: <span class="hljs-built_in">string</span>; subject: <span class="hljs-built_in">string</span>; html: <span class="hljs-built_in">string</span>;
  }) {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> message = {
        to: options.email,
        subject: options.subject,
        html: options.html
      };
      <span class="hljs-keyword">const</span> emailSend = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.mailerService.sendMail({
        ...message,
      });
      <span class="hljs-keyword">return</span> emailSend;
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> HttpException(<span class="hljs-string">'Error'</span>, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }
}
</code></pre>
<p>Now you've defined the method to send an email. You've also put an exception handler in place for better error handling.</p>
<p>Now it's time to add this newly created service to your user registration flow.</p>
<p>Navigate to your user service file, and add the mail service to your constructor as a provider. Then call the service in your <code>create user</code> method like this:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersService {
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">
    <span class="hljs-meta">@InjectRepository</span>(User)
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> userRepository: Repository&lt;User&gt;,
    <span class="hljs-keyword">private</span> emailService: EmailService
  </span>) {}
  <span class="hljs-keyword">async</span> create(createUserDto: CreateUserDto): <span class="hljs-built_in">Promise</span>&lt;User&gt; {
    <span class="hljs-keyword">const</span> newUser = <span class="hljs-built_in">this</span>.userRepository.create(createUserDto);
    <span class="hljs-keyword">const</span> user =  <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.userRepository.save(newUser);
      <span class="hljs-keyword">const</span> emailData = {
        email: user.email,
        subject: <span class="hljs-string">'Welcome to Our Community'</span>,
        html: <span class="hljs-string">`&lt;p&gt;Hello <span class="hljs-subst">${user.username}</span>,&lt;/p&gt;
        &lt;p&gt;Welcome to our community! Your account is now active.&lt;/p&gt;
        &lt;p&gt;Enjoy your time with us!&lt;/p&gt;`</span>,
      };
      <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.emailService.sendEmail(emailData)
    <span class="hljs-keyword">return</span> user
  }
}
</code></pre>
<p>Make sure to modify your modules in order to correct any dependency injection errors. In your email module file, add the EmailService to the exports array:</p>
<pre><code class="lang-typescript"> providers: [EmailService],
 <span class="hljs-built_in">exports</span>: [EmailService]
</code></pre>
<p>Add it below your providers to export the Email Service so it can be accessed in other modules. Then import the EmailModule to your User module file and add it to your import array like this:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@Module</span>({
  imports: [TypeOrmModule.forFeature([User]), EmailModule],
  controllers: [UsersController],
  providers: [UsersService],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersModule {}
</code></pre>
<p>Now it's time to test it. Get a free account from any online email testing platform and open Postman. Make a request to the <code>create user</code> endpoint with your valid email. You should get an email response like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696695108644/25aa9e76-da00-436b-9e43-f0c978f87c6f.png" alt="Image" width="712" height="272" loading="lazy">
<em>Email response you should get</em></p>
<h2 id="heading-how-to-integrate-a-queue-service-using-rabbitmq">How to Integrate a Queue Service using RabbitMQ</h2>
<p>To get started with this, you'll have to install some packages that let you implement queues using RabbitMQ. Enter the command below to install these packages:</p>
<pre><code class="lang-bash">npm install --save amqplib @types/amqplib amqp-connection-manager
</code></pre>
<h3 id="heading-configure-the-producer-service">Configure the Producer Service</h3>
<p>Once installation is complete, it's time to configure RabbitMQ. You'll create a new folder in your src directory and name it queues. Then create the queue producer file. Import these packages and set them up like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { HttpException, HttpStatus, Injectable, Logger } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> amqp, { ChannelWrapper } <span class="hljs-keyword">from</span> <span class="hljs-string">'amqp-connection-manager'</span>;
<span class="hljs-keyword">import</span> { Channel } <span class="hljs-keyword">from</span> <span class="hljs-string">'amqplib'</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ProducerService {
  <span class="hljs-keyword">private</span> channelWrapper: ChannelWrapper;
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
    <span class="hljs-keyword">const</span> connection = amqp.connect([<span class="hljs-string">'amqp://localhost'</span>]);
    <span class="hljs-built_in">this</span>.channelWrapper = connection.createChannel({
      setup: <span class="hljs-function">(<span class="hljs-params">channel: Channel</span>) =&gt;</span> {
        <span class="hljs-keyword">return</span> channel.assertQueue(<span class="hljs-string">'emailQueue'</span>, { durable: <span class="hljs-literal">true</span> });
      },
    });
  }

  <span class="hljs-keyword">async</span> addToEmailQueue(mail: <span class="hljs-built_in">any</span>) {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.channelWrapper.sendToQueue(
        <span class="hljs-string">'emailQueue'</span>,
        Buffer.from(<span class="hljs-built_in">JSON</span>.stringify(mail)),
        {
          persistent: <span class="hljs-literal">true</span>,
        },
      );
      Logger.log(<span class="hljs-string">'Sent To Queue'</span>);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> HttpException(
        <span class="hljs-string">'Error adding mail to queue'</span>,
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }
}
</code></pre>
<p>The AMQP connection was set and is running on localhost with the default RabittMQ port which is 5432. You also established a channel on that connection with an option input which is executed anytime a new channel is created. This helps if you have any configuration for that channel. </p>
<p>You also created an <code>emailQueue</code> with the assertQueue property which checks that a queue with that name does not already exist. If it does exist, it has no effect so it's idempotent. </p>
<p>Then you created an option <code>durable: true</code> to make sure that the queue will survive a server restart.</p>
<p>Next, you defined the method to add the email data to a queue. This calls the <code>sendToQueue</code> property of the channelWrapper, passing in the queue name you want to send the data to. Ideally, it should be the same name as the one you defined with the assertQueue property.</p>
<p>The second argument is the mail data, but firstly you converted it to a JSON string then to a Buffer. You do this because messages in RabbitMQ are mostly transmitted as binary data.</p>
<p>You can then set an option <code>persistent: true</code> to ensure that the data being sent to the queue won't be lost if the server crashes. Then with some error handling and the method to send messages to the queue, it's good to go.</p>
<h3 id="heading-set-up-the-consumer-service">Set Up the Consumer Service</h3>
<p>Now that you've configured the producer service, it's time to set up the consumer service. </p>
<p>Create another file in the queue sub-folder. It's quite similar, but in this case, you will be consuming the data from the queue. Below is the configuration for the consumer service:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Injectable, OnModuleInit, Logger } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> amqp, { ChannelWrapper } <span class="hljs-keyword">from</span> <span class="hljs-string">'amqp-connection-manager'</span>;
<span class="hljs-keyword">import</span> { ConfirmChannel } <span class="hljs-keyword">from</span> <span class="hljs-string">'amqplib'</span>;
<span class="hljs-keyword">import</span> { EmailService } <span class="hljs-keyword">from</span> <span class="hljs-string">'src/email/email.service'</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ConsumerService <span class="hljs-keyword">implements</span> OnModuleInit {
  <span class="hljs-keyword">private</span> channelWrapper: ChannelWrapper;
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> logger = <span class="hljs-keyword">new</span> Logger(ConsumerService.name);
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> emailService: EmailService</span>) {
    <span class="hljs-keyword">const</span> connection = amqp.connect([<span class="hljs-string">'amqp://localhost'</span>]);
    <span class="hljs-built_in">this</span>.channelWrapper = connection.createChannel();
  }

  <span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> onModuleInit() {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.channelWrapper.addSetup(<span class="hljs-keyword">async</span> (channel: ConfirmChannel) =&gt; {
        <span class="hljs-keyword">await</span> channel.assertQueue(<span class="hljs-string">'emailQueue'</span>, { durable: <span class="hljs-literal">true</span> });
        <span class="hljs-keyword">await</span> channel.consume(<span class="hljs-string">'emailQueue'</span>, <span class="hljs-keyword">async</span> (message) =&gt; {
          <span class="hljs-keyword">if</span> (message) {
            <span class="hljs-keyword">const</span> content = <span class="hljs-built_in">JSON</span>.parse(message.content.toString());
            <span class="hljs-built_in">this</span>.logger.log(<span class="hljs-string">'Received message:'</span>, content);
            <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.emailService.sendEmail(content);
            channel.ack(message);
          }
        });
      });
      <span class="hljs-built_in">this</span>.logger.log(<span class="hljs-string">'Consumer service started and listening for messages.'</span>);
    } <span class="hljs-keyword">catch</span> (err) {
      <span class="hljs-built_in">this</span>.logger.error(<span class="hljs-string">'Error starting the consumer:'</span>, err);
    }
  }
}
</code></pre>
<p>First, you defined your consumer class. For this, it implements the <code>onModuleInit</code> interface which is provided by <code>@nestJs/common</code>. This specifies that the defined class should have a method named <code>onModuleInit()</code>. </p>
<p>Like the name says, the method will be called automatically during the module initialization which is when the module containing this class is loaded. </p>
<p>In the class constructor, you added the <code>emailService</code> because you'll be using the <code>sendEmail</code> method of that class.</p>
<p>In the <code>onModuleInit()</code> method, you defined a channel. This is necessary because you need a channel to consume messages from a queue.</p>
<p>From this, the channel is then used to assert a queue which should be similar in name and options to what you have on your producer service. If it's not, you won't be able to listen to the queue created on the producer service. </p>
<p>Then you used the consume method of channel to listen and execute the message coming from the queue you have registered.</p>
<p>Recall that before, you had to convert the message to Buffer in order to send it into a queue. Now, you have to convert it to a JavaScript object. Then call the emailService method to send an email and pass in the converted JavaScript object as the argument of that method.</p>
<p>Finally, you called the <code>ack</code> method which is used to inform the queue that the message has been received and processed successfully in order for it to be removed from the queue.</p>
<p>Now that you've defined these services, create a module file and set them in the providers array. Then export the producer service because you will be calling it in another module.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Module } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { ConsumerService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./consumer.file'</span>;
<span class="hljs-keyword">import</span> { ProducerService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./producer.file'</span>;

<span class="hljs-meta">@Module</span>({
  providers: [ProducerService, ConsumerService],
  <span class="hljs-built_in">exports</span>: [ProducerService],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> QueueModule {}
</code></pre>
<p>Next up is to add the emails being sent on user registration to the queue service that you just created. </p>
<p>Navigate back to your user service file and make some modifications: replace the email service with the producer service as a provider in the constructor, and then call the service and the method to add to the email queue as shown below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Injectable } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/common"</span>;
<span class="hljs-keyword">import</span> { InjectRepository } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/typeorm"</span>;
<span class="hljs-keyword">import</span> { Repository } <span class="hljs-keyword">from</span> <span class="hljs-string">"typeorm"</span>;
<span class="hljs-keyword">import</span> { CreateUserDto } <span class="hljs-keyword">from</span> <span class="hljs-string">"./dto/create-user.dto"</span>;
<span class="hljs-keyword">import</span> { User } <span class="hljs-keyword">from</span> <span class="hljs-string">"./entities/user.entity"</span>;
<span class="hljs-keyword">import</span> { ProducerService } <span class="hljs-keyword">from</span> <span class="hljs-string">"src/queues/producer.file"</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersService {
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">
    <span class="hljs-meta">@InjectRepository</span>(User)
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> userRepository: Repository&lt;User&gt;,
    <span class="hljs-keyword">private</span> producerService: ProducerService,
  </span>) {}
  <span class="hljs-keyword">async</span> create(createUserDto: CreateUserDto): <span class="hljs-built_in">Promise</span>&lt;User&gt; {
    <span class="hljs-keyword">const</span> newUser = <span class="hljs-built_in">this</span>.userRepository.create(createUserDto);
    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.userRepository.save(newUser);
    <span class="hljs-keyword">const</span> emailData = {
      email: user.email,
      subject: <span class="hljs-string">'Welcome to Our Community'</span>,
      html: <span class="hljs-string">`&lt;p&gt;Hello <span class="hljs-subst">${user.username}</span>,&lt;/p&gt;
        &lt;p&gt;Welcome to our community! Your account is now active.&lt;/p&gt;
        &lt;p&gt;Enjoy your time with us!&lt;/p&gt;`</span>,
    };
    <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.producerService.addToEmailQueue(emailData);
    <span class="hljs-keyword">return</span> user;
  }
}
</code></pre>
<p>Also in the user module file, replace the EmailModule with that of the QueueModule to avoid dependency injection errors when you start up your server.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Module } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { UsersService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./users.service'</span>;
<span class="hljs-keyword">import</span> { UsersController } <span class="hljs-keyword">from</span> <span class="hljs-string">'./users.controller'</span>;
<span class="hljs-keyword">import</span> { TypeOrmModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/typeorm'</span>;
<span class="hljs-keyword">import</span> { User } <span class="hljs-keyword">from</span> <span class="hljs-string">'./entities/user.entity'</span>;
<span class="hljs-keyword">import</span> { QueueModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'src/queues/queue.module'</span>;

<span class="hljs-meta">@Module</span>({
  imports: [TypeOrmModule.forFeature([User]), QueueModule],
  controllers: [UsersController],
  providers: [UsersService],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersModule {}
</code></pre>
<p>Now finally, it's time to test the user registration flow again. So navigate back to Postman and then type in a valid email and username and hit enter. On the terminal of your server running, you will see logs that were set in order to track the way the message got sent and how it was received and executed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696982914939/7f28f0e3-22e3-462c-8956-0bd2156d4c10.png" alt="Image" width="800" height="153" loading="lazy">
<em>Logs that help you track the message</em></p>
<p>You can also open up the RabbitMQ dashboard to view queue activity on <a target="_blank" href="http://localhost:15672/">http://localhost:15672</a>, By default the user is "guest", so enter in <code>guest</code> for the username and password.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1702377899227/4158d8b2-2b9b-424e-bd0b-a4203648eb50.png" alt="Image" width="906" height="523" loading="lazy">
<em>RabbitMQ Queues and Streams</em></p>
<p>Here's the link to the <a target="_blank" href="https://github.com/ChuloWay/article-nestjs-queue">GitHub repository</a>. Feel free to check it out whenever you're stuck.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article you learned what a message queue is along with some major components of how they work. You also built a mini Nest.js project and implemented an email service in it. Finally, you integrated the queue service into your project, showing how it works in a real-life scenario.</p>
<p>Understanding message queue behaviors and patterns is an essential skill when developing scalable applications. This helps reduce lag and improves the speed and efficiency of your applications. </p>
<p>I hope you enjoyed reading this article. You can follow me on <a target="_blank" href="https://twitter.com/OkoyeVictorr">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Bundle a Simple React Application Using esbuild ]]>
                </title>
                <description>
                    <![CDATA[ Bundling is an important phase in the web development process, particularly when dealing with JavaScript frameworks like React. It entails combining all the various JavaScript files and dependencies into a single file for faster browser loading and e... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/bundle-a-basic-react-application-using-esbuild/</link>
                <guid isPermaLink="false">66ba6102bca875d7790d6aa6</guid>
                
                    <category>
                        <![CDATA[ Bundler ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ valentine Gatwiri ]]>
                </dc:creator>
                <pubDate>Tue, 22 Aug 2023 20:56:13 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/Screenshot-from-2023-08-21-16-04-04.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Bundling is an important phase in the web development process, particularly when dealing with JavaScript frameworks like React. It entails combining all the various JavaScript files and dependencies into a single file for faster browser loading and execution. </p>
<p>esbuild is a lightweight and efficient bundler for React apps. Here's an overview of how to use esbuild to bundle a basic React application.</p>
<h2 id="heading-how-to-install-esbuild-globally">How to Install esbuild Globally</h2>
<p>We'll start by installing esbuild globally in your system by running <code>npm install -g esbuild</code> in the command line. This will install the latest version of esbuild globally on your system. </p>
<p>After installation, you can access esbuild from the command line by typing <code>esbuild</code>.</p>
<h2 id="heading-how-to-create-a-new-directory-for-your-react-application">How to Create a New Directory for Your React Application</h2>
<p>To create a new directory for your React application, open the terminal and navigate to the directory where you want to create the new directory. Then run the following command:</p>
<pre><code class="lang-bash">mkdir my-react-app
</code></pre>
<p>This will create a new directory named <code>my-react-app</code>. You can replace it with whatever name you want to give your React application directory.</p>
<p>After creating the directory, navigate into it by running:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> my-react-app
</code></pre>
<p>Initialize a new <code>npm</code> project by running the following command and following the prompts:</p>
<pre><code class="lang-bash">npm init -y
</code></pre>
<p>Install React and React DOM by running <code>npm install react react-dom</code> in the terminal. This will install the latest versions of React and React DOM in your project, along with any required dependencies.</p>
<h2 id="heading-how-to-create-the-necessary-files-and-folders">How to Create the Necessary Files and Folders</h2>
<p>Let's create the necessary files and folders. Here's a basic structure:</p>
<pre><code>my-react-app
├── src
|   |
│   |── index.js
├── |--- index.html
│  
└── package.json
</code></pre><p>Add the code shown below in your app, following the above structure:</p>
<p><strong>index.html</strong>:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1, shrink-to-fit=no"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Hello, esbuild!<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"root"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"Bundle.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span></span>
</code></pre>
<p>The above code outlines the fundamental structure of an HTML5 web page. It starts with a declaration indicating the use of HTML5. The main structure consists of an <code>&lt;html&gt;</code> root element containing a <code>&lt;head&gt;</code> section for metadata, including character encoding and viewport settings for responsiveness.</p>
<p> The <code>&lt;title&gt;</code> element defines the browser tab's title, while the actual content resides in the <code>&lt;body&gt;</code> element. Within the <code>&lt;body&gt;</code>, a <code>&lt;div&gt;</code> element with the id "root" serves as a placeholder for potential dynamic content. </p>
<p>Additionally, there's a <code>&lt;script&gt;</code> tag pointing to an external JavaScript file named "Bundle.js," generated by esbuild, to be executed by the browser. </p>
<p>This structure sets the foundation for building a web page with HTML5, CSS, and JavaScript functionality.</p>
<p><strong>index.js</strong></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Hello, esbuild! <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

ReactDOM.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>, <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
</code></pre>
<p>Our React code sets up a simple React application with a single component App. It renders a <code>&lt;div&gt;</code> element with the text <code>Hello, esbuild!</code> and mounts it into the DOM, specifically into the element with the <code>id</code> of <code>root</code>.</p>
<h2 id="heading-how-to-create-the-build-function">How to Create the Build Function</h2>
<p>Let's add the following build script using the <code>esbuild</code> bundler in our <code>package.json</code> file:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
        <span class="hljs-attr">"build"</span>: <span class="hljs-string">"esbuild src/index.js --bundle --outfile=Bundle.js --loader:.js=jsx --format=cjs"</span>
},
</code></pre>
<p>This build script starts with the entry point <code>src/index.js</code> and proceeds to bundle all the dependencies. The resulting bundled code is saved as <code>Bundle.js</code>. </p>
<p>The script also specifies that files with the <code>.js</code> extension should be treated as <code>jsx</code> files, indicating the usage of JSX syntax.</p>
<p>Finally, the output format is set to <code>CommonJS (cjs)</code> which is the module system utilized by Node.js. </p>
<p>By executing this build script, the <code>esbuild</code> bundler will process the files, apply the necessary transformations, and generate a single bundled JavaScript file ready for deployment or further usage.</p>
<h3 id="heading-overview-of-the-build-function-and-its-purpose">Overview of the Build Function and its Purpose</h3>
<p>The build script using esbuild is JavaScript code that bundles your JavaScript code into a single file. This is useful for optimizing your code for production environments, reducing the number of HTTP requests needed to load your application, and improving load times.</p>
<p>The build method takes an <code>options</code> object as its argument, which allows you to configure how your code is bundled. The options object specifies properties such as <code>entryPoints</code>, <code>outfile</code>, <code>format</code>, <code>bundle</code>, and <code>loader</code>.</p>
<p>Once the build method is configured with the desired options, the build function is called, which triggers the build process. This will output a single bundled file containing all of your JavaScript code.</p>
<p>Finally, the build script is run by executing the script using Node.js. You can do this by updating the <code>package.json</code> file to include a script that runs the build script, as shown above.</p>
<p>Build the React app using the following command:</p>
<pre><code class="lang-bash">npm run build
</code></pre>
<p>Then run the app using this command:</p>
<pre><code class="lang-bash">npx http-server
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>By following these steps, you can bundle your basic React application using esbuild and have it ready for deployment or further usage. Here is the <a target="_blank" href="https://github.com/gatwirival/esbuild-bundling-demo.git">demo.</a></p>
<p>Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Avoid the N+1 Query Problem in GraphQL and REST APIs [with Benchmarks] ]]>
                </title>
                <description>
                    <![CDATA[ By Mohamed Mayallo The N+1 query problem is a performance issue you might face while building APIs, regardless of whether they're GraphQL or REST APIs. In fact, this problem occurs when your application needs to return a set of data that includes rel... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/n-plus-one-query-problem/</link>
                <guid isPermaLink="false">66d46013a326133d12440a21</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 07 Jul 2023 17:59:59 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/07/N-1-Query-Problem.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Mohamed Mayallo</p>
<p>The N+1 query problem is a performance issue you might face while building APIs, regardless of whether they're GraphQL or REST APIs.</p>
<p>In fact, this problem occurs when your application needs to return a set of data that includes related nested data – for example, a post that includes comments.</p>
<p>But how can you fix this problem? To avoid this issue, you should understand what is it and how it occurs.</p>
<p>So in this tutorial, you'll learn what the N+1 query problem is, why it is easy to fall into it, and how you can avoid it.</p>
<p>Before starting, it is good to know:</p>
<ul>
<li>The examples in this article are just for the sake of simplicity.</li>
<li><code>SELECT *</code> is very bad, and you should avoid it.</li>
<li>You should care about pagination if you’re working with large data sets.</li>
</ul>
<p>You can find the examples in this article in this <a target="_blank" href="https://github.com/Mohamed-Mayallo/n_plus_one_problem_benchmarks">repo</a>. Let's dive in.</p>
<h2 id="heading-understanding-the-n1-query-problem">Understanding the N+1 Query Problem</h2>
<p>The N+1 problem occurs when your application needs to return a set of data that includes related data that exists in:</p>
<ul>
<li>Another table.</li>
<li>Another database (in the case of microservices, for example)</li>
<li>Or even another third-party service.</li>
</ul>
<p>In other words, you need to execute extra database queries or external requests to return the nested data.</p>
<p>If you are wondering about what the name means (N+1), follow the below example, which uses a single database:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/related-data.drawio.png" alt="Post and Comment tables | By Author" width="600" height="400" loading="lazy">
<em>Illustration of N+1 problem</em></p>
<p>As you can see, the relationship between <code>Post</code> and <code>Comment</code> is one-to-many, respectively.</p>
<p>So, if your application needs to return a list of posts and their related comments, you might end up with this code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">'SELECT * FROM "Post"'</span>); <span class="hljs-comment">// Get all posts (1 database query)</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> post <span class="hljs-keyword">in</span> posts) {
    <span class="hljs-comment">// For sure, you can replace the following query with an external request if you need to retrieve the post's comments from another service</span>
    <span class="hljs-keyword">const</span> comments = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">`SELECT * FROM "Comment" WHERE "post_id" = <span class="hljs-subst">${post.id}</span>`</span>); <span class="hljs-comment">// Get all comments for every post (n database query for n posts)</span>
    post.comments = comments;
}
</code></pre>
<p>So, you have executed <strong>N</strong> queries to retrieve every post’s comments and <strong>1</strong> query to retrieve all posts <strong>(N comments queries + 1 posts query).</strong></p>
<p>But, why you should be aware of this problem?</p>
<h2 id="heading-why-is-the-n1-query-problem-a-serious-issue">Why Is the N+1 Query Problem a Serious Issue?</h2>
<p>Here are some reasons why the N+1 query problem can cause serious performance issues in your application:</p>
<ol>
<li>Your application makes a lot of database queries or external requests to retrieve a list of data like posts.</li>
<li>The more data your application retrieves, the slower your request is going to be and the more resources your application is going to consume.</li>
<li>A large data set might end up with notable network latency.</li>
<li>It is going to be challenging to scale the application to handle larger data sets.</li>
</ol>
<p>On top of that, you are going to see the performance impact in numbers in the benchmarks section later in this article.</p>
<p>Now that you understand the N+1 query problem and its impact on your application, let’s introduce some effective ways you can avoid this problem.</p>
<h2 id="heading-strategies-to-avoid-the-n1-query-problem">Strategies to Avoid the N+1 Query Problem</h2>
<p>Fortunately, there are a few simple strategies you can follow to avoid the N+1 query problem.</p>
<p>Let’s apply them to our previous example.</p>
<h3 id="heading-1-eager-loading-using-sql-joins-for-example">1) Eager Loading (Using SQL Joins, for example)</h3>
<p>In this strategy, instead of returning the post’s comments separately for every post, you can use <strong>SQL Joins</strong>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> postsAndComments = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">`
    SELECT * 
    FROM "Post"
    JOIN "Comment"
    ON "Comment"."post_id" = "Post"."post_id"
`</span>);
</code></pre>
<p>When you're using this strategy, it's good to know that:</p>
<ul>
<li>It is only one database query to return all posts and their nested comments.</li>
<li>You can't apply this strategy if you are consuming your data sets from a different database or service.</li>
</ul>
<h3 id="heading-2-batch-loading">2) Batch Loading</h3>
<p>In this strategy, your code should follow the below steps:</p>
<ul>
<li>Execute one request to retrieve all posts.</li>
<li>Execute another request to load a batch of posts’ comments instead of loading every post’s comments separately.</li>
<li>Map every comment to its corresponding parent post.</li>
</ul>
<p>Let’s jump into an example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">'SELECT * FROM "Post"'</span>), <span class="hljs-comment">// 1- Retrieve all posts in one request</span>
    postsIds = posts.map(<span class="hljs-function"><span class="hljs-params">post</span> =&gt;</span> post.id),
    postsComments = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">`SELECT * FROM "Comment" WHERE "post_id" IN (<span class="hljs-subst">${postsIds}</span>)`</span>); <span class="hljs-comment">// 2- retrieve all posts’ comments in another request</span>

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> post <span class="hljs-keyword">in</span> posts) { <span class="hljs-comment">// 3- Map every comment to its parent post</span>
    <span class="hljs-keyword">const</span> comments = postsComments.filter(<span class="hljs-function"><span class="hljs-params">comment</span> =&gt;</span> comment.post_id === post.id);
    post.comments = comments;
}
</code></pre>
<p>As you see, in this strategy, there are just two requests: one to retrieve all posts and another one to retrieve their comments.</p>
<h3 id="heading-3-caching">3) Caching</h3>
<p>You may be familiar with caching and its impact on any application's performance.</p>
<p>You can implement caching on your client side or server side using <a target="_blank" href="https://redis.io/">Redis</a>, <a target="_blank" href="https://memcached.org/">Memcached</a>, or any other similar tool. Wherever you can properly use caching, it significantly pushes your application's performance.</p>
<p>Let’s get back to our example and cache the posts’ comments in a Redis store.</p>
<pre><code class="lang-js">    <span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">'SELECT * FROM "Post"'</span>),
        postsIds = posts.map(<span class="hljs-function"><span class="hljs-params">post</span> =&gt;</span> post.id),
        cachedPostsComments = getPostsCommentsFromRedis(postsIds);

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> post <span class="hljs-keyword">in</span> posts) {
    <span class="hljs-keyword">const</span> comments = cachedPostsComments.filter(<span class="hljs-function"><span class="hljs-params">comment</span> =&gt;</span> comment.post_id === post.id);
    post.comments = comments;
}
</code></pre>
<p>As you might guess, you can cache the posts’ comments or even the posts themselves which significantly minimizes the load on databases.</p>
<h3 id="heading-4-lazy-loading">4) Lazy Loading</h3>
<p>In this strategy, you are distributing the responsibility between the server side and the client side.</p>
<p>You shouldn’t return all data at once from the server side. Instead, you prepare two endpoints for the client side like this:</p>
<ul>
<li><code>GET /api/posts</code>: Retrieves all posts.</li>
<li><code>GET /api/comments/:postId</code>: Retrieves a post’s comments on demand.</li>
</ul>
<p>And now, the data retrieval is up to the client side.</p>
<p>This strategy is very useful because:</p>
<ul>
<li>It enables the client side to load the parent post first and display its content, and then load its related comments lazily. So users don't have to wait for the entire data set to be returned from the server side.</li>
<li>You have full control over sorting, filtering, pagination and so on over every endpoint.</li>
</ul>
<p>The key point of this strategy is that it gets rid of nested data like comments and flattens all data sets in their own endpoint.</p>
<h3 id="heading-5-graphql-dataloader">5) GraphQL Dataloader</h3>
<p>As you might guess, this strategy works with GraphQL APIs.</p>
<p>Dataloader is a GraphQL utility that works by batching multiple database queries into one request. So, it uses the Batch Loading strategy under the hood.</p>
<p>Let’s jump into our example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> DataLoader = <span class="hljs-built_in">require</span>(<span class="hljs-string">'dataloader'</span>);

<span class="hljs-comment">// 1- GraphQL Schema Definition</span>
<span class="hljs-keyword">const</span> typeDefs = gql<span class="hljs-string">`
  type Post {
    post_id: ID!
        comments: [Comment]
  }

    type Comment {
        comment_id: ID!
    post_id: ID!
  }

  type Query {
    posts: [Post]
  }
`</span>;

<span class="hljs-comment">// 2- Resolve the GraphQL Schema</span>
<span class="hljs-keyword">const</span> resolvers = {
  <span class="hljs-attr">Query</span>: {
    <span class="hljs-attr">posts</span>: <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">'SELECT * FROM "Post"'</span>);
            <span class="hljs-keyword">return</span> posts;
    }
  },

  <span class="hljs-attr">Post</span>: {
    <span class="hljs-attr">comments</span>: <span class="hljs-function">(<span class="hljs-params">post, args, { dataLoaders }</span>) =&gt;</span> {
      <span class="hljs-keyword">return</span> dataLoaders.commentsLoader.load(post.id);
    }
  }
};

<span class="hljs-comment">// 3- Define Dataloaders</span>
<span class="hljs-keyword">const</span> commentsBatchFunction = <span class="hljs-keyword">async</span> postsIds =&gt; {
      <span class="hljs-keyword">const</span> comments = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">`SELECT * FROM "Comment" WHERE "post_id" IN (<span class="hljs-subst">${postsIds}</span>)`</span>);
        <span class="hljs-keyword">const</span> groupedComments = comments.reduce(<span class="hljs-function">(<span class="hljs-params">tot, cur</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (!tot[cur.post_id]) {
        tot[cur.post_id] = [cur];
      } <span class="hljs-keyword">else</span> {
        tot[cur.post_id].push(cur);
      }
      <span class="hljs-keyword">return</span> tot;
    }, {});
        <span class="hljs-keyword">return</span> postsIds.map(<span class="hljs-function">(<span class="hljs-params">postId</span>) =&gt;</span> groupedComments[postId]);
    },
    createCommentsLoader = <span class="hljs-keyword">new</span> DataLoader(commentsBatchFunction),
    createDataloaders = <span class="hljs-function">() =&gt;</span> ({
        <span class="hljs-attr">commentsLoader</span>: createCommentsLoader()
    });

<span class="hljs-comment">// 4- Inject Dataloaders in the GraphQL Context</span>
<span class="hljs-keyword">const</span> server = <span class="hljs-keyword">new</span> ApolloServer({
    typeDefs,
    resolvers,
    <span class="hljs-attr">context</span>: <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">dataLoaders</span>: createDataloaders(),
    }
  }
});
</code></pre>
<p>So how does it work? To get more detailed information, you can check out the <a target="_blank" href="https://github.com/graphql/dataloader">documentation</a>. But we'll go through the basics here.</p>
<p>The key point of the Dataloader is the <a target="_blank" href="https://github.com/graphql/dataloader#batch-function">Batch Function</a>. Here, the batch function <code>commentsBatchFunction</code> takes an array of keys <code>postsIds</code> and returns a <a target="_blank" href="https://mayallo.com/asynchronous-javascript/">Promise which resolves</a> to an array of values <code>comments</code>, <code>[ [post1comment1, post1comment2], [post2comment1], ... ]</code>.</p>
<p>On top of that, the batch function has two constraints:</p>
<ul>
<li>The size of the keys array <code>postsIds</code> must equal the values array <code>comments</code>. In other words, this expression must be true: <code>postsIds.length === comments.length</code>.</li>
<li>Each index in the keys array <code>postsIds</code> must correspond to the values array <code>comments</code>. So you might note that I looped over the <code>postsIds</code> to map each corresponding comment.</li>
</ul>
<p>As a result, you can see that GraphQL Dataloader uses the second strategy (Batch Loading) under the hood.</p>
<p>Let’s get back to our example to walk through its implementation:</p>
<ol>
<li>First, we defined the GraphQL schema.</li>
<li>Then we resolved the GraphQL schema. Keep in mind, if you resolved the comments in the <code>Post</code> type using this query <code>await rawSql('SELECT * FROM "Comment" WHERE "post_id" = ' + post.id);</code>, you’re going to fall into the N+1 query problem.</li>
<li>Next, we defined the comments batch function and then created the comments dataloader.</li>
<li>Finally, we injected dataloaders in the <a target="_blank" href="https://www.apollographql.com/docs/apollo-server/data/context/">GraphQL Context</a> to be able to use them in resolvers.</li>
</ol>
<p>So, by using GraphQL Dataloader, if you have 10 posts and every post has 5 comments, you would end up with two queries – one to retrieve the 10 posts and another one to retrieve their comments.</p>
<p>Take a look at the following screenshot:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Code_1K9XMH0CHB.png" alt="Database queries with GraphQL Dataloader and without it" width="600" height="400" loading="lazy">
<em>Illustration of process with and without Dataloader</em></p>
<h2 id="heading-benchmarks-about-n1-query-problem">Benchmarks About N+1 Query Problem</h2>
<p>In this section, let’s compare each strategy in terms of performance.</p>
<table>
<thead>
<tr>
<th>N+1 in REST API</th>
<th>Eager Loading Strategy</th>
<th>Batch Loading Strategy</th>
<th>Caching Strategy</th>
<th>N+1 in GraphQL API</th>
<th>GraphQL Dataloader</th>
</tr>
</thead>
<tbody>
<tr>
<td>2.139</td>
<td>0.065</td>
<td>0.048</td>
<td>0.019</td>
<td>2.44</td>
<td>0.397</td>
</tr>
<tr>
<td>2.147</td>
<td>0.081</td>
<td>0.068</td>
<td>0.024</td>
<td>2.38</td>
<td>0.483</td>
</tr>
<tr>
<td>2.152</td>
<td>0.062</td>
<td>0.065</td>
<td>0.035</td>
<td>2.67</td>
<td>0.372</td>
</tr>
<tr>
<td>2.17</td>
<td>0.053</td>
<td>0.047</td>
<td>0.031</td>
<td>2.71</td>
<td>0.377</td>
</tr>
<tr>
<td>2.181</td>
<td>0.052</td>
<td>0.069</td>
<td>0.031</td>
<td>2.38</td>
<td>0.364</td>
</tr>
<tr>
<td>2.14</td>
<td>0.076</td>
<td>0.043</td>
<td>0.017</td>
<td>2.53</td>
<td>0.346</td>
</tr>
<tr>
<td>2.321</td>
<td>0.073</td>
<td>0.045</td>
<td>0.018</td>
<td>2.60</td>
<td>0.451</td>
</tr>
<tr>
<td>2.13</td>
<td>0.061</td>
<td>0.06</td>
<td>0.015</td>
<td>2.35</td>
<td>0.369</td>
</tr>
<tr>
<td>2.149</td>
<td>0.064</td>
<td>0.04</td>
<td>0.015</td>
<td>2.65</td>
<td>0.368</td>
</tr>
<tr>
<td>2.361</td>
<td>0.065</td>
<td>0.045</td>
<td>0.016</td>
<td>2.54</td>
<td>0.424</td>
</tr>
<tr>
<td>2.190</td>
<td>0.065</td>
<td>0.053</td>
<td>0.022</td>
<td>2.525</td>
<td>0.395</td>
</tr>
</tbody>
</table>

<p><em>Note that the results of the Cache strategy are coming just after caching the data set. The first query is ignored as caching is missed.</em></p>
<p>These results were generated from the following environment:</p>
<ul>
<li>Seeded data: 1000 posts and 50 comments for every post.</li>
<li>CPU: AMD Ryzen 5 3600 6-Core Processor 3.60 GHz.</li>
<li>RAM: 32.0 GB.</li>
<li>OS: Windows 10 Pro.</li>
</ul>
<p>To be able to retest these strategies in your environment, follow these steps:</p>
<ul>
<li>Clone this <a target="_blank" href="https://github.com/Mohamed-Mayallo/n_plus_one_problem_benchmarks">repo</a>.</li>
<li>Then run <code>docker-compose up</code>.</li>
<li>For GraphQL, open <code>http://localhost:3000/graphql</code>.</li>
<li><strong>A query suffers from the N+1 problem:</strong> query only <strong><code>commentsWithNPlusOne</code></strong> in the <code>Post</code> type<strong>.</strong></li>
<li><strong>Dataloader strategy</strong>: query only <code>commentsWithDataloader</code> in the <code>Post</code> type.</li>
<li>For REST, follow these endpoints:</li>
<li><strong>A query suffers from the N+1 problem</strong>: <code>http://localhost:3000/api/postsWithNPlusOne</code>.</li>
<li><strong>Eager Loading strategy</strong>: <code>http://localhost:3000/api/postsWithEagerLoading</code>.</li>
<li><strong>Batch Loading strategy</strong>: <code>http://localhost:3000/api/postsWithBatchLoading</code>.</li>
<li><strong>Caching strategy</strong>: <code>http://localhost:3000/api/postsWithCache</code>.</li>
</ul>
<p>My notes about these benchmarks:</p>
<ul>
<li>These strategies are way too efficient.</li>
<li>You may notice that the slower strategy in REST, the Eager Loading strategy, is <strong>about 34 times faster</strong> than the N+1 query in the REST API.</li>
<li>The Dataloader strategy is <strong>about 6.4 times faster</strong> than the N+1 query in the GraphQL API.</li>
<li>If you compared the results of REST and GraphQL APIs, you may notice that REST is faster than GraphQL. I think this is because of the internal implementations of GraphQL, which makes sense.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you learned that the N+1 query problem is a performance issue you might encounter when working with APIs.</p>
<p>You then learned about some strategies you can follow to avoid this problem like:</p>
<ul>
<li>Eager Loading using SQL Joins</li>
<li>Batch Loading by executing fewer requests and then mapping each corresponding item to its parent.</li>
<li>Caching using Redis</li>
<li>Dataloader in the GraphQL world.</li>
</ul>
<p>Finally, we created some benchmarks about the N+1 query problem so we could see how efficiently these strategies improve our API performance.</p>
<h2 id="heading-before-you-leave">Before you leave</h2>
<p>If you found this article useful, you can <a target="_blank" href="https://mayallo.com/blog/">check out some of my other articles on my personal blog as well</a>.</p>
<p>Thanks a lot for staying with me up till this point. I hope you enjoy reading this article.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How CDNs Help Speed Up Performance by Reducing Latency ]]>
                </title>
                <description>
                    <![CDATA[ By Austin Gil In some recent tutorials, I covered supporting file uploads on the front end, supporting file uploads on the back end, and optimizing costs by moving file uploads to object storage. Today, I'll continue to focus on more architectural wo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/cdns-speed-up-performance-by-reducing-latency/</link>
                <guid isPermaLink="false">66d45d98052ad259f07e4a59</guid>
                
                    <category>
                        <![CDATA[ content delivery network  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 27 Jun 2023 00:17:23 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/06/pexels-pixabay-315934.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Austin Gil</p>
<p>In some recent tutorials, I covered <a target="_blank" href="https://austingil.com/uploading-files-with-html/">supporting file uploads on the front end</a>, <a target="_blank" href="https://austingil.com/file-uploads-in-node/">supporting file uploads on the back end</a>, and optimizing costs by <a target="_blank" href="https://austingil.com/upload-to-s3/">moving file uploads to object storage.</a></p>
<p>Today, I'll continue to focus on more architectural work, but this time it’ll be focused on optimizing performance.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/Vymnxp-t0qs" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-overview-of-object-storage-solution">Overview of Object Storage Solution</h2>
<p>Let's say we have an application that stores uploaded files somewhere in the world. For this example, it’s an <a target="_blank" href="https://www.linode.com/products/object-storage/">Object Storage bucket from Akamai cloud computing services</a>, and I've deployed it to the <code>us-southeast-1</code> region.</p>
<p>You may be using a different provider and different region, but the following points will still apply.</p>
<p>So when I upload a cute photo of Nugget making a big ol’ yawn, I'll be able to access it at some URL like austins-bucket.us-southeast-1.linodeobjects.com/files/nugget.jpg</p>
<p><img src="https://austingil.com/wp-content/uploads/image-65-1080x608.png" alt="Screenshot of my browser showing a cute photo of Nugget making a big yawn, and there's a box highlighting the URL from Akamai Object Storage." width="1080" height="608" loading="lazy"></p>
<p>Nugget is a super cute dog. Naturally, a lot of people are going to want to see this. Unfortunately, because this photo is hosted in the <code>us-southeast-1</code> region, anyone that lives far away from that region has to wait longer before their eyes can feast on this beast.</p>
<p>Latency sucks.</p>
<p>And that’s why CDNs exist.</p>
<h2 id="heading-what-is-a-cdn">What is a CDN?</h2>
<p>CDN stands for "<strong>content delivery network</strong>". It’s a connected network of computers that are globally distributed and can store copies of the same files so that when a user makes a request for a specific file, it can be served from the nearest computer to the user. </p>
<p>By using a CDN, the distance a request must travel is reduced. This helps resolve requests faster, regardless of a user’s location.</p>
<p>Here’s a <a target="_blank" href="https://www.webpagetest.org/result/230417_BiDc3J_AP8/">webpagetest.org test results</a> for that photo of Nugget. The request was made from their servers in Japan, and it took 1.1 seconds for the request to complete.</p>
<p><img src="https://austingil.com/wp-content/uploads/image-69-1080x723.png" alt="Image" width="1080" height="723" loading="lazy"></p>
<p>Instead of serving the file directly from my Object Storage bucket, I can set up a CDN in front of my application to cache the photo all over the world.</p>
<p>So users in Tokyo will get the same photo but served from their nearest CDN location (which is probably in Tokyo), and users in Toronto are going to get that same file, but served from their nearest CDN location (which is probably in Toronto).</p>
<p>This can have significant performance implications.</p>
<p>Let’s look at that same request, but served behind a CDN. The <a target="_blank" href="https://www.webpagetest.org/result/230417_BiDc41_ARJ/">webpagetest.org results</a> still show the same photo of Nugget, and the request still originated from Tokyo, but this time it only took 0.2 seconds – <strong>a fraction of the time!</strong></p>
<p><img src="https://austingil.com/wp-content/uploads/image-68-1080x956.png" alt="Image" width="1080" height="956" loading="lazy"></p>
<p>When the request is made for this image, the CDN can check if it already has a cached version. If it does, it can respond immediately. If it doesn’t, it can go fetch the original file from Object Storage, then save a cached version for any future requests.</p>
<p><strong>Note</strong>: the numbers reported above are from a single test. They may vary depending on network conditions.</p>
<h2 id="heading-the-compounding-returns-of-cdns">The Compounding Returns of CDNs</h2>
<p>The example above focused on improving delivery speeds of uploaded files. In that context, I was only dealing with a single image that is uploaded to an Object Storage bucket. It shows almost a full second improvement in response times, which is great, but things get even better when you consider other types of assets.</p>
<p>CDNs are great for any static asset (CSS, JavaScript, fonts, images, icons, and so on). By putting it in front of my application, all the other static files can automatically get cached as well. This includes the files that Nuxt.js generates in the build process, and which are hosted on the application server.</p>
<p>This is especially relevant when you consider the “<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Performance/Critical_rendering_path">Critical rendering path</a>” and render-blocking resources like CSS, JavaScript, or fonts.</p>
<p>When a webpage loads, as the browser comes across a render-blocking resource, it will pause parsing and go download the resource before it continues (hence “render-blocking”). So any latency that affects a single asset may also impact the performance of other assets further down the network cascade.</p>
<p>This means the performance improvements from a CDN are compounding. Nice!</p>
<p>So is this about showing cute photos of my dog to more people even faster, or is it about helping you make your applications run faster? YES!</p>
<p>Whatever motivates you to build faster websites, including a CDN as part of your application infrastructure is a crucial step if you plan on serving customers from more than one region.</p>
<h2 id="heading-how-to-connect-akamai-cdn-to-object-storage">How to Connect Akamai CDN to Object Storage</h2>
<p>Now I want to take a little side-quest and share how I set up Akamai with Object Storage. I didn’t find much information on the subject, and I’d like to help anyone in this specific situation. If it doesn’t apply to your use case, feel free to skip this section.</p>
<p>With something like 300,000 servers across 4,000 locations, Akamai is the largest CDN provider in the world. It’s used by some of the biggest companies in the world, but it’s hard to find Akamai-related content because most large companies don't like to share unnecessary information about their infrastructure.</p>
<p>But I'm not most companies :)</p>
<p>(Note: You will need an Akamai account and access to your DNS editor)</p>
<p>In the <a target="_blank" href="https://control.akamai.com/">Akamai Control Center</a>, I created <a target="_blank" href="https://control.akamai.com/apps/create/#/property/products">a new Property</a> using the <a target="_blank" href="https://www.akamai.com/products/web-performance-optimization">Ion Standard product,</a> which is great for general purpose CDN delivery.</p>
<p><img src="https://austingil.com/wp-content/uploads/image-71-1080x274.png" alt="Image" width="1080" height="274" loading="lazy"></p>
<p>After clicking “Create Property”, you’ll be prompted to choose whether to use the setup wizard to guide you through creating the property, or you can go straight to the Property Manager settings for the new property. I chose the latter.</p>
<p>In the Property Manager, I had to add a new hostname in the Property Hostnames section. I added the hostname for my application. This is the URL where users will find your application. In my case, it was uploader.austingil.com.</p>
<p><img src="https://austingil.com/wp-content/uploads/image-76-1080x520.png" alt="Image" width="1080" height="520" loading="lazy"></p>
<p>Part of this process also requires setting up an SSL certificate for the hostname. I left the default value selected for Enhanced TLS.</p>
<p><img src="https://austingil.com/wp-content/uploads/image-77-1080x520.png" alt="Image" width="1080" height="520" loading="lazy"></p>
<p>With all that set up, Akamai will show me the following Property Hostname and Edge Hostname. We’ll come back to these later when it’s time to make DNS changes.</p>
<ul>
<li><strong>Property Hostname:</strong> uploader.austingil.com</li>
<li><strong>Edge Hostname:</strong> uploader.austingil.com-v2.edgekey.net</li>
</ul>
<p><img src="https://austingil.com/wp-content/uploads/image-72-1080x155.png" alt="Image" width="1080" height="155" loading="lazy"></p>
<p>Next, I had to set up the actual property’s behavior, which meant editing the Default Rule under the Property Configuration Settings. Specifically, I had to point the <strong>Origin Server Hostname</strong> to the domain where my origin server will live.</p>
<p><img src="https://austingil.com/wp-content/uploads/image-73-1080x761.png" alt="Image" width="1080" height="761" loading="lazy"></p>
<p>In my DNS, I created a new A record pointing origin-uploader.austingil.com to my origin server’s IP address, then added a CNAME record that points uploader.austingil.com to the Edge Hostname provided by Akamai.</p>
<ul>
<li>A: origin-uploader.austingil.com -&gt; origin server IP</li>
<li>CNAME: uploader.austingil.com -&gt; uploader.austingil.com-v2.edgekey.net</li>
</ul>
<p>This lets me build out my CDN configuration and test it as needed, only sending traffic through the CDN when I’m ready.</p>
<p>Finally, to serve files in my Object Storage instance through Akamai, I created a new rule based on the blank rule template. I set the rule criteria to apply to all requests going to the <code>/files/*</code> sub-route.</p>
<p><img src="https://austingil.com/wp-content/uploads/image-74-1080x402.png" alt="Image" width="1080" height="402" loading="lazy"></p>
<p>The rule behavior is set up to rewrite the request’s Origin Server Hostname and change it to my Object Storage location: npm.us-southeast-1.linodeobjects.com.</p>
<p><img src="https://austingil.com/wp-content/uploads/image-75-1080x602.png" alt="Image" width="1080" height="602" loading="lazy"></p>
<p>This way, any request that goes to <a target="_blank" href="https://uploader.austingil.com/files/nugget.jpg">uploader.austingil.com/files/nugget.jpeg</a> is served <strong>through</strong> the CDN, but the file originates from the Object Storage location. And when you load the application, all the static assets generated by Nuxt are served from the CDN as well. All other requests are passed through Akamai and forwarded to origin-uploader.austingil.com, which points to the origin server.</p>
<p>So that’s how I’ve configured Akamai CDN to sit in front of my application. Hopefully, it all made sense, but if you have questions, feel free to ask me.</p>
<h2 id="heading-to-sum-up">To Sum Up</h2>
<p>Today we looked at what a CDN is, the role it plays in reducing network latency, and how to set up Akamai CDN with Object Storage.</p>
<p>But this is just the tip of the iceberg. There’s a whole world of tweaking CDN configuration to get even more performance. </p>
<p>There are also a lot of other performance and security features a CDN can offer beyond just static file caching: Web Application Firewalls, faster network path resolution, <a target="_blank" href="https://www.akamai.com/solutions/security/ddos-protection">DDoS protection</a>, bot mitigation, <a target="_blank" href="https://www.akamai.com/solutions/edge">edge compute</a>, automated <a target="_blank" href="https://www.akamai.com/products/image-and-video-manager">image and video optimization</a>, malware scanning, request security headers, and more. </p>
<p>My colleague <a target="_blank" href="https://www.linkedin.com/in/mikeelissen/">Mike Elissen</a> also covers some great security topics <a target="_blank" href="https://blog.securitylevelup.eu/">on his blog</a>.</p>
<p>The most important thing that I wanted to convey today is that using a CDN improves file delivery performance by caching content close to the user.</p>
<p>Thank you so much for reading. If you liked this article, and want to support me, the best ways to do so are to <a target="_blank" href="https://twitter.com/share?via=heyAustinGil">share it</a>, <a target="_blank" href="https://austingil.com/newsletter/">sign up for my newsletter</a>, and <a target="_blank" href="https://twitter.com/heyAustinGil">follow me on Twitter</a>.</p>
<p><em>You can find this and my other articles published on <a target="_blank" href="https://austingil.com/file-uploads-cdn/">austingil.com</a>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Measure and Improve the Performance of a React App ]]>
                </title>
                <description>
                    <![CDATA[ Hi everyone! React is a popular JavaScript library for building user interfaces. As applications built with React become more complex, their performance can start to degrade. Poor performance can lead to a frustrating user experience and a negative i... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/measure-and-improve-performance-of-react-apps/</link>
                <guid isPermaLink="false">66d45f0f182810487e0ce19a</guid>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ German Cocca ]]>
                </dc:creator>
                <pubDate>Mon, 27 Mar 2023 17:18:19 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/nicolas-hoizey-poa-Ycw1W8U-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hi everyone!</p>
<p>React is a popular JavaScript library for building user interfaces. As applications built with React become more complex, their performance can start to degrade.</p>
<p>Poor performance can lead to a frustrating user experience and a negative impact on user engagement. So in this article, we will discuss how to measure and improve the performance of a React application.</p>
<h1 id="heading-table-of-contents">Table of Contents</h1>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-define-performance">How to define performance</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-measure-performance">How to measure performance</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-react-dev-tools">React dev tools</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-improve-performance">How to improve performance</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-optimizing-images">Optimizing images</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-code-splitting-and-lazy-loading">Code splitting and Lazy Loading</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-optimizing-the-dom">Optimizing the DOM</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-avoid-unnecessary-component-re-renders">Avoid unnecessary component re-renders</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-rendering-patterns">Rendering patterns</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-content-delivery-network-cdn">CDNs</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></p>
</li>
</ul>
<h1 id="heading-how-to-define-performance">How to Define Performance</h1>
<p>In web development, "performance" generally refers to the speed and efficiency of a website or web application. It encompasses several different factors, including:</p>
<ol>
<li><p><strong>Page load time:</strong> This refers to the time it takes for a page to fully load and display all of its content. Faster load times generally lead to a better user experience.</p>
</li>
<li><p><strong>Responsiveness:</strong> This refers to the speed at which a website responds to user interactions, such as clicking a button or scrolling. A responsive website feels snappy and quick, which can also improve user experience.</p>
</li>
<li><p><strong>Resource usage:</strong> This refers to the amount of server resources (such as CPU and memory) that a website uses to serve pages and respond to requests. A well-optimized website will use resources efficiently, allowing the server to handle more traffic and reducing costs.</p>
</li>
<li><p><strong>Scalability:</strong> This refers to a website's ability to handle increased traffic and load without sacrificing performance. A scalable website can handle sudden spikes in traffic without slowing down or crashing.</p>
</li>
</ol>
<p>Optimizing website performance is important because it can directly impact user experience, search engine rankings, and even business revenue.</p>
<h1 id="heading-how-to-measure-performance">How to Measure Performance</h1>
<p>The first step in improving the performance of a React application is to measure its current performance. There are several tools available for measuring performance, including:</p>
<ol>
<li><p><strong>Lighthouse</strong> – <a target="_blank" href="https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=es">Lighthouse</a> is an open-source tool from Google that audits web pages for performance, accessibility, and more. Lighthouse generates a report that includes suggestions for improving the performance of the application.</p>
</li>
<li><p><strong>WebPageTest</strong> – <a target="_blank" href="https://gercocca.vercel.app/">WebPageTest</a> is a free tool that allows you to test the speed of your website from multiple locations around the world. WebPageTest provides detailed reports on the performance of your website, including suggestions for improvement.</p>
</li>
<li><p><strong>Google PageSpeed Insights –</strong> <a target="_blank" href="https://pagespeed.web.dev/">Google PageSpeed Insights</a> analyzes the content of a web page and generates a report that identifies opportunities to improve the page's performance.</p>
</li>
</ol>
<p>All three tools work basically in the same way. You provide the URL of the site you'd like to analyze, and the tools will run through it and provide you with a detailed report covering improvement opportunities in performance, and also accessibility, SEO and general best practices.</p>
<p>These tools are nice to get an objective measure of our apps. Some of them can even be integrated into CI/CD pipelines so we can monitor how changes impact in performance through time.</p>
<h2 id="heading-react-dev-tools">React dev tools</h2>
<p>Another useful tool for measuring performance in a React app is the profiler of <a target="_blank" href="https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi">React DevTools</a>. React DevTools is a browser extension that allows you to inspect and debug React applications in the Chrome, Firefox, or Edge browsers.</p>
<p>The "profiler" is a tool that allows you to record the activity in your app, and later on generate a report showing what components were rendered, how many times and when each component was rendered, and how long each render took.</p>
<p>It's quite useful for detecting unnecessary component re-renders and renders that take too long, generating performance bottlenecks.</p>
<p>If you'd like to get a deeper dive into how profiler works, I recommend <a target="_blank" href="https://www.youtube.com/watch?v=00RoZflFE34&amp;t=452s">this video</a>.</p>
<h1 id="heading-how-to-improve-performance">How to Improve Performance</h1>
<p>Now that we have an idea of how can we identify performance issues in our app, let's go through some of the optimization techniques we can use to make it better.</p>
<h2 id="heading-optimizing-images">Optimizing Images</h2>
<p>Images are one of the primary culprits for slow loading websites. You can optimize images by compressing them without compromising their quality. Tools like <a target="_blank" href="https://tinypng.com/">tinyPng</a> can compress your images and help you reduce the size of your website, and therefore it's load time.</p>
<p>Meta frameworks such as Next come with built-in image optimization.</p>
<h2 id="heading-code-splitting-and-lazy-loading">Code splitting and Lazy Loading</h2>
<p>Lazy loading involves loading content only when it is needed, instead of loading everything at once. This is done through something called <strong>"code splitting"</strong>. This is a bundling technique that allows you to break up code in smaller chunks that are downloaded only when needed, instead of downloading the whole code in the first render.</p>
<p>A classic example of when this technique can come in handy is when navigating through different routes. Let's say our website has two main routes, "Home" and "Contact".</p>
<p>We'd only want to download the code related to the "Home" page when we're in that route, and the "Contact" code to download when we are in that other route. Code splitting allows us to do that, and in this way help reduce the initial load time of the application and improve the user experience.</p>
<p>You can use tools such as <strong>React.lazy()</strong> and <strong>Suspense</strong> to implement lazy loading in your application. If you'd like a deeper dive into how these tools work, <a target="_blank" href="https://www.youtube.com/watch?v=JU6sl_yyZqs">check out this video</a>.</p>
<h2 id="heading-optimizing-the-dom">Optimizing the DOM</h2>
<p>The size of the Document Object Model (DOM) can impact the performance of the application. The bigger and more complex it is, the longer it'll take to load and be modified.</p>
<p>You can optimize the DOM by reducing the number of elements, removing unnecessary elements, and minimizing the use of CSS animations.</p>
<h3 id="heading-avoid-unnecessary-component-re-renders">Avoid unnecessary component re-renders</h3>
<p>As you may know, React is a library that allows us to build user interfaces. In React, each piece of the UI is represented in code by a component. When a piece of the UI needs to be modified, React re-renders the component with the updated information.</p>
<p>There are two things that trigger a component re-render: A change in state or a change in props. But sometimes, components can re-render unnecessarily, meaning there's no actual change in the information to be displayed.</p>
<p>To prevent unnecessary re-renders, we can implement some of the following techniques:</p>
<ul>
<li><p><strong>Memoization:</strong> In React, memoization allows a component to "remember" the value of the state and/or props it receives. Before re-rendering, it can check if the value has actually changed. If it hasn't, then it doesn't re-render. This technique can be achieved through hooks like <code>useMemo</code> and <code>useCallback</code>. If you'd like a deeper dive on that, <a target="_blank" href="https://www.freecodecamp.org/news/memoization-in-javascript-and-react/">check out this article I wrote</a>.</p>
</li>
<li><p><strong>Use key prop for lists:</strong> When rendering a list of items in React, it's important to provide a unique key prop for each item. This helps React identify which items have changed and need to be re-rendered. If you don't provide a key prop, React will use the index of the item in the array, which can lead to unnecessary re-renders if the order of the items changes.</p>
</li>
<li><p><strong>Keeping state as local as possible:</strong> By keeping state local, I mean that the state that a component uses should be (when possible) within the component itself or as close in the component tree as possible. This is because when a component re-renders, all children components will re-render as well. It's not necessarily a terrible thing, but if we can avoid it, we probably should. So It's not a good idea to centralize all state in a single parent component, unless that states needs to be used from multiple parts of the application down the component tree. Here's <a target="_blank" href="https://kentcdodds.com/blog/state-colocation-will-make-your-react-app-faster">a great article about this topic</a> if you're interested in learning more.</p>
</li>
</ul>
<h2 id="heading-rendering-patterns">Rendering patterns</h2>
<p>Another thing that can have an impact on the performance of your app is the rendering pattern it uses. A rendering pattern refers to the way in which the HTML, CSS, and JavaScript code is all processed and rendered in a web application or website.</p>
<p>Different rendering patterns are used to achieve different performance and user experience goals. The most common rendering patterns in web development are:</p>
<ol>
<li><p><strong>Client-side rendering (CSR)</strong>: In CSR, the client's browser generates the HTML content of a web page on the client-side using JavaScript. This approach can provide a fast and interactive user experience but can be slower for initial loading times and bad for SEO.</p>
</li>
<li><p><strong>Server-side rendering (SSR)</strong>: In SSR, the web server generates the HTML content of a web page on the server-side and sends it to the client's browser. This approach can improve initial loading times and SEO (search engine optimization) but can be slower for dynamic content.</p>
</li>
</ol>
<p>Server-Side Rendering (SSR) can help improve the initial load time of the application by rendering the initial page on the server-side. This can help improve the Time-to-Interactive (TTI) and First Contentful Paint (FCP) metrics. You can use tools such as Next.js or Gatsby to implement SSR in your application.</p>
<p>The choice of rendering pattern depends on the specific needs and requirements of a project, such as performance, SEO, user experience, and flexibility. If your priority is to provide users with a fluid, native-like experience, CSR is probably a good choice. If you need ultra fast page load times, SSR or SSG can be a better option.</p>
<p>For a deeper dive into rendering patterns, check out <a target="_blank" href="https://www.freecodecamp.org/news/rendering-patterns/">this article I recently wrote</a>.</p>
<h2 id="heading-content-delivery-network-cdn">Content Delivery Network (CDN)</h2>
<p>A CDN, or Content Delivery Network, is a system of distributed servers or nodes that work together to deliver web content, such as images, videos, and other files, to users based on their geographic location.</p>
<p>When a user requests content from a website, the CDN will serve the content from the server closest to the user, which helps to reduce latency and improve website performance. CDNs can also help to reduce the load on a website's origin server by caching frequently accessed content and delivering it from the CDN's servers instead of the origin server.</p>
<p>CDNs are normally used to host static content (meaning content that doesn't change frequently over time), such as images, videos, blog posts and so on. Also, if you're using Static Site Generation (SSG) as a rendering pattern, you could host your rendered sites in a CDN for an even faster delivery.</p>
<p>Some examples of popular CDNs are Cloudflare and Amazon CloudFront.</p>
<p>For more detail on how CDNs work, check out <a target="_blank" href="https://www.youtube.com/watch?v=RI9np1LWzqw">this awesome video</a>.</p>
<h1 id="heading-wrapping-up"><strong>Wrapping Up</strong></h1>
<p>Well everyine, in this article we've discussed how to measure and improve the performance of a React application.</p>
<p>We defined the concept of website performance, including page load time, responsiveness, resource usage, and scalability, and outlined how to measure performance using tools such as Lighthouse, WebPageTest, Google PageSpeed Insights and React dev tools.</p>
<p>Finally, we've seen some optimization techniques such as optimizing images, code splitting and lazy loading, optimizing the DOM, and avoiding unnecessary component re-renders.</p>
<p>As always, I hope you enjoyed the article and learned something new.</p>
<p>If you want, you can also follow me on <a target="_blank" href="https://www.linkedin.com/in/germancocca/">LinkedIn</a> or <a target="_blank" href="https://twitter.com/CoccaGerman">Twitter</a>. See you in the next one!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/AbsoluteAnnualKoi-size_restricted.gif" alt="Image" width="600" height="400" loading="lazy"></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Next.js SEO for Developers – How to Build Highly Performant Apps with Next ]]>
                </title>
                <description>
                    <![CDATA[ By Scott Gary Next.js is a popular React-based web framework that has gained popularity and a growing community in recent years. It's a powerful tool for building fast and SEO-friendly web applications with dynamic pages that work great on mobile dev... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/nextjs-seo/</link>
                <guid isPermaLink="false">66d460f4c7632f8bfbf1e4b7</guid>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SEO ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 20 Mar 2023 21:17:55 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/pexels-andrei-photo-2127783.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Scott Gary</p>
<p>Next.js is a popular React-based web framework that has gained popularity and a growing community in recent years. It's a powerful tool for building fast and SEO-friendly web applications with dynamic pages that work great on mobile devices. </p>
<p>Due to the complex nature of isomorphic system design, Next.js SEO can be a tricky topic to get your head around. Especially if you're coming from traditional React apps and you're relying solely on documentation.</p>
<p>With its built-in support for server-side rendering, static site generation, and now React server components, Next.js provides a robust platform for achieving quality SEO web metrics in your web application. It also helps you deliver exceptional user experiences across multiple pages in Node and React apps while making them SEO friendly.</p>
<h2 id="heading-why-should-you-learn-nextjs-for-front-end-development">Why Should You Learn NextJS for Front End Development?</h2>
<p>In short, the newest version of NextJS is an open source platform that addresses a lot of rendering issues that React currently has. I wrote this article because a lot of front end developers get mad at me :-D. </p>
<p>They spend 6-9 months developing a React App, and then I have to ask them to refactor their code. </p>
<p>Next.js avoids a lot of rending issues – it makes it very easy for search engines to understand what your website is all about.</p>
<h3 id="heading-who-will-get-the-most-out-of-this-article">Who Will get the most out of this article?</h3>
<p>This will be very helpful to you if you're a marketer or more advanced developer who's experiencing SEO issues. </p>
<p>However newer developers are welcome to review this info as well, as it will help you in the long term.</p>
<h2 id="heading-how-should-you-render-your-next-js-web-page-application">How Should You Render Your Next JS Web Page Application?</h2>
<p>I've personally reviewed a ton of theses websites from my consultancy <a target="_blank" href="https://www.ohmycrawl.com/">OhMyCrawl</a> and made a video overview to help understand the benefits of using frameworks such as Next.js for SEO:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/U8V0rk5AwBU" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-how-is-next-seo-different-from-other-frameworks">How is Next SEO Different from Other Frameworks?</h2>
<p>Next SEO sets itself apart by streamlining so many features and free tools into a well-organized package that you can easily digest and apply in your single page applications. Next does a great job when it comes to tasks such as search engine optimization, image optimization, and minimizing cumulative layout shift.</p>
<p>The benefits of Next.js SEO don't stop there. We’ll be covering many of the goodies that Next.js brings to the table related to search engines, old and new. </p>
<h2 id="heading-search-engines-ssr-and-ssg-concepts-are-evolving">Search Engines, SSR, and SSG Concepts Are Evolving</h2>
<p>Most developers and SEO experts have become pretty comfortable with the existing page creation strategies and the whole SSR vs SSG paradigm. They've also developed a high level of trust in version 12 of Next.js, which provides a clear cut way to handle these two forms of page generation. </p>
<p>As usual, though, yet another web app paradigm shift is underway, this time in the form of React Server Components (RSCs), which are included by default in Next.js version 13.</p>
<h3 id="heading-seo-concepts-havent-changed-just-the-approach">SEO Concepts Haven’t Changed – Just the Approach</h3>
<p>Next JS SEO won’t change much conceptually. If you’re looking for good search engine results and organic traffic, the game still revolves around the notion of fast page loads, quick paints, low cumulative layout shifts, and all the rest. Static pages still play a large role as well. </p>
<p>But Next.js gives us some pretty cool and novel features that help facilitate excellent search engine metrics, and it’s more than just React Server Components.</p>
<p>We'll explore some best practices along with a few different techniques and strategies for achieving great SEO optimization web metrics with Next.js. We'll also see how to take advantage of its unique features to improve your website's search engine visibility and user engagement.</p>
<h2 id="heading-whats-new-with-nextjs-13-that-relates-to-seo">What’s New With Next.js 13 that Relates to SEO?</h2>
<p>Rather than give you a comprehensive guide to the technical changes found in version 13, we’re going to focus mainly on Next JS SEO related advantages. We'll also look at how you can leverage the best SEO practices to achieve the best possible results in search engines with much less sweat off your back than is typically needed.</p>
<p>The version 13 changes we’ll discuss here are as follows:</p>
<ul>
<li>React server components</li>
<li>Streaming UI chunks</li>
<li>Updated Next Image component</li>
<li>Next Font component</li>
</ul>
<p>On top of the existing default SEO properties of Next, these particular upgrades are the cornerstone of Next.js SEO improvements in version 13. Each one is awesome for its own reasons, which we’ll be going over shortly.</p>
<h3 id="heading-react-server-components">React Server Components</h3>
<p>RSCs allow for a more fine-grained approach to rendering on both the client and the server. </p>
<p>Rather than being forced to decide whether to render an entire page on the client or server upon user requests, React allows developers to choose whether components should be rendered on the server or the client. This can give you a huge advantage in search engine results pages.</p>
<p>A huge majority of page optimization these days revolves around sending less JavaScript to the client. After all, this is the primary benefit of using pre-rendering and Server Side Rendering to create web pages and HTML pages. </p>
<p>RSCs are another tool to help achieve this end and gain as much SEO value from your web pages or single page applications as you can. This helps achieve better SEO by refreshing dynamic data in a React component while leaving the static parts of the page’s content intact.</p>
<h3 id="heading-streaming-ui-chunks">Streaming UI Chunks</h3>
<p>Next.js SEO made a huge leap adding RSC to the mix, and streaming UI chunks is the cherry on top. Streaming UI is a similar spin-off of a new and growing design pattern called “the island architecture,” which strives to send as little code to the client as possible at first load.</p>
<p>Allowing fine-grained control is great, but why not send a JavaScript-free, fully rendered page to the client, and send the rest later? That’s exactly what streaming UI chunks accomplish.</p>
<p>When Next.js renders a page on the server, the page typically comes with all the JavaScript bundled up and sent along with it. The ability to stream chunks of data eliminates this need, and allows an extremely tiny static page to be sent to the client, significantly improving web metrics such as first contentful paint and overall page speed.</p>
<h3 id="heading-nextjs-13-app-directory">Next.js 13 App Directory</h3>
<p>When you start a new Next.js 13 project, you’ll notice a new directory called <strong>app</strong>. Everything within the app directory is preconfigured to allow for RSCs and streaming UI chunks. You need only create a <a target="_blank" href="https://beta.nextjs.org/docs/routing/loading-ui">loading.js</a> component, which will wrap the page component entirely and any children within a suspense boundary.</p>
<p>You can achieve an <em>even more</em> granular loading pattern by manually creating the suspense boundaries yourself, essentially allowing for unlimited control over what gets loaded upon the initial request.</p>
<p>The steps for streaming UI chunks go something like this:</p>
<ol>
<li>User makes initial request.</li>
<li>Barebones HTML page is rendered and sent to the client.</li>
<li>JavaScript bundles are being prepared on the server.</li>
<li>A page section requiring JavaScript becomes visible in the client browser.</li>
<li>JavaScript bundle for only that component is sent to the client.</li>
</ol>
<p>This new tooling has important implications for technical SEO by allowing more interactive pages to compete with static pages in regards to page load speed and other web metrics that are used as ranking factors in search results by search engines.</p>
<h3 id="heading-updated-next-image-component">Updated Next Image Component</h3>
<p>Another important upgrade to the Next.js SEO sphere is the Image component. Although it’s been somewhat understated, the biggest improvement in my opinion is the utilization of native lazy loading. </p>
<p>Browsers have had great support for native lazy loading for some time now, and including extra JavaScript for this feature is simply a waste of bandwidth.</p>
<p>A few other great improvement for SEO are:</p>
<ul>
<li>Required alt tag by default.</li>
<li>Better validation to pinpoint errors involving invalid properties.</li>
<li>More easily styled due to a more HTML-like interface.</li>
</ul>
<p>Overall, the new Image component is simplified and slimmed down, and in the programming world simpler is almost always better.</p>
<h3 id="heading-the-next-font-component">The Next Font Component</h3>
<p>The font component is a huge win for Next.js SEO, and it will certainly help alleviate many headaches in the future. Any experienced developer knows how tedious it can be configuring fonts properly (proper is not relative in this case!).</p>
<p>Cumulative layout shifts due to slow loading is a common nuisance, and search engines like Google have <a target="_blank" href="https://developers.google.com/publisher-tag/guides/minimize-layout-shift">openly stated</a> that CLS is an important web metric. </p>
<p>Depending on the framework you’re working with (Gatsby comes to mind), it can be tricky getting your fonts to preload effectively. Making external requests to font repositories such as Google have been a necessary evil for some time, creating a hard to manage bottleneck in many SPA applications.</p>
<p>The Next Font Component aims to solve this problem by fetching all external fonts at build time, and self-hosting them from your own domain. Fonts are also optimized automatically, and zero cumulative layout shift is accomplished by automatic utilization of the CSS <strong>size-adjust</strong> property.</p>
<h2 id="heading-common-seo-related-tasks-with-nextjs">Common SEO-Related Tasks with Next.js</h2>
<p>There are a few important topics to consider when configuring common Next.js SEO tasks for version 13. </p>
<h3 id="heading-nextjs-seo-with-version-13">Next.js SEO With Version 13</h3>
<p>The Next version of the React Head component has typically been used to assign values to meta tags within the document head and also to inject structured data.</p>
<p>With version 13, however, the Head component goes out the window. At first, Next opted to utilize a special file called <strong>head.js</strong> that works in a similar fashion as the Head component. After version 13.2, Next implemented the <strong>Metadata</strong> component, which is a more proprietary implementation to solving the metadata problem by easily populating meta tags.</p>
<p>Let’s take a closer look at these two common SEO tasks, and examine how they used to be handled as opposed to the new version 13 way.</p>
<h2 id="heading-how-to-configure-the-head-tag-for-search-engine-optimization">How to Configure the Head Tag for Search Engine Optimization</h2>
<p>Prior to version 13, we would import the <strong>Next/Head</strong> component, and set any necessary metadata values such as title and description or other meta tags within the html file of the web page. </p>
<p>A simple example of the Head component in version 12 looks like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">'next/head'</span>
<span class="hljs-keyword">const</span> structData = {
<span class="hljs-string">'@context'</span>: <span class="hljs-string">'https://schema.org'</span>,
<span class="hljs-string">'@type'</span>: <span class="hljs-string">'BlogPosting'</span>,
<span class="hljs-attr">headline</span>: <span class="hljs-string">'Learning Next.js SEO'</span>,
<span class="hljs-attr">description</span>: <span class="hljs-string">'All about Next.js features and more'</span>,
<span class="hljs-attr">author</span>: [
{
<span class="hljs-string">'@type'</span>: <span class="hljs-string">'Person'</span>,
<span class="hljs-attr">name</span>: <span class="hljs-string">'Jane Doe'</span>,
},
],
<span class="hljs-attr">datePublished</span>: <span class="hljs-string">'2023-02-16T09:00:00.000Z'</span>,
};
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">IndexPage</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">Head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"initial-scale=1.0, width=device-width"</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>My page title<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span>
<span class="hljs-attr">key</span>=<span class="hljs-string">"structured-1"</span>
<span class="hljs-attr">type</span>=<span class="hljs-string">"application/ld+json"</span>
<span class="hljs-attr">dangerouslySetInnerHTML</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">__html:</span> <span class="hljs-attr">JSON.stringify</span>(<span class="hljs-attr">structData</span>) }}
/&gt;</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">Head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello world!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span></span>
)
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> IndexPage
</code></pre>
<p>Adding structured data such as title and description or any additional meta tags in a page’s metadata is a simple matter of including a script tag with the <strong>dangerouslySetInnerHTML</strong> attribute, as seen in the example.</p>
<p>Most developers code an SEO component that utilizes the Head component in order to achieve a more DRY (don’t repeat yourself) approach. Here, you prevent the same data or HTML files from being sent multiple times to the user. But under the hood it’s all the same, and Head was the go-to approach for optimizing a web page in regards to meta tags.</p>
<h3 id="heading-the-next-special-headjs-file">The Next Special head.js File</h3>
<p>With version 13, you can forget all about the usual Head component. Starting with the first iteration of version 13, Next implemented the <strong>head.js (or .tsx)</strong> file. This file can be included within any folder inside the app directory to dynamically manage SEO metadata and declare which tags, along with their values, will be utilized for a particular route and particular page.</p>
<p>Every folder in the app directory accounts for a new route, which is why you’ll need to create a <strong>head.js</strong> file within each folder to configure your metadata values. Here’s an example <strong>head.js</strong> file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Head</span>(<span class="hljs-params">params</span>) </span>{
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag">&lt;&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>head.js Example<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/&gt;</span></span>
);
}
</code></pre>
<p>Notice that we return a React fragment rather than an actual head tag, or any other element. This is a required aspect of the <strong>head.js</strong> component. </p>
<p>You can only return the following metadata tags from within the fragment: , &lt;meta&gt;, &lt;link&gt; (with the precedence attribute) or &lt;script&gt; (with the async attribute).&lt;/p&gt;
&lt;p&gt;Next never fully fleshed out this component, which is why most developers baked up custom implementations for adding structured data to the mix. Although, a bit later on Next did start recommending that structured data be added into the layout or page component instead, which we’ll go over a bit later.&lt;/p&gt;
&lt;p&gt;This component became deprecated in version 13.2, and the Vercel team moved on to the &lt;strong&gt;Metadata&lt;/strong&gt; component.&lt;/p&gt;
&lt;h3 id="heading-the-next-metadata-component"&gt;The Next Metadata Component&lt;/h3&gt;
&lt;p&gt;With the release of Next version 13.2, Next decided to opt out of a head component altogether, and instead created the &lt;strong&gt;Metadata&lt;/strong&gt; component. &lt;/p&gt;
&lt;p&gt;At the time of writing, there isn’t a whole lot of material out there for usage examples and such. In fact, 13.2 hasn’t even been released, and we’re only up to 13.1.7-canaray at the moment.&lt;/p&gt;
&lt;p&gt;Nonetheless, Next has a decent write-up in their documentation, so we’ll go over the usage and give a basic analysis. It’s important to be informed on this if you plan on being on top of Next.js SEO, because it’s coming down the pipe.&lt;/p&gt;
&lt;p&gt;The Metadata component aims to be the one-stop shop for populating the &lt;strong&gt;head&lt;/strong&gt; tag with title and description and other dynamic metadata in an efficient and easy to use manner. The usage is really quite simple, and involves exporting either an object called &lt;strong&gt;metadata&lt;/strong&gt; or a function called &lt;strong&gt;generateMetadata&lt;/strong&gt; from the page component itself.&lt;/p&gt;
&lt;p&gt;Let’s take a look at a basic usage example:&lt;/p&gt;
&lt;h3 id="heading-nextjs-export-metadata-example"&gt;Next.js export metadata Example&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;examplePage.tsx&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-js"&gt;&lt;span class="hljs-keyword"&gt;import&lt;/span&gt; type { Metadata } &lt;span class="hljs-keyword"&gt;from&lt;/span&gt; &lt;span class="hljs-string"&gt;'next'&lt;/span&gt;;
&lt;span class="hljs-keyword"&gt;export&lt;/span&gt; &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; metadata: Metadata = {
&lt;span class="hljs-attr"&gt;title&lt;/span&gt;: &lt;span class="hljs-string"&gt;'Example component'&lt;/span&gt;,
&lt;span class="hljs-attr"&gt;description&lt;/span&gt;: &lt;span class="hljs-string"&gt;'Learning Next.js SEO'&lt;/span&gt;,
};
&lt;span class="hljs-keyword"&gt;export&lt;/span&gt; &lt;span class="hljs-keyword"&gt;default&lt;/span&gt; &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title"&gt;Page&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;/span&gt;) &lt;/span&gt;{
&lt;span class="hljs-keyword"&gt;return&lt;/span&gt; (
&lt;span class="xml"&gt;&lt;span class="hljs-tag"&gt;&lt;&gt;&lt;/span&gt;
&lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;div&lt;/span&gt;&gt;&lt;/span&gt;Example page component…&lt;span class="hljs-tag"&gt;&lt;/&lt;span class="hljs-name"&gt;div&lt;/span&gt;&gt;&lt;/span&gt;
)      &lt;span class="hljs-tag"&gt;&lt;/&gt;&lt;/span&gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will automatically populate the &lt;strong&gt;examplePage.tsx&lt;/strong&gt; component with the proper HTML meta tags and given values.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;metadata&lt;/strong&gt; component offers a set of default tags as well, which automatically sets the following &lt;strong&gt;charset&lt;/strong&gt; and &lt;strong&gt;viewport&lt;/strong&gt; meta tags:&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-js"&gt;
&lt;meta charset=&lt;span class="hljs-string"&gt;"utf-8"&lt;/span&gt; /&gt;
&lt;span class="xml"&gt;&lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;meta&lt;/span&gt; &lt;span class="hljs-attr"&gt;name&lt;/span&gt;=&lt;span class="hljs-string"&gt;"viewport"&lt;/span&gt; &lt;span class="hljs-attr"&gt;content&lt;/span&gt;=&lt;span class="hljs-string"&gt;"width=device-width, initial-scale=1"&lt;/span&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="heading-nextjs-export-generatemetadata-example"&gt;Next.js export generateMetadata Example&lt;/h3&gt;
&lt;p&gt;In many applications, especially ecommerce, you’ll run across the need to dynamically populate meta tags, and ensure that this data always reflects changes to a database or some other store of data.&lt;/p&gt;
&lt;p&gt;For cases such as these, Next offers the &lt;strong&gt;generateMetadata&lt;/strong&gt; function, which can be exported from any page component along with any necessary API calls to fetch and inject the desired data.&lt;/p&gt;
&lt;p&gt;Here’s an example page component that utilizes this method:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;pageExample.tsx&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-js"&gt;&lt;span class="hljs-keyword"&gt;import&lt;/span&gt; type { Metadata } &lt;span class="hljs-keyword"&gt;from&lt;/span&gt; &lt;span class="hljs-string"&gt;'next'&lt;/span&gt;;
&lt;span class="hljs-keyword"&gt;async&lt;/span&gt; &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title"&gt;getInfo&lt;/span&gt;(&lt;span class="hljs-params"&gt;id&lt;/span&gt;) &lt;/span&gt;{
&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; res = &lt;span class="hljs-keyword"&gt;await&lt;/span&gt; fetch(&lt;span class="hljs-string"&gt;`https://someapi/product/&lt;span class="hljs-subst"&gt;${id}&lt;/span&gt;`&lt;/span&gt;);
&lt;span class="hljs-keyword"&gt;return&lt;/span&gt; res.json();
}
&lt;span class="hljs-keyword"&gt;export&lt;/span&gt; &lt;span class="hljs-keyword"&gt;async&lt;/span&gt; &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title"&gt;generateMetadata&lt;/span&gt;(&lt;span class="hljs-params"&gt;{ params }&lt;/span&gt;): &lt;span class="hljs-title"&gt;Promise&lt;/span&gt;&lt;&lt;span class="hljs-title"&gt;Metadata&lt;/span&gt;&gt; &lt;/span&gt;{
&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; product = &lt;span class="hljs-keyword"&gt;await&lt;/span&gt; getInfo(params.id);
&lt;span class="hljs-keyword"&gt;return&lt;/span&gt; { &lt;span class="hljs-attr"&gt;title&lt;/span&gt;: product.title }
}
&lt;span class="hljs-keyword"&gt;export&lt;/span&gt; &lt;span class="hljs-keyword"&gt;default&lt;/span&gt; &lt;span class="hljs-keyword"&gt;async&lt;/span&gt; &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title"&gt;Page&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;/span&gt;) &lt;/span&gt;{
&lt;span class="hljs-keyword"&gt;return&lt;/span&gt; (
&lt;span class="xml"&gt;&lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;div&lt;/span&gt;&gt;&lt;/span&gt;Example page…&lt;span class="hljs-tag"&gt;&lt;/&lt;span class="hljs-name"&gt;div&lt;/span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, we created a method that returns some information about a product from an API, and used that method in our &lt;strong&gt;generateMetadata&lt;/strong&gt; function to then populate the &lt;strong&gt;title&lt;/strong&gt; property. This in turn will set the title tag in our rendered HTML page.&lt;/p&gt;
&lt;p&gt;It’s important to note that the &lt;strong&gt;generateMetadata&lt;/strong&gt; function can only be used within server components, which we discussed earlier. Remember, all components within the &lt;strong&gt;app&lt;/strong&gt; directory are automatically configured as server components by default.&lt;/p&gt;
&lt;p&gt;For an exhaustive list of properties and property extensions available with the &lt;strong&gt;Metadata&lt;/strong&gt; component, take a look at the &lt;a target='_blank' rel='noopener'  href="https://beta.nextjs.org/docs/api-reference/metadata"&gt;docs&lt;/a&gt;. Pretty much anything you can think of can be accomplished with relative ease.&lt;/p&gt;
&lt;h2 id="heading-how-to-implement-structured-data-with-next-13"&gt;How to Implement Structured Data With Next 13&lt;/h2&gt;
&lt;p&gt;Next recommends adding structured JSON-LD data to the layout or page component. In all honesty, this has always been a much simpler solution because Google has never said anything about excluding structured data from the page itself.&lt;/p&gt;
&lt;p&gt;In fact, this has long been a common practice, and it’s a bit of a mystery as to why many developers have become fixed on the idea of placing it in the head tag.&lt;/p&gt;
&lt;h3 id="heading-how-to-add-structured-data-to-the-layout-or-page-component"&gt;How to Add Structured Data to the Layout or Page Component&lt;/h3&gt;
&lt;p&gt;Adding structured data to a component, whether the layout or page, looks something like this (example pulled straight from the docs):&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-js"&gt;&lt;span class="hljs-keyword"&gt;export&lt;/span&gt; &lt;span class="hljs-keyword"&gt;default&lt;/span&gt; &lt;span class="hljs-keyword"&gt;async&lt;/span&gt; &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title"&gt;Page&lt;/span&gt;(&lt;span class="hljs-params"&gt;{ params }&lt;/span&gt;) &lt;/span&gt;{
&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; product = &lt;span class="hljs-keyword"&gt;await&lt;/span&gt; getProduct(params.id);
&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; jsonLd = {
&lt;span class="hljs-string"&gt;'@context'&lt;/span&gt;: &lt;span class="hljs-string"&gt;'https://schema.org'&lt;/span&gt;,
&lt;span class="hljs-string"&gt;'@type'&lt;/span&gt;: &lt;span class="hljs-string"&gt;'Product'&lt;/span&gt;,
&lt;span class="hljs-attr"&gt;name&lt;/span&gt;: product.name,
&lt;span class="hljs-attr"&gt;image&lt;/span&gt;: product.image,
&lt;span class="hljs-attr"&gt;description&lt;/span&gt;: product.description
};
&lt;span class="hljs-keyword"&gt;return&lt;/span&gt; (
&lt;span class="xml"&gt;&lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;section&lt;/span&gt;&gt;&lt;/span&gt;
{/* Add JSON-LD to your page */}
&lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;script&lt;/span&gt; &lt;span class="hljs-attr"&gt;type&lt;/span&gt;=&lt;span class="hljs-string"&gt;"application/ld+json"&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class="javascript"&gt;{&lt;span class="hljs-built_in"&gt;JSON&lt;/span&gt;.stringify(jsonLd)}&lt;/span&gt;&lt;span class="hljs-tag"&gt;&lt;/&lt;span class="hljs-name"&gt;script&lt;/span&gt;&gt;&lt;/span&gt;
{/* ... */}
&lt;span class="hljs-tag"&gt;&lt;/&lt;span class="hljs-name"&gt;section&lt;/span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, this is super simple, and there’s really no need to complicate things by attempting to inject structured data into the head tag.&lt;/p&gt;
&lt;h2 id="heading-nextjs-seo-wrapping-things-up"&gt;Next.js SEO – Wrapping Things Up&lt;/h2&gt;
&lt;p&gt;We went over quite a bit here for &lt;a target='_blank' rel='noopener'  href="https://www.ohmycrawl.com/next-js-seo/"&gt;Nextjs SEO&lt;/a&gt;. From the new features included with Next 13 that aim to solve many SEO related problems, to old features being revamped and streamlined for a better developer experience, things are looking great for Next.&lt;/p&gt;
&lt;p&gt;If you plan on using Next.js as your framework of choice, I highly recommend experimenting with Next 13. Although features such as the Font component are still in beta, and the whole thing is still in canary (testing phase), much of version 13 is already considered stable and being used by many developers and the world's leading companies.&lt;/p&gt;
&lt;p&gt;Major version updates can be daunting, but make sure to read the full documentation and give it a spin in order to ensure you’re staying at the cutting edge of Next.js SEO.  &lt;/p&gt;
</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
