<?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" version="2.0"><channel><title><![CDATA[MyCodingNotebook]]></title><description><![CDATA[MyCodingNotebook is every developer's online notebook. Find coding insights, best practices, and solutions—ideal for all skill levels.]]></description><link>https://blog.mycodingnotebook.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1739012632405/25b71ff9-4f99-46db-8b92-92fd759800a4.png</url><title>MyCodingNotebook</title><link>https://blog.mycodingnotebook.com</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 14 Apr 2026 01:26:09 GMT</lastBuildDate><atom:link href="https://blog.mycodingnotebook.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Hot Module Replacement (HMR): How It Works and Why It Matters]]></title><description><![CDATA[Ever changed a button color, tweaked a UI element, or updated a function—only to refresh the page and lose everything? Losing form inputs, app state, or debugging progress due to a full reload is frustrating.
Hot Module Replacement (HMR) solves this ...]]></description><link>https://blog.mycodingnotebook.com/hot-module-replacement-hmr-how-it-works-and-why-it-matters</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/hot-module-replacement-hmr-how-it-works-and-why-it-matters</guid><category><![CDATA[Hot Module Replacement]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Tue, 11 Mar 2025 00:00:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741486309707/3980e910-dbf3-4d24-85df-3f1239ae180f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ever changed a button color, tweaked a UI element, or updated a function—only to refresh the page and lose everything? Losing form inputs, app state, or debugging progress due to a full reload is frustrating.</p>
<p><strong>Hot Module Replacement (HMR) solves this problem</strong> by enabling live updates of modules (JavaScript, CSS, etc.) in a running application without <strong>a full page refresh</strong>, preserving state and instantly reflecting code changes.</p>
<h2 id="heading-why-is-hmr-important">Why is HMR Important?</h2>
<ul>
<li><p><strong>Faster Feedback Loop</strong>: No need to reload the entire app after every change.</p>
</li>
<li><p><strong>Preserve Application State</strong>: Maintains the current state of the app during development.</p>
</li>
<li><p><strong>Improved Productivity</strong>: Reduces development time and frustration.</p>
</li>
</ul>
<h2 id="heading-the-problem-hmr-solves"><strong>The Problem HMR Solves</strong></h2>
<p>Before HMR, developers relied on <strong>Live Reload</strong>, which refreshed the entire page on every change. This reset the app’s state, making it tedious to debug interactions (e.g., multi-step forms, animations, and API-dependent UI changes).</p>
<h3 id="heading-hmr-vs-live-reload"><strong>HMR vs. Live Reload</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>HMR (Hot Module Replacement)</strong></td><td><strong>Live Reload</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>State Preservation</strong></td><td>Yes</td><td>No (State resets)</td></tr>
<tr>
<td><strong>Update Speed</strong></td><td>Faster (updates only modified code)</td><td>Slower (full page reload)</td></tr>
<tr>
<td><strong>Implementation Complexity</strong></td><td>Requires bundler support</td><td>Simple (just refreshes the page)</td></tr>
</tbody>
</table>
</div><h2 id="heading-how-hmr-works">How HMR Works</h2>
<p>HMR is typically implemented by bundlers like Webpack, Vite, and Parcel. The process involves multiple components and steps to efficiently replace modules without requiring a full reload.</p>
<h3 id="heading-core-components-of-hmr"><strong>Core Components of HMR</strong></h3>
<ol>
<li><p><strong>Module Graph</strong>:</p>
<ul>
<li><p>A dependency map of all files and their relationships</p>
</li>
<li><p>Used to determine which modules need recompilation when a file changes.</p>
</li>
<li><p>Example: Updating <code>styles.css</code> triggers updates in all modules that import it.</p>
</li>
</ul>
</li>
<li><p><strong>HMR Server</strong>:</p>
<ul>
<li><p>Runs alongside the development server (e.g., <code>webpack-dev-server</code>, <code>vite dev</code>).</p>
</li>
<li><p>Watches files for changes using operating system’s file system APIs (e.g., <code>inotify</code> on Linux, <code>FSWatch</code> on macOS).</p>
</li>
<li><p>Rebuilds <strong>only affected modules</strong> (via the module graph).</p>
</li>
<li><p>Sends updates to the client via the communication channel.</p>
</li>
</ul>
</li>
<li><p><strong>HMR Runtime</strong>:</p>
<ul>
<li><p>Injected into the browser by the bundler (e.g., as part of the app’s bundled code).</p>
</li>
<li><p>Listens for updates from the HMR server.</p>
</li>
<li><p>Applies new code dynamically (e.g., replacing modules, injecting CSS).</p>
</li>
<li><p>Handles errors and falls back to full reloads if needed.</p>
</li>
</ul>
</li>
<li><p><strong>Communication Channel</strong>:</p>
<ul>
<li><p>Enables real-time server-client messaging.</p>
</li>
<li><p>Uses <strong>WebSockets</strong> (not HTTP) for instant, bidirectional communication.</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-the-hmr-update-process"><strong>The HMR Update Process</strong></h3>
<p>Let’s go through the HMR update process using a simple react app as an example</p>
<h4 id="heading-1-buttonjsx-child-component">1. <code>Button.jsx</code> (Child Component)</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./styles.css'</span>;

<span class="hljs-keyword">const</span> Button = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
      <span class="hljs-attr">className</span>=<span class="hljs-string">"my-button"</span> 
      <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(c =&gt; c + 1)}
    &gt;
      Clicks: {count}
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Button;
</code></pre>
<h4 id="heading-2-appjsx-parent-component">2. <code>App.jsx</code> (Parent Component)</h4>
<pre><code class="lang-javascript"><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> Button <span class="hljs-keyword">from</span> <span class="hljs-string">'./Button'</span>;

<span class="hljs-keyword">const</span> App = <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">"app"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>HMR Demo<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Button</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> App;
</code></pre>
<h4 id="heading-3-stylescss">3. <code>styles.css</code></h4>
<pre><code class="lang-css"><span class="hljs-selector-class">.my-button</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">12px</span>;
  <span class="hljs-attribute">background</span>: blue;
  <span class="hljs-attribute">color</span>: white;
}
</code></pre>
<p>Currently, The counter shows <code>Clicks: 0</code>.</p>
<p>Now, let’s walkthrough the HMR process as we modify the button’s text from <code>"Clicks: {count}"</code> to <code>"Total Clicks: {count}"</code> and save <code>Button.jsx</code>.</p>
<h3 id="heading-step-1-change-detection">Step 1: Change Detection</h3>
<ul>
<li><p><strong>File Monitoring</strong>:<br />  The <strong>HMR server</strong> detects the <code>Button.jsx</code> change using OS-level watchers.</p>
</li>
<li><p><strong>Dependency Resolution</strong>:<br />  The <strong>module graph</strong> (a dependency map) identifies:</p>
<ul>
<li><p>Direct dependency: <code>styles.css</code> (imported by <code>Button.jsx</code>).</p>
</li>
<li><p>Parent relationship: <code>App.jsx</code> renders <code>Button.jsx</code>.</p>
</li>
</ul>
</li>
<li><p><strong>Change Validation</strong>:<br />  A content hash (e.g., SHA-1) verifies the change is significant (not whitespace) before proceeding with the update.</p>
</li>
</ul>
<h3 id="heading-step-2-partial-rebuilding">Step 2: Partial Rebuilding</h3>
<p>The goal here is to rebuild only affected modules for efficiency.</p>
<ul>
<li><p><strong>Partial Compilation</strong>:</p>
<ul>
<li><p><code>Button.jsx</code> and <code>styles.css</code> are recompiled.</p>
</li>
<li><p><code>App.jsx</code> is <strong>not</strong> recompiled—it only renders <code>Button</code> and isn’t tied to its internal logic.</p>
</li>
</ul>
</li>
<li><h5 id="heading-code-transformation"><strong>Code Transformation:</strong></h5>
<ul>
<li><h5 id="heading-transpilers-transform-the-code-into-browser-compatible-formats-such-as-transpiling-typescript-to-javascript-or-scss-to-css">Transpilers transform the code into browser-compatible formats, such as transpiling <strong>TypeScript to JavaScript</strong> or <strong>SCSS to CSS.</strong></h5>
</li>
</ul>
</li>
</ul>
<ul>
<li><p><strong>Preparing the Update Package</strong>:<br />  The bundler creates an update bundle containing:</p>
<pre><code class="lang-json">  {
    <span class="hljs-attr">"id"</span>: <span class="hljs-string">"src/Button.jsx"</span>,        <span class="hljs-comment">// Changed module ID</span>
    <span class="hljs-attr">"code"</span>: <span class="hljs-string">"/* Transpiled JS */"</span>, <span class="hljs-comment">// New component code</span>
    <span class="hljs-attr">"deps"</span>: [<span class="hljs-string">"src/styles.css"</span>]      <span class="hljs-comment">// Affected dependencies</span>
  }
</code></pre>
</li>
</ul>
<h3 id="heading-step-3-sending-updates">Step 3: Sending Updates</h3>
<ul>
<li><p>The <strong>HMR server</strong> then sends a <strong>WebSocket</strong> message to the client.</p>
</li>
<li><p>This message contains metadata, including the updated module's ID and new code.</p>
<pre><code class="lang-json">  {
    <span class="hljs-attr">"type"</span>: <span class="hljs-string">"hot-update"</span>,
    <span class="hljs-attr">"moduleId"</span>: <span class="hljs-string">"src/Button.jsx"</span>,
    <span class="hljs-attr">"code"</span>: <span class="hljs-string">"function Button() { ... }"</span>, <span class="hljs-comment">// New transpiled code</span>
    <span class="hljs-attr">"css"</span>: <span class="hljs-string">".my-button { ... }"</span> <span class="hljs-comment">// Updated CSS</span>
  }
</code></pre>
</li>
</ul>
<h3 id="heading-step-4-applying-updates">Step 4: Applying Updates</h3>
<p>Once the HMR runtime receives the updated module, it evaluates how to apply the changes efficiently without requiring a full page reload.</p>
<p><strong>Handling Different Types of Updates</strong></p>
<ul>
<li><p><strong>CSS Updates</strong></p>
<ul>
<li><p>The updated styles are injected into the DOM dynamically.</p>
</li>
<li><p>No page refresh occurs, preventing flickers or input losses.</p>
</li>
</ul>
</li>
<li><p><strong>JavaScript Module Updates</strong></p>
<p>  How HMR updates JavaScript modules <strong>depends on the bundler:</strong></p>
<ul>
<li><p><a target="_blank" href="https://webpack.js.org/api/hot-module-replacement/"><strong>Webpack</strong></a><strong>:</strong> Webpack does not automatically replace modules during HMR. Instead, modules must explicitly opt-in using <a target="_blank" href="https://webpack.js.org/api/hot-module-replacement/"><code>module.hotaccept()</code></a> for versions before Webpack 5 or <a target="_blank" href="https://webpack.js.org/api/hot-module-replacement/"><code>import.meta.webpackHot.accept()</code></a> for Webpack 5.</p>
<p>  Example: Enabling HMR for a JavaScript Module in Webpack</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">//counter.js</span>
  <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>;

  <span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">increment</span>(<span class="hljs-params"></span>) </span>{
    count++;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Count: <span class="hljs-subst">${count}</span>`</span>);
  }

  <span class="hljs-comment">// Accept HMR updates for this module</span>
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">import</span>.meta.webpackHot) {
    <span class="hljs-keyword">import</span>.meta.webpackHot.accept();
  }
</code></pre>
<p>  <strong>How It Works:</strong></p>
<ul>
<li><p>The <a target="_blank" href="https://webpack.js.org/api/hot-module-replacement/"><code>import.meta.webpackHot.accept()</code></a> method tells Webpack that this module can accept updates without requiring a full page reload.</p>
</li>
<li><p>When <code>counter.js</code> is modified, Webpack will replace it in memory and apply the updates dynamically.</p>
</li>
</ul>
</li>
<li><p><a target="_blank" href="https://vite.dev/guide/features.html#hot-module-replacement"><strong>Vite</strong></a> <strong>&amp;</strong> <a target="_blank" href="https://parceljs.org/blog/alpha1/#configuration"><strong>Parcel</strong></a><strong>:</strong> Unlike Webpack, <a target="_blank" href="https://vite.dev/guide/features.html#hot-module-replacement"><strong>Vite</strong></a> <strong>and</strong> <a target="_blank" href="https://parceljs.org/blog/alpha1/#configuration"><strong>Parcel</strong></a> <strong>automatically apply updates</strong> whenever they detect that a module can be safely replaced. They do not require explicit <a target="_blank" href="https://webpack.js.org/api/hot-module-replacement/"><code>import.meta.webpackHot.accept()</code></a>.</p>
</li>
</ul>
</li>
</ul>
<p>    Regardless of the bundler, if a module <strong>cannot self-update</strong>, HMR will:</p>
<ol>
<li><p><strong>Propagate the update up the dependency graph</strong>, searching for a parent module that can handle it.</p>
</li>
<li><p>If no parent can accept the update, <strong>a full page reload is triggered</strong> to ensure the application remains in a consistent state.</p>
</li>
</ol>
<ul>
<li><p><strong>React Component Updates</strong></p>
<p>  For React components, HMR is seamlessly managed by <a target="_blank" href="https://github.com/facebook/react/issues/16604#issuecomment-528663101"><strong>React Fast Refresh</strong></a>, which ensures:</p>
<ol>
<li><p><strong>Component Compatibility Check</strong></p>
<ul>
<li><p>If the component’s structure remains compatible (e.g., UI or text changes), <strong>HMR updates it in place</strong>.</p>
</li>
<li><p>If the structure <strong>changes significantly</strong> (e.g., new hooks or converting from a class to a function), the component <strong>remounts</strong> instead.</p>
</li>
</ul>
</li>
<li><p><strong>State Preservation</strong></p>
<ul>
<li>If the structure remains the same, React <strong>preserves state</strong> (e.g., <code>useState</code> values stay intact).</li>
</ul>
</li>
<li><p><strong>Efficient DOM Updates</strong></p>
<ul>
<li>React’s <strong>Virtual DOM ensures minimal re-renders</strong>, updating only what changed.</li>
</ul>
</li>
</ol>
</li>
</ul>
<p>    <strong>In our example:</strong></p>
<ul>
<li><p>If before saving <code>Button.jsx</code>, the counter displays: <code>Clicks: 3</code></p>
</li>
<li><p>After modifying the text to <code>Total Clicks: {count}</code> and saving,</p>
<ul>
<li><p>The text updates <strong>without a page reload</strong>.</p>
</li>
<li><p>The counter <strong>remains at 3</strong> because the component state is preserved</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-step-5-error-handling-and-recovery">Step 5: Error Handling and Recovery</h3>
<ul>
<li><p>If an error occurs while applying updates, the HMR runtime attempts to recover by retrying the update.</p>
</li>
<li><p>If errors persist, the application falls back to a <strong>full reload</strong> to ensure a consistent state.</p>
</li>
<li><p>HMR includes safeguards to prevent crashes:</p>
<ul>
<li><p><strong>Automatic Retries</strong>: Temporary issues (e.g., network errors) trigger retries.</p>
</li>
<li><p><strong>Fallback to Reload</strong>: If HMR cannot apply the update cleanly, a full reload is triggered.</p>
</li>
<li><p><strong>Clear Error Messages</strong>: The browser’s console displays warnings to help debug issues.</p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>HMR significantly enhances the development process by enabling real-time updates without requiring a full page refresh. It improves development speed, preserves state, and boosts productivity. Understanding its internal mechanisms allows developers to fully utilise HMR for a more efficient workflow. By understanding its inner workings and best practices, developers can fully leverage HMR’s capabilities for a smoother workflow.</p>
]]></content:encoded></item><item><title><![CDATA[Web Performance Optimisation Techniques IV - Asset Optimisation]]></title><description><![CDATA[Websites rely on assets such as images, fonts, and videos to deliver content. Asset optimisation involves refining these resources to ensure they load quickly and efficiently while maintaining quality. This process includes compression, format select...]]></description><link>https://blog.mycodingnotebook.com/web-performance-optimisation-techniques-iv-asset-optimisation</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/web-performance-optimisation-techniques-iv-asset-optimisation</guid><category><![CDATA[Performance Optimization]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[web performance]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Mon, 10 Mar 2025 00:00:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741281677539/1031a354-bad8-456c-ad6a-b531b9dc72ef.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Websites rely on assets such as images, fonts, and videos to deliver content. Asset optimisation involves refining these resources to ensure they load quickly and efficiently while maintaining quality. This process includes compression, format selection, and delivery optimisation to improve performance.</p>
<h2 id="heading-why-is-asset-optimisation-important">Why is Asset Optimisation Important?</h2>
<ol>
<li><p><strong>Improved Page Speed</strong>: Smaller assets reduce download times, directly enhancing load performance.</p>
</li>
<li><p><strong>Enhanced User Experience</strong>: Faster websites lower bounce rates and keep visitors engaged.</p>
</li>
<li><p><strong>SEO Benefits</strong>: Search engines like Google prioritise fast-loading websites in rankings.</p>
</li>
<li><p><strong>Bandwidth Efficiency</strong>: Optimised assets consume less data, benefiting users on limited mobile plans.</p>
</li>
</ol>
<h2 id="heading-how-to-optimise-assets">How to Optimise Assets</h2>
<h3 id="heading-1-image-optimisation">1. Image Optimisation</h3>
<p>Images often make up the largest portion of a webpage's total size. Optimising them involves:</p>
<ul>
<li><p><strong>Compression</strong>: Compression reduces the file size of images while maintaining an acceptable level of quality. There are two main types of compression:</p>
<ul>
<li><p><strong>Lossless Compression</strong>: This method reduces file size without any loss in quality by removing unnecessary metadata and optimising data structures. It is ideal for graphics requiring precision, such as logos and icons.</p>
</li>
<li><p><strong>Lossy Compression</strong>: This method achieves higher compression rates by discarding some image data, which may result in a slight quality loss. It is best suited for photographs and other complex images where minor quality degradation is acceptable.</p>
</li>
</ul>
</li>
</ul>
<p>    Tools that can be used for image compression include:</p>
<ul>
<li><p><a target="_blank" href="https://squoosh.app/"><strong>Squoosh</strong></a>: A powerful web-based tool that allows for both lossy and lossless compression.</p>
</li>
<li><p><a target="_blank" href="https://tinypng.com/"><strong>TinyPNG</strong></a>: Specialises in compressing PNG and JPEG files without significant quality loss.</p>
</li>
<li><p><a target="_blank" href="https://imageoptim.com/api/start">ImageOptim</a>: Lossless compression and metadata removal</p>
</li>
</ul>
<ul>
<li><p><strong>Modern Formats</strong>: Traditional formats like <strong>JPEG and PNG</strong> can be large and inefficient. In contrast, <strong>WebP and AVIF</strong> offer significantly better compression, reducing file sizes by <strong>30-50%</strong> while maintaining quality.</p>
<p>  To efficiently convert images, <a target="_blank" href="https://www.ffmpeg.org/documentation.html"><strong>FFmpeg</strong></a> provides a powerful command-line solution. However, since not all browsers support these modern formats, implementing <strong>fallbacks to traditional formats</strong> is essential to ensure compatibility. <strong>For example:</strong></p>
<pre><code class="lang-xml">  <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">srcset</span>=<span class="hljs-string">"image.avif"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/avif"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">source</span> <span class="hljs-attr">srcset</span>=<span class="hljs-string">"image.webp"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/webp"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"image.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"..."</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">picture</span>&gt;</span>
</code></pre>
</li>
<li><p><strong>Responsive Delivery</strong>: To ensure images look sharp on all devices while minimising bandwidth use, serve images in different sizes based on the user’s screen size. The <code>srcset</code> and <code>sizes</code> attributes allow browsers to choose the most appropriate image:</p>
<pre><code class="lang-xml">  <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">srcset</span>=<span class="hljs-string">"medium.jpg 800w, large.jpg 1200w"</span>  
       <span class="hljs-attr">sizes</span>=<span class="hljs-string">"(max-width: 600px) 800px, 1200px"</span>  
       <span class="hljs-attr">alt</span>=<span class="hljs-string">"..."</span>&gt;</span>
</code></pre>
</li>
<li><p><strong>Lazy Loading</strong>: Loading all images at once can slow down page performance. Instead, defer loading images that are not immediately visible using the <code>loading="lazy"</code> attribute. This improves initial page load time and conserves bandwidth:</p>
<pre><code class="lang-xml">  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"image.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Lazy Loaded Image"</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span>&gt;</span>
</code></pre>
</li>
</ul>
<h3 id="heading-2-video-and-multimedia-optimisation">2. Video and Multimedia Optimisation</h3>
<p>Videos are large assets that require efficient handling to ensure smooth playback without unnecessary bandwidth consumption.</p>
<ul>
<li><p><strong>Compression</strong>: Use tools like <a target="_blank" href="https://handbrake.fr/"><strong>HandBrake</strong></a> to reduce resolution and bitrate while maintaining quality.</p>
</li>
<li><p><strong>Streaming Over Hosting</strong>: Instead of self-hosting, use platforms like <a target="_blank" href="https://vimeo.com/"><strong>YouTube</strong></a> or <a target="_blank" href="https://vimeo.com/"><strong>Vimeo</strong></a>, which offer optimised streaming, adaptive bitrate playback, and CDN distribution, ensuring fast loading times and better performance across different devices and network conditions.</p>
</li>
<li><p><strong>Disable Autoplay</strong>: Allow users to control video playback rather than consuming bandwidth automatically. This approach enhances user experience, conserves mobile data, and prevents unnecessary distractions.</p>
</li>
<li><p><strong>Use HTML5 Video Instead of GIFs</strong>: MP4 files are significantly smaller and more efficient than GIFs. Unlike large, looping GIFs, MP4 videos provide the same visual effect with better compression and playback controls. <strong>For example,</strong> a looping animation can be implemented using HTML5 video:</p>
<pre><code class="lang-xml">  <span class="hljs-tag">&lt;<span class="hljs-name">video</span> <span class="hljs-attr">autoplay</span> <span class="hljs-attr">loop</span> <span class="hljs-attr">muted</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">source</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"animation.mp4"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"video/mp4"</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">video</span>&gt;</span>
</code></pre>
</li>
</ul>
<h3 id="heading-3-font-optimisation">3. Font Optimisation</h3>
<p>Custom fonts enhance the aesthetics of a website but can negatively impact performance if not optimized properly. To improve font efficiency, several techniques can be applied:</p>
<ul>
<li><p><strong>Subsetting</strong>: Reducing font size by removing unused characters and language-specific glyphs can significantly decrease file size. Tools like <strong>Google Fonts Subsetting</strong> allow developers to include only the necessary characters, improving load times.</p>
</li>
<li><p><strong>Efficient Font Formats</strong>: Using highly compressed font formats such as <strong>woff2</strong> ensures faster loading while maintaining quality. Since <strong>woff2</strong> is supported by most modern browsers, it is the preferred format for web fonts.</p>
</li>
<li><p><strong>Preloading Critical Fonts</strong>: To prevent layout shifts caused by delayed font loading, critical fonts should be preloaded. This ensures they are available as soon as the page renders. The following example demonstrates how to preload a font file:</p>
<pre><code class="lang-xml">  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"preload"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"font.woff2"</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"font"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"font/woff2"</span> <span class="hljs-attr">crossorigin</span>&gt;</span>
</code></pre>
</li>
<li><p><strong>System Font Fallbacks</strong>: To minimise reliance on external font files, developers should define system fonts as fallback options. Using widely available fonts like <strong>Arial</strong> or <strong>Helvetica</strong> helps maintain readability while reducing additional HTTP requests.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In a world where more than <a target="_blank" href="https://www.cloudflare.com/resources/assets/slt3lc6tev37/1PdxTNFdaTagVJ1zxxTKCX/1310183e51d5f7997fbea47fbe7c3ef6/Getting-faster-website-performance-whitepaper_Q42019.pdf"><strong>53% of users abandon sites taking over 3 seconds to load</strong></a>, asset optimisation is not optional—it’s essential. By optimising images, fonts, and multimedia, developers can significantly improve page load times, enhance user experience, and boost SEO rankings.</p>
<p>Moreover, prioritising asset optimisation not only benefits end users by providing a smoother browsing experience but also reduces bandwidth consumption and server load, making websites more scalable and cost-effective.</p>
]]></content:encoded></item><item><title><![CDATA[Web Performance Optimisation Techniques III - Tree Shaking]]></title><description><![CDATA[Tree shaking is a term borrowed from the concept of shaking a tree to remove dead leaves. In the context of web development, it refers to the process of eliminating unused or "dead" code from an application during the build process. This is particula...]]></description><link>https://blog.mycodingnotebook.com/web-performance-optimisation-techniques-iii-tree-shaking</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/web-performance-optimisation-techniques-iii-tree-shaking</guid><category><![CDATA[Web Development]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[web performance]]></category><category><![CDATA[Performance Optimization]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Sun, 09 Mar 2025 00:00:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741294904762/4f3cee00-99b3-4065-84e2-21e326cfd76f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Tree shaking is a term borrowed from the concept of shaking a tree to remove dead leaves. <strong>In the context of web development</strong>, it refers to the process of <strong>eliminating unused or "dead" code</strong> from an application <strong>during the build process.</strong> This is particularly useful in JavaScript applications, where large libraries might be imported, but only a small portion of them is actually used.</p>
<p>The term was popularised by the JavaScript bundler <a target="_blank" href="https://rollupjs.org/faqs/#what-is-tree-shaking"><strong>Rollup</strong></a>, but it has since been adopted by other bundlers like <strong>Webpack</strong>, <strong>Parcel</strong>, and <strong>Vite</strong>. In this guide, we’ll explore the importance of tree shaking, how it works under the hood, and best practices to maximise its effectiveness.</p>
<h2 id="heading-why-is-tree-shaking-important"><strong>Why is Tree Shaking Important?</strong></h2>
<ul>
<li><p><strong>Smaller Bundle Sizes</strong>:</p>
<p>  One of the primary benefits of tree shaking is that it reduces the size of the final JavaScript bundle. Smaller bundles mean faster load times, which is crucial for user experience, especially on mobile devices or slow networks.</p>
</li>
<li><p><strong>Improved Performance:</strong></p>
<p>  By removing unused code, applications become more efficient. Less code means less parsing, compiling, and executing, which leads to better runtime performance.</p>
</li>
<li><p><strong>Dead Code Identification:</strong></p>
<p>  Highlights unused modules or dependencies during bundling, helping developers identify and remove dead code from source files. This reduces bloat and technical debt, ensuring a leaner, more maintainable codebase over time</p>
</li>
</ul>
<h2 id="heading-the-mechanics-of-tree-shaking"><strong>The Mechanics of Tree shaking</strong></h2>
<p>To understand how tree shaking works, it is essential to dive into the mechanics behind it. At its core, tree shaking relies on <strong>static analysis</strong>, a process where the bundler analyses code without executing it.</p>
<p>Let’s break this down.</p>
<h3 id="heading-the-role-of-static-analysis"><strong>The Role of Static Analysis</strong></h3>
<p>Static analysis is the backbone of tree shaking. It allows the bundler to analyse code at build time and determine which parts are actually used. This is only possible with <strong>static code</strong>.</p>
<p><strong>Static vs. Dynamic Code</strong></p>
<ul>
<li><p><strong>Static Code</strong>: Code that <strong>can</strong> be analysed at <strong>build time</strong> or <strong>before the application runs</strong>. (e.g., <code>import</code> and <code>export</code> statements in ES6 modules).</p>
</li>
<li><p><strong>Dynamic Code</strong>: Code that <strong>cannot</strong> be analysed <strong>until runtime</strong> (e.g.,<code>require</code> statements in CommonJS or dynamic imports).</p>
</li>
</ul>
<p>Tree shaking works <strong>best</strong> with static code because the <strong>bundler can make decisions about what to include or exclude before the application runs</strong>.</p>
<h2 id="heading-how-tree-shaking-works"><strong>How Tree Shaking Works</strong></h2>
<p>Tree shaking is a multi-step process that occurs during the build phase of an application. To better understand how this process works, let’s walk through a simple example step by step.</p>
<p><strong>Consider the following two files:</strong></p>
<ol>
<li><code>math.js</code></li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-comment">// math.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> add = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a + b;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> subtract = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a - b;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> multiply = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a * b;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> divide = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a / b;
</code></pre>
<ol start="2">
<li><code>main.js</code></li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-comment">// main.js</span>
<span class="hljs-keyword">import</span> { add, multiply } <span class="hljs-keyword">from</span> <span class="hljs-string">'./math.js'</span>;

<span class="hljs-built_in">console</span>.log(add(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>));       <span class="hljs-comment">// Only `add` is used</span>
<span class="hljs-built_in">console</span>.log(multiply(<span class="hljs-number">2</span>, <span class="hljs-number">4</span>));  <span class="hljs-comment">// Only `multiply` is used</span>
</code></pre>
<p><strong>In this example,</strong></p>
<ul>
<li><p>The <code>math.js</code> module exports four functions: <code>add</code>, <code>subtract</code>, <code>multiply</code>, and <code>divide</code>.</p>
</li>
<li><p>However, in <code>main.js</code>, only the <code>add</code> and <code>multiply</code> functions are imported and used.</p>
</li>
<li><p>The goal of tree shaking is to ensure that only these two functions are included in the final bundle, while <code>subtract</code> and <code>divide</code> are removed as unused code.</p>
</li>
</ul>
<h3 id="heading-step-by-step-process-of-tree-shaking"><strong>Step-by-Step Process of Tree Shaking</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741482277141/9a21d4ca-96f3-44a7-a9e5-82870ede49b5.png" alt class="image--center mx-auto" /></p>
<ol>
<li><h3 id="heading-static-analysis-of-imports-and-exports">Static Analysis of Imports and Exports</h3>
<p> The bundler analyses all <code>import</code> statements in the code to identify which modules and functions are being used. It also examines the <code>export</code> statements to understand what is being exposed by each module.</p>
<h4 id="heading-how-static-analysis-works">How Static Analysis Works</h4>
<p> Static analysis is typically performed using an <strong>Abstract Syntax Tree (AST)</strong>. An AST is a tree representation of the structure of the code, where each node corresponds to a construct in the source code (e.g., a function, variable, or expression).</p>
<p> <strong>For example, the AST for</strong> <code>math.js</code> <strong>might look like this:</strong></p>
<pre><code class="lang-json"> {
   <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Program"</span>,
   <span class="hljs-attr">"body"</span>: [
     {
       <span class="hljs-attr">"type"</span>: <span class="hljs-string">"ExportNamedDeclaration"</span>,
       <span class="hljs-attr">"declaration"</span>: {
         <span class="hljs-attr">"type"</span>: <span class="hljs-string">"FunctionDeclaration"</span>,
         <span class="hljs-attr">"id"</span>: { <span class="hljs-attr">"name"</span>: <span class="hljs-string">"add"</span> },
         <span class="hljs-attr">"params"</span>: [...],
         <span class="hljs-attr">"body"</span>: [...]
       }
     },
     {
       <span class="hljs-attr">"type"</span>: <span class="hljs-string">"ExportNamedDeclaration"</span>,
       <span class="hljs-attr">"declaration"</span>: {
         <span class="hljs-attr">"type"</span>: <span class="hljs-string">"FunctionDeclaration"</span>,
         <span class="hljs-attr">"id"</span>: { <span class="hljs-attr">"name"</span>: <span class="hljs-string">"subtract"</span> },
         <span class="hljs-attr">"params"</span>: [...],
         <span class="hljs-attr">"body"</span>: [...]
       }
     },
     ...
   ]
 }
</code></pre>
<p> <strong>The bundler uses the AST to:</strong></p>
<ul>
<li><p>Identify which functions are exported from <code>math.js</code> (<code>add</code>, <code>subtract</code>, <code>multiply</code>, and <code>divide</code>).</p>
</li>
<li><p>Determine which functions are imported and used in <code>main.js</code> (<code>add</code> and <code>multiply</code>).</p>
</li>
</ul>
</li>
</ol>
<p>    By analysing these statements, the bundler can determine which functions are used and which are not.</p>
<ol start="2">
<li><h3 id="heading-building-a-dependency-graph"><strong>Building a Dependency Graph</strong></h3>
<p> Once the bundler has analysed the imports and exports, it constructs a <strong>dependency graph</strong>. This graph represents the relationships between modules and functions in the application.</p>
<ul>
<li><p><strong>Nodes</strong>: Each module or function is a node in the graph.</p>
</li>
<li><p><strong>Edges</strong>: The edges represent dependencies between modules (e.g., <code>main.js</code> depends on <code>math.js</code>).</p>
</li>
</ul>
</li>
</ol>
<p>    The dependency graph helps the bundler understand which parts of the code are reachable from the <strong>entry point</strong> of the application (e.g., <code>main.js</code>).</p>
<p>    For example, the dependency graph for the above code might look like this:</p>
<pre><code class="lang-plaintext">    main.js
      └── math.js
          ├── add
          └── multiply
</code></pre>
<p>    <strong>In this graph:</strong></p>
<ul>
<li><p><code>main.js</code> is the entry point.</p>
</li>
<li><p><code>math.js</code> is a dependency of <code>main.js</code>.</p>
</li>
<li><p>Only <code>add</code> and <code>multiply</code> are connected to the entry point (<code>main.js</code>), meaning they are used in the application.</p>
</li>
</ul>
<p>    The <code>subtract</code> and <code>divide</code> functions are not connected to the entry point, so they are considered unreachable.</p>
<ol start="3">
<li><h3 id="heading-dead-code-elimination"><strong>Dead Code Elimination</strong></h3>
<p> After building the dependency graph, the bundler identifies and removes any code that is not reachable from the entry point. This process is known as <strong>dead code elimination</strong>.</p>
<ul>
<li><p><strong>Reachable Code</strong>: Code that is directly or indirectly referenced from the entry point is kept.</p>
</li>
<li><p><strong>Unreachable Code</strong>: Code that is not referenced (e.g., unused functions or modules) is removed.</p>
</li>
</ul>
</li>
</ol>
<p>    In the example above, the <code>subtract</code> and <code>divide</code> functions are unreachable and will be eliminated.</p>
<h2 id="heading-challenges-with-tree-shaking"><strong>Challenges with Tree Shaking</strong></h2>
<p>While tree shaking is a powerful optimisation technique, it is not without its challenges:</p>
<ol>
<li><h3 id="heading-dynamic-code"><strong>Dynamic Code</strong></h3>
<p> Because tree shaking relies on <strong>static analysis</strong>, it cannot determine which parts of dynamically loaded modules will be used. As a result, the bundler may include the entire module in the final bundle, even if only a small portion is needed.</p>
<p> <strong>Example: Dynamic Imports</strong></p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./math.js'</span>).then(<span class="hljs-function"><span class="hljs-params">math</span> =&gt;</span> {
   <span class="hljs-built_in">console</span>.log(math.add(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>));
 });
</code></pre>
<p> <strong>In this case:</strong></p>
<ul>
<li><p>The bundler cannot determine which functions from <code>math.js</code> will be used at runtime.</p>
</li>
<li><p>As a result, it may include the entire <code>math.js</code> module in the bundle, even if only the <code>add</code> function is needed.</p>
</li>
</ul>
</li>
</ol>
<p>    <strong>Another Example: CommonJS Modules</strong></p>
<p>    CommonJS is a module system used in Node.js and older JavaScript projects. It uses <code>require</code> and <code>module.exports</code> to define and import modules. However, CommonJS is inherently <strong>dynamic</strong>, which makes tree shaking difficult or impossible.</p>
<p>    Let’s rewrite our earlier example to use commonJS:</p>
<h4 id="heading-mathjs"><code>math.js</code></h4>
<pre><code class="lang-javascript">    <span class="hljs-comment">// math.js</span>
    <span class="hljs-built_in">exports</span>.add = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a + b;
    <span class="hljs-built_in">exports</span>.subtract = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a - b;
    <span class="hljs-built_in">exports</span>.multiply = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a * b;
    <span class="hljs-built_in">exports</span>.divide = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a / b;
</code></pre>
<h4 id="heading-mainjs"><code>main.js</code></h4>
<pre><code class="lang-javascript">    <span class="hljs-comment">// main.js</span>
    <span class="hljs-keyword">const</span> math = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./math.js'</span>);

    <span class="hljs-built_in">console</span>.log(math.add(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>));       <span class="hljs-comment">// Only `add` is used</span>
    <span class="hljs-built_in">console</span>.log(math.multiply(<span class="hljs-number">2</span>, <span class="hljs-number">4</span>));  <span class="hljs-comment">// Only `multiply` is used</span>
</code></pre>
<p>    <strong>In this example:</strong></p>
<ul>
<li><p>The <code>require</code> statement dynamically loads the <code>math.js</code> module.</p>
</li>
<li><p>The bundler cannot determine which functions (<code>add</code>, <code>subtract</code>, <code>multiply</code>, <code>divide</code>) will be used at runtime.</p>
</li>
<li><p>As a result, the entire <code>math.js</code> module is included in the bundle, even though only <code>add</code> and <code>multiply</code> are used.</p>
</li>
</ul>
<ol start="2">
<li><h3 id="heading-side-effects"><strong>Side Effects</strong></h3>
<p> Code with side effects cannot be safely removed, even if it appears unused.</p>
<p> <strong>For example:</strong></p>
<pre><code class="lang-javascript"> <span class="hljs-comment">// side-effect.js</span>
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'This is a side effect!'</span>);

 <span class="hljs-comment">// main.js</span>
 <span class="hljs-keyword">import</span> <span class="hljs-string">'./side-effect.js'</span>;
</code></pre>
<p> Even though <code>side-effect.js</code> does not export anything, the <code>console.log</code> statement is a side effect, so it will be included in the bundle.</p>
</li>
</ol>
<h2 id="heading-best-practices-for-effective-tree-shaking">Best Practices for Effective Tree Shaking</h2>
<p>To get the most out of tree shaking, follow these best practices:</p>
<ol>
<li><p><strong>Use ES6 Modules</strong></p>
<ul>
<li>Whenever possible, use ES6 modules (<code>import</code>/<code>export</code>) instead of CommonJS (<code>require</code>/<code>module.exports</code>). ES6 modules have a static structure that enables effective tree shaking.</li>
</ul>
</li>
<li><p><strong>Avoid Dynamic Imports</strong></p>
<ul>
<li>Use static imports whenever possible. Reserve dynamic imports for cases where lazy loading is absolutely necessary.</li>
</ul>
</li>
<li><p><strong>Minimise Side Effects</strong></p>
<ul>
<li><p>Whenever possible, try to write pure functions as they are easier to tree shake because they don’t have side effects.</p>
</li>
<li><p>However, If your code has side effects, use the <code>sideEffects</code> property in <code>package.json</code> to indicate which files have side effects. This helps the bundler make better decisions about what to include or exclude.</p>
<p>  <strong>Example:</strong></p>
<pre><code class="lang-json">  <span class="hljs-comment">//package.json</span>
  {
    <span class="hljs-attr">"sideEffects"</span>: [
      <span class="hljs-string">"src/some-side-effectful-file.js"</span>,
      <span class="hljs-string">"*.css"</span>
    ]
  }
</code></pre>
</li>
</ul>
</li>
</ol>
<ol start="4">
<li><p><strong>Optimise Third-Party Libraries</strong></p>
<ul>
<li><p>Look for libraries that support ES6 modules and have minimal side effects.</p>
</li>
<li><p>Also, use tools like Babel or Rollup to convert a third-party library that uses CommonJS to ES6 modules.</p>
</li>
</ul>
</li>
</ol>
<h2 id="heading-popular-bundlers-that-support-tree-shaking">Popular bundlers That Support Tree Shaking</h2>
<p>Below is a table summarising the popular bundlers that support tree shaking:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Bundler</strong></td><td><strong>Key Features</strong></td></tr>
</thead>
<tbody>
<tr>
<td><a target="_blank" href="https://webpack.js.org/guides/tree-shaking/#root"><strong>Webpack</strong></a></td><td>Requires <code>mode: 'production'</code> and <code>sideEffects</code> property in <code>package.json</code>.</td></tr>
<tr>
<td><a target="_blank" href="https://rollupjs.org/faqs/#what-is-tree-shaking"><strong>Rollup</strong></a></td><td>First bundler to introduce tree shaking. Automatically performs tree shaking with ES6 modules.</td></tr>
<tr>
<td><a target="_blank" href="https://parceljs.org/blog/beta1/#tree-shaking"><strong>Parcel</strong></a></td><td>Zero-configuration bundler with built-in tree shaking support.</td></tr>
<tr>
<td><a target="_blank" href="https://vite.dev/"><strong>Vite</strong></a></td><td>Uses <strong>ESBuild</strong> for fast bundling and <strong>Rollup</strong> for production builds. Supports tree shaking during development and production.</td></tr>
</tbody>
</table>
</div><h2 id="heading-in-conclusion">In Conclusion,</h2>
<p>Tree shaking is a powerful technique for optimizing JavaScript applications. By eliminating unused code, it significantly reduces bundle sizes, improves performance, and enhances maintainability. While tree shaking is most effective with ES6 modules, it’s important to follow best practices and be aware of common pitfalls to get the most out of it.</p>
]]></content:encoded></item><item><title><![CDATA[Web Performance Optimisation Techniques II: Code Splitting]]></title><description><![CDATA[Code splitting is a technique where an application’s code is divided into smaller chunks or bundles, which are loaded on demand. Instead of loading the entire application at once, only the code needed for the current view is loaded. This improves per...]]></description><link>https://blog.mycodingnotebook.com/web-performance-optimisation-techniques-ii-code-splitting</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/web-performance-optimisation-techniques-ii-code-splitting</guid><category><![CDATA[Web Development]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Performance Optimization]]></category><category><![CDATA[web performance]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Sat, 08 Mar 2025 00:00:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741281634442/eccd8a7c-3367-4df2-a8ac-66614b9ff2f5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Code splitting is a technique where an application’s code is divided into smaller chunks or bundles, which are loaded <strong>on demand</strong>. Instead of loading the entire application at once, only the code needed for the current view is loaded. This improves performance and user experience by reducing the initial load time and optimising resource usage.</p>
<h2 id="heading-why-is-code-splitting-important"><strong>Why is Code Splitting Important?</strong></h2>
<ul>
<li><p><strong>Faster Initial Load Times</strong>: By loading only the code required for the initial page view, the application starts faster.</p>
</li>
<li><p><strong>Enhanced User Experience</strong>: Users spend less time waiting for the app to become interactive.</p>
</li>
<li><p><strong>Efficient Resource Usage</strong>: Prevents unnecessary code from being loaded, saving bandwidth and processing power.</p>
</li>
<li><p><strong>Improved Caching</strong>: Shared modules are cached and reused across different parts of the application, reducing the number of server requests.</p>
</li>
</ul>
<h2 id="heading-key-concepts-for-code-splitting"><strong>Key Concepts for Code Splitting</strong></h2>
<p>To understand how code splitting works, let’s first explore two key concepts: <strong>dynamic imports</strong> and <strong>lazy loading</strong>. These concepts work together to make code splitting possible and effective.</p>
<h3 id="heading-what-are-dynamic-imports"><strong>What are Dynamic Imports?</strong></h3>
<p>Dynamic imports are a <strong>JavaScript feature</strong> that allows you to load modules (or chunks of code) <strong>asynchronously at runtime</strong>, rather than loading everything upfront. Instead of using a regular <code>import</code> statement (which loads all the code immediately), you use the <code>import()</code> function, which returns a <strong>Promise</strong>. This means the code is only loaded when it’s actually needed.</p>
<h4 id="heading-example-static-import-vs-dynamic-import">Example: Static Import vs. Dynamic Import</h4>
<pre><code class="lang-javascript"><span class="hljs-comment">// Static import (loads immediately)</span>
<span class="hljs-keyword">import</span> myModule <span class="hljs-keyword">from</span> <span class="hljs-string">'./myModule.js'</span>;

<span class="hljs-comment">// Dynamic import (loads only when needed)</span>
<span class="hljs-keyword">import</span>(<span class="hljs-string">'./myModule.js'</span>).then(<span class="hljs-function">(<span class="hljs-params"><span class="hljs-built_in">module</span></span>) =&gt;</span> {
  <span class="hljs-built_in">module</span>.default(); <span class="hljs-comment">// Use the module after it's loaded</span>
});
</code></pre>
<p><strong>In the example above:</strong></p>
<ul>
<li><p>The <strong>static import</strong> loads <code>myModule.js</code> as soon as the app starts.</p>
</li>
<li><p>The <strong>dynamic import</strong> loads <code>myModule.js</code> only when the <code>import()</code> function is called.</p>
</li>
</ul>
<p>This means the code inside <code>myModule.js</code> won’t be downloaded until it’s actually required, which is the foundation of <strong>code splitting</strong>.</p>
<h3 id="heading-what-is-lazy-loading"><strong>What is Lazy Loading?</strong></h3>
<p>Lazy loading is a <strong>design pattern</strong> that delays the loading of non-essential resources (like JavaScript modules, components, or images) until they are actually needed. This helps improve performance by reducing the amount of code loaded upfront.</p>
<h4 id="heading-how-does-lazy-loading-work">How Does Lazy Loading Work?</h4>
<ul>
<li><p>Lazy loading of <strong>javascript modules</strong> is typically implemented using <strong>dynamic imports</strong> (<code>import()</code>). For example, instead of loading a component immediately, you load it only when the user interacts with a specific feature or navigates to a specific route.</p>
</li>
<li><p><strong>Also,</strong> different frameworks provide built-in ways to implement lazy loading. For instance <strong>React</strong> uses <code>React.lazy</code> and <strong>Vue</strong> uses <code>defineAsyncComponent</code> to lazy-load components.</p>
</li>
</ul>
<h2 id="heading-tools-for-code-splitting"><strong>Tools for Code Splitting</strong></h2>
<p>Code Splitting is implemented using a combination of <strong>framework-specific tools</strong> and <strong>general-purpose build tools</strong>. These tools work hand in hand to achieve efficient code splitting:</p>
<ul>
<li><p><strong>Framework-Specific Tools</strong>: These are built into frameworks like React, Vue, and Angular. They provide easy-to-use features to define split points and lazy-load components.</p>
</li>
<li><p><strong>General-Purpose Build Tools</strong>: They handle the actual splitting of code into smaller chunks and optimise the bundles for production.</p>
</li>
</ul>
<h3 id="heading-framework-specific-tools"><strong>Framework Specific Tools</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Tool</strong></td><td><strong>Framework</strong></td><td><strong>Key Feature</strong></td></tr>
</thead>
<tbody>
<tr>
<td><a target="_blank" href="https://react.dev/reference/react/lazy"><strong>React.lazy</strong></a></td><td>React</td><td>Built-in React feature for lazy-loading components with <code>Suspense</code>.</td></tr>
<tr>
<td><a target="_blank" href="https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#1-code-splitting"><strong>Next.js</strong></a></td><td>React</td><td>Automatic route-based splitting and dynamic imports.</td></tr>
<tr>
<td><a target="_blank" href="https://vuejs.org/api/general.html#defineasynccomponent"><strong>defineAsyncComponent</strong></a></td><td>Vue</td><td>Vue’s feature for lazy-loading components using dynamic imports.</td></tr>
<tr>
<td><a target="_blank" href="https://angular.dev/guide/routing/common-router-tasks#lazy-loading"><strong>Angular Router</strong></a></td><td>Angular</td><td>Router-based lazy loading with <code>loadChildren</code>.</td></tr>
<tr>
<td><a target="_blank" href="https://router.vuejs.org/guide/advanced/lazy-loading.html#Lazy-Loading-Routes"><strong>Vue Router</strong></a></td><td>Vue.js</td><td>Lazy-loaded routes using dynamic imports.</td></tr>
</tbody>
</table>
</div><h3 id="heading-general-purpose-build-tools"><strong>General Purpose Build Tools</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Tool</strong></td><td><strong>Key Feature</strong></td></tr>
</thead>
<tbody>
<tr>
<td><a target="_blank" href="https://webpack.js.org/guides/code-splitting/"><strong>Webpack</strong></a></td><td>Built-in support for dynamic imports and shared dependency optimization.</td></tr>
<tr>
<td><a target="_blank" href="https://vite.dev/guide/features.html#css-code-splitting"><strong>Vite</strong></a></td><td>Native ESM support for fast builds and automatic code splitting.</td></tr>
<tr>
<td><a target="_blank" href="https://rollupjs.org/tutorial/#code-splitting"><strong>Rollup</strong></a></td><td>Supports dynamic imports and manual chunking.</td></tr>
<tr>
<td><a target="_blank" href="https://parceljs.org/recipes/react/#code-splitting"><strong>Parcel</strong></a></td><td>Zero-configuration code splitting with dynamic imports.</td></tr>
<tr>
<td><a target="_blank" href="https://www.snowpack.dev/guides/optimize-and-bundle#nav-primary"><strong>Snowpack</strong></a></td><td>Native ESM support for fast builds and code splitting.</td></tr>
<tr>
<td><a target="_blank" href="https://rsbuild.dev/guide/optimization/code-splitting">Rsbuild</a></td><td>High-performance Rust-powered build system with efficient code splitting.</td></tr>
</tbody>
</table>
</div><h2 id="heading-practical-implementation-of-code-splitting"><strong>Practical Implementation of Code Splitting</strong></h2>
<p>Now, let’s explore how code splitting works under the hood using a simple React app with the following files:</p>
<ul>
<li><strong>App.js (Main entry point)</strong></li>
</ul>
<pre><code class="lang-javascript"><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> { BrowserRouter <span class="hljs-keyword">as</span> Router, Route, Routes, Link } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;
<span class="hljs-keyword">import</span> HomePage <span class="hljs-keyword">from</span> <span class="hljs-string">'./HomePage'</span>;
<span class="hljs-keyword">import</span> Dashboard <span class="hljs-keyword">from</span> <span class="hljs-string">'./Dashboard'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Router</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span> | <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/dashboard"</span>&gt;</span>Dashboard<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">HomePage</span> /&gt;</span>} /&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/dashboard"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Dashboard</span> /&gt;</span>} /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Router</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<ul>
<li><strong>HomePage.js</strong></li>
</ul>
<pre><code class="lang-javascript"><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> HomePage = <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>&gt;</span>Welcome to the Home Page!<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> HomePage;
</code></pre>
<ul>
<li><strong>Dashboard.js</strong></li>
</ul>
<pre><code class="lang-javascript"><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> Dashboard = <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>&gt;</span>Welcome to the Dashboard!<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> Dashboard;
</code></pre>
<p><strong>In this version:</strong></p>
<ul>
<li><p><strong>Initial Load:</strong> The browser downloads the entire JavaScript bundle (e.g., <code>main.js</code>), which includes <code>App.js</code>, <code>HomePage.js</code>, and <code>Dashboard.js</code>.</p>
</li>
<li><p><strong>No On-Demand Loading</strong>: Since all components are bundled together, the app loads everything upfront, which can lead to slower initial load times especially for larger applications.</p>
</li>
</ul>
<h3 id="heading-adding-code-splitting-to-the-app"><strong>Adding Code Splitting to the App</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741482637474/9048e662-a8a7-484d-a545-5b2ac1deb6d0.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-step-1-specifying-split-points">Step 1: Specifying Split Points</h3>
<p>The developer defines <strong>split points</strong> in the code using the framework-specific tool.</p>
<p><strong>Let’s modify</strong> <code>App.js</code> <strong>to use</strong> <code>React.lazy</code> <strong>and</strong> <code>Suspense</code> <strong>for lazy loading:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { Suspense, lazy } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { BrowserRouter <span class="hljs-keyword">as</span> Router, Route, Routes, Link } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;

<span class="hljs-comment">// Lazy-load the components</span>
<span class="hljs-keyword">const</span> HomePage = lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./HomePage'</span>));
<span class="hljs-keyword">const</span> Dashboard = lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./Dashboard'</span>));

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Router</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span> | <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/dashboard"</span>&gt;</span>Dashboard<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
      <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">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>}&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">HomePage</span> /&gt;</span>} /&gt;
          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/dashboard"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Dashboard</span> /&gt;</span>} /&gt;
        <span class="hljs-tag">&lt;/<span class="hljs-name">Routes</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">Router</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h4 id="heading-whats-happening-here">What’s Happening Here?</h4>
<ul>
<li><p>We have specified that <code>HomePage</code> and <code>Dashboard</code> should be loaded <strong>on demand</strong> using lazy loading.</p>
</li>
<li><p><code>&lt;Suspense fallback={&lt;div&gt;Loading...&lt;/div&gt;}&gt;</code> provides a fallback UI while the components are being loaded.</p>
</li>
</ul>
<h3 id="heading-step-2-build-tool-analyses-the-code">Step 2: Build Tool Analyses the Code</h3>
<p>Once the developer specifies the split points, the <strong>build tool</strong> (e.g., Webpack, Vite) analyses the application’s codebase to:</p>
<ul>
<li><p>Identify dependencies and entry points.</p>
</li>
<li><p>Create a <strong>dependency graph</strong>, which maps out how all the modules (files) in the application are connected.</p>
</li>
</ul>
<p><strong>For the example above,</strong> the dependency graph might look like this:</p>
<pre><code class="lang-plaintext">App.js
├── HomePage.js
└── Dashboard.js
</code></pre>
<p><strong>This graph tells the tool that:</strong></p>
<ul>
<li><p><code>App.js</code> depends on <code>HomePage.js</code> and <code>Dashboard.js</code>.</p>
</li>
<li><p><code>HomePage.js</code> and <code>Dashboard.js</code> are independent of each other.</p>
</li>
</ul>
<h3 id="heading-step-3-build-tool-splits-the-code">Step 3: Build Tool Splits the Code</h3>
<p>Based on the dependency graph and split points, the build tool divides the code into smaller chunks. The splitting is done based on:</p>
<ul>
<li><p><strong>Dynamic Imports</strong>: Code that is loaded only when needed (e.g., <code>import('./HomePage')</code>).</p>
</li>
<li><p><strong>Entry Points</strong>: Different parts of the application (e.g., homepage, dashboard) can be split into separate bundles.</p>
</li>
<li><p><strong>Shared Dependencies</strong>: Common modules (e.g., libraries like <code>React</code>) are split into shared bundles to avoid duplication.</p>
</li>
</ul>
<h3 id="heading-step-4-build-tool-generates-bundles">Step 4: Build Tool Generates Bundles</h3>
<p>The build tool generates multiple smaller bundles instead of one large bundle. Here’s what the output might look like after code splitting:</p>
<pre><code class="lang-plaintext">dist/
├── main.js
├── HomePage.chunk.js
└── Dashboard.chunk.js
</code></pre>
<ul>
<li><p><strong>main.js</strong> (Initial bundle containing <code>App.js</code> and shared dependencies like <code>React</code>).</p>
</li>
<li><p><strong>HomePage.chunk.js</strong> (Chunk for the <code>HomePage</code> component).</p>
</li>
<li><p><strong>Dashboard.chunk.js</strong> (Chunk for the <code>Dashboard</code> component).</p>
</li>
</ul>
<h3 id="heading-step-5-loading-bundles-in-the-browser">Step 5: Loading Bundles in the Browser</h3>
<p>When the application runs in the browser, the <strong>code splitting technique</strong> comes into play:</p>
<ol>
<li><p><strong>Initial Load</strong>:</p>
<ul>
<li><p>The browser loads <code>main.js</code>, which contains the core application logic and the <code>Suspense</code> fallback UI.</p>
</li>
<li><p>The code for <code>HomePage</code> and <code>Dashboard</code> is <strong>not</strong> included in the initial bundle.</p>
</li>
</ul>
</li>
<li><p><strong>On-Demand Loading</strong>:</p>
<ul>
<li><p>When the user navigates to the home page, the browser dynamically fetches <code>HomePage.chunk.js</code> and renders the <code>HomePage</code> component.</p>
</li>
<li><p>When the user navigates to the dashboard, the browser dynamically fetches <code>Dashboard.chunk.js</code> and renders the <code>Dashboard</code> component.</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-note-caching-and-reusing-bundles">Note: Caching and Reusing Bundles</h3>
<ul>
<li><p><strong>Shared Dependencies</strong>: If multiple chunks depend on the same module (e.g., <code>React</code>), the build tool ensures that the module is only included once in a shared bundle. This reduces duplication and improves caching.</p>
</li>
<li><p><strong>Browser Caching</strong>: Once a chunk is loaded, it is cached by the browser. If the user revisits the same part of the application, the chunk is loaded from the cache instead of being downloaded again.</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Code splitting is a powerful technique to optimise web applications by loading only the necessary code upfront and fetching additional chunks on demand. By combining <strong>dynamic imports</strong>, <strong>lazy loading</strong>, and the right tools (both <strong>framework-specific</strong> and <strong>general-purpose build tools</strong>), developers can significantly improve performance, reduce load times, and enhance user experience.</p>
]]></content:encoded></item><item><title><![CDATA[Web Performance Optimisation Techniques I: Minification]]></title><description><![CDATA[Minification is the process of removing unnecessary characters from code, such as whitespaces, comments, and formatting, without altering its functionality. The primary goal is to reduce file size, enabling websites to load faster by minimising the a...]]></description><link>https://blog.mycodingnotebook.com/web-performance-optimisation-techniques-i-minification</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/web-performance-optimisation-techniques-i-minification</guid><category><![CDATA[Web Development]]></category><category><![CDATA[web performance]]></category><category><![CDATA[Performance Optimization]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Fri, 07 Mar 2025 14:00:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741281298537/53e9cba1-0c6b-43f4-b2e5-958d7bf8c46e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Minification is the process of <strong>removing unnecessary characters</strong> from code, such as whitespaces, comments, and formatting, <strong>without altering its functionality</strong>. The primary goal is to reduce file size, enabling websites to load faster by minimising the amount of data browsers need to process.</p>
<h2 id="heading-why-is-minification-important"><strong>Why is Minification Important?</strong></h2>
<ul>
<li><p><strong>Faster Loading Times</strong>: Smaller files result in quicker downloads, enhancing the user experience by reducing wait times.</p>
</li>
<li><p><strong>Improved Performance</strong>: Browsers can process minified code more efficiently, as there’s less extraneous information to sift through.</p>
</li>
<li><p><strong>Saves Bandwidth</strong>: Minification decreases the data transferred between the server and the user, which is particularly beneficial for mobile users or those with slower internet connections.</p>
</li>
</ul>
<h3 id="heading-how-does-minification-work"><strong>How Does Minification Work?</strong></h3>
<p>Let’s walk through the minification process step by step using a simple JavaScript example.</p>
<h4 id="heading-original-javascript-code"><strong>Original JavaScript Code</strong></h4>
<pre><code class="lang-javascript"><span class="hljs-comment">// Calculate the square of a number</span>
<span class="hljs-keyword">const</span> square = <span class="hljs-function">(<span class="hljs-params">number</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> number * number;
};

<span class="hljs-built_in">console</span>.log(square(<span class="hljs-number">5</span>));
</code></pre>
<p><strong>Here’s a breakdown of what happens during minification:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741482915006/50ac2304-8b17-4743-808b-c09c05f72392.png" alt class="image--center mx-auto" /></p>
<ol>
<li><h4 id="heading-parsing-the-code"><strong>Parsing the Code</strong></h4>
<p> The minification tool reads the original code (e.g., JavaScript, CSS, or HTML) and parses it into a structured format, such as an <strong>Abstract Syntax Tree (AST)</strong>. An AST is a tree representation of the code's structure, but it’s often represented in a <strong>JSON-like format</strong> for clarity and ease of understanding.</p>
<p> <strong>So for our example, a simplified AST representation could look like this:</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1740561533359/badd7df7-7a6d-4d74-b92a-f1058824e5c1.png" alt class="image--center mx-auto" /></p>
<p> <strong>And in JSON format:</strong></p>
<pre><code class="lang-json"> {
   <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Program"</span>,
   <span class="hljs-attr">"body"</span>: [
     {
       <span class="hljs-attr">"type"</span>: <span class="hljs-string">"VariableDeclaration"</span>,
       <span class="hljs-attr">"declarations"</span>: [
         {
           <span class="hljs-attr">"type"</span>: <span class="hljs-string">"VariableDeclarator"</span>,
           <span class="hljs-attr">"id"</span>: {
             <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Identifier"</span>,
             <span class="hljs-attr">"name"</span>: <span class="hljs-string">"square"</span>
           },
           <span class="hljs-attr">"init"</span>: {
             <span class="hljs-attr">"type"</span>: <span class="hljs-string">"ArrowFunctionExpression"</span>,
             <span class="hljs-attr">"params"</span>: [
               {
                 <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Identifier"</span>,
                 <span class="hljs-attr">"name"</span>: <span class="hljs-string">"number"</span>
               }
             ],
             <span class="hljs-attr">"body"</span>: {
               <span class="hljs-attr">"type"</span>: <span class="hljs-string">"BlockStatement"</span>,
               <span class="hljs-attr">"body"</span>: [
                 {
                   <span class="hljs-attr">"type"</span>: <span class="hljs-string">"ReturnStatement"</span>,
                   <span class="hljs-attr">"argument"</span>: {
                     <span class="hljs-attr">"type"</span>: <span class="hljs-string">"BinaryExpression"</span>,
                     <span class="hljs-attr">"operator"</span>: <span class="hljs-string">"*"</span>,
                     <span class="hljs-attr">"left"</span>: {
                       <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Identifier"</span>,
                       <span class="hljs-attr">"name"</span>: <span class="hljs-string">"number"</span>
                     },
                     <span class="hljs-attr">"right"</span>: {
                       <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Identifier"</span>,
                       <span class="hljs-attr">"name"</span>: <span class="hljs-string">"number"</span>
                     }
                   }
                 }
               ]
             }
           }
         }
       ],
       <span class="hljs-attr">"kind"</span>: <span class="hljs-string">"const"</span>
     },
     {
       <span class="hljs-attr">"type"</span>: <span class="hljs-string">"ExpressionStatement"</span>,
       <span class="hljs-attr">"expression"</span>: {
         <span class="hljs-attr">"type"</span>: <span class="hljs-string">"CallExpression"</span>,
         <span class="hljs-attr">"callee"</span>: {
           <span class="hljs-attr">"type"</span>: <span class="hljs-string">"MemberExpression"</span>,
           <span class="hljs-attr">"object"</span>: {
             <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Identifier"</span>,
             <span class="hljs-attr">"name"</span>: <span class="hljs-string">"console"</span>
           },
           <span class="hljs-attr">"property"</span>: {
             <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Identifier"</span>,
             <span class="hljs-attr">"name"</span>: <span class="hljs-string">"log"</span>
           }
         },
         <span class="hljs-attr">"arguments"</span>: [
           {
             <span class="hljs-attr">"type"</span>: <span class="hljs-string">"CallExpression"</span>,
             <span class="hljs-attr">"callee"</span>: {
               <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Identifier"</span>,
               <span class="hljs-attr">"name"</span>: <span class="hljs-string">"square"</span>
             },
             <span class="hljs-attr">"arguments"</span>: [
               {
                 <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Literal"</span>,
                 <span class="hljs-attr">"value"</span>: <span class="hljs-number">5</span>
               }
             ]
           }
         ]
       }
     }
   ]
 }
</code></pre>
</li>
<li><h4 id="heading-removing-unnecessary-characters"><strong>Removing Unnecessary Characters</strong></h4>
<p> The minification tool then analyses the AST and removes or shortens parts of the code that aren’t needed for execution. This includes:</p>
<ul>
<li><p><strong>Whitespace</strong>: Spaces, tabs, and line breaks are removed to make the code more compact.</p>
<p>  Example: <code>const square = (number) =&gt; {</code> becomes <code>const square=number=&gt;{</code></p>
</li>
<li><p><strong>Comments</strong>: Developer notes are removed.</p>
<p>  Example: <code>// Calculate the square of a number</code> is removed entirely.</p>
</li>
<li><p><strong>Unnecessary Semicolons</strong>: Optional semicolons are removed.</p>
<p>  Example: <code>return number * number;</code> becomes <code>return number*number</code>.</p>
</li>
<li><p><strong>Curly Braces</strong>: If the function body is a single statement, the curly braces can be removed.</p>
<p>  Example: <code>{ return number * number; }</code> becomes <code>number*number</code>.</p>
</li>
<li><p><strong>Long Variable Names</strong>: If <a target="_blank" href="https://en.wikipedia.org/wiki/Obfuscation_\(software\)">obfuscation</a> is enabled, variable names like <code>number</code> might be shortened further (e.g., to <code>x</code>).</p>
</li>
</ul>
</li>
</ol>
<ol start="3">
<li><h4 id="heading-optimising-the-code"><strong>Optimising the Code</strong></h4>
<p> The tool performs additional optimisations, such as:</p>
<ul>
<li><p><strong>Shortening Syntax</strong>: For example, converting <code>(number) =&gt; { return number * number; }</code> to <code>number=&gt;number*number</code>.</p>
</li>
<li><p><strong>Removing Unused Code</strong>: If there were unused functions or variables, they would be removed. In this example, all code is used, so nothing is removed.</p>
</li>
</ul>
</li>
</ol>
<ol start="4">
<li><h4 id="heading-generating-the-minified-output"><strong>Generating the Minified Output</strong></h4>
<p> The tool converts the optimised AST back into a single, compact line of code. The result is a much smaller file that works the same way as the original.</p>
<p> <strong>Minified Code:</strong></p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> square=<span class="hljs-function"><span class="hljs-params">number</span>=&gt;</span>number*number;<span class="hljs-built_in">console</span>.log(square(<span class="hljs-number">5</span>));
</code></pre>
</li>
</ol>
<h2 id="heading-examples-of-minifiers"><strong>Examples of Minifiers</strong></h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Language</strong></td><td><strong>Tool</strong></td></tr>
</thead>
<tbody>
<tr>
<td>HTML</td><td><a target="_blank" href="https://www.npmjs.com/package/html-minifier">HTMLMinifier</a>, <a target="_blank" href="https://webpack.js.org/plugins/html-minimizer-webpack-plugin/">HTMLMinimizerWebpackPlugin</a>, <a target="_blank" href="https://www.npmjs.com/package/vite-plugin-minify">VitePluginMinify</a></td></tr>
<tr>
<td>CSS</td><td><a target="_blank" href="https://cssnano.github.io/cssnano/"><strong>CSSNano</strong></a>, <a target="_blank" href="https://purgecss.com/"><strong>PurgeCSS</strong></a>, <a target="_blank" href="https://www.cleancss.com/">CleanCSS</a></td></tr>
<tr>
<td>Javascript</td><td><a target="_blank" href="https://terser.org/"><strong>Terser</strong></a>, <a target="_blank" href="https://github.com/mishoo/UglifyJS#readme">UglifyJS</a>, <a target="_blank" href="https://developers.google.com/closure/compiler">Google Closure Compiler</a>, <a target="_blank" href="https://esbuild.github.io/">esbuild</a></td></tr>
</tbody>
</table>
</div><h2 id="heading-conclusion">Conclusion</h2>
<p>Minification is a crucial technique for optimising web performance. By reducing file sizes, it enhances loading times, improves browser efficiency, and conserves bandwidth. Understanding the minification process and utilising the appropriate tools can significantly boost the performance of your website, providing a better experience for your users. Whether you're working with HTML, CSS, or JavaScript, incorporating minification into your development workflow is a smart and effective strategy for modern web development.</p>
]]></content:encoded></item><item><title><![CDATA[Introduction to Web Performance Optimisation Techniques]]></title><description><![CDATA[Ever clicked on a website, only to stare at a blank screen for what feels like forever? Or tried to navigate a page that takes ages to respond to your clicks? These frustrating experiences are often the result of poor web performance. In today’s fast...]]></description><link>https://blog.mycodingnotebook.com/introduction-to-web-performance-optimisation-techniques</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/introduction-to-web-performance-optimisation-techniques</guid><category><![CDATA[Performance Optimization]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[web performance]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Wed, 05 Mar 2025 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741281797681/a53d17a7-d4df-4891-9ce1-2abee0901345.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ever clicked on a website, only to stare at a blank screen for what feels like forever? Or tried to navigate a page that takes ages to respond to your clicks? These frustrating experiences are often the result of poor web performance. In today’s fast-paced digital world, users expect websites to load quickly and run smoothly. If a site is slow or unresponsive, they’re likely to leave and never return.</p>
<p>This is where <strong>web performance optimisation</strong> comes in. By adopting the right techniques, developers can ensure their applications are fast, efficient, and user-friendly. In this article, we’ll explore key optimisation strategies, including <strong>Minification, Code Splitting, Tree Shaking, Asset Optimisation, Caching, Content Delivery Networks (CDNs), Reducing HTTP Requests, Critical Rendering Path Optimisation, etc.</strong> We’ll also discuss common performance bottlenecks, how performance impacts web applications, and how to measure performance effectively.</p>
<h2 id="heading-common-performance-bottlenecks"><strong>Common Performance Bottlenecks</strong></h2>
<p>Before diving into optimisation techniques, it’s important to understand the key areas where performance issues often arise. These bottlenecks can slow down websites, frustrate users, and even hurt businesses. Let’s take a closer look at the most common culprits:</p>
<ol>
<li><p><strong>Large JavaScript Bundles:</strong></p>
<ul>
<li><p><strong>What Happens:</strong> When a website relies on large JavaScript files, the browser takes longer to download and execute them.</p>
</li>
<li><p><strong>Impact:</strong> This delays the time it takes for a page to become interactive, especially on slower networks or devices.</p>
</li>
</ul>
</li>
<li><p><strong>Unoptimised Assets:</strong></p>
<ul>
<li><p><strong>What Happens:</strong> Large images, fonts, and videos can significantly slow down a website.</p>
</li>
<li><p><strong>Impact:</strong> For instance, a high-resolution image that hasn’t been compressed can take several seconds to load, making the site feel sluggish and unresponsive.</p>
</li>
</ul>
</li>
<li><p><strong>Render-blocking Resources:</strong></p>
<ul>
<li><p><strong>What Happens:</strong> CSS and JavaScript files that block the rendering of a page can delay the display of content.</p>
</li>
<li><p><strong>Impact:</strong> Users might see a blank screen for several seconds before anything appears, leading to a poor first impression.</p>
</li>
</ul>
</li>
<li><p><strong>Inefficient Network Requests:</strong></p>
<ul>
<li><p><strong>What Happens:</strong> If a website makes too many HTTP requests or sends uncompressed data, it can slow down page loading.</p>
</li>
<li><p><strong>Impact:</strong> Each request adds overhead, and uncompressed files take longer to download, increasing overall load times.</p>
</li>
</ul>
</li>
<li><p><strong>Lack of Caching:</strong></p>
<ul>
<li><p><strong>What Happens:</strong> Without proper caching, browsers and servers have to re-download the same assets every time a user visits the site.</p>
</li>
<li><p><strong>Impact:</strong> This wastes bandwidth and increases load times, especially for returning visitors.</p>
</li>
</ul>
</li>
</ol>
<h2 id="heading-how-performance-impacts-web-applications"><strong>How Performance Impacts Web Applications</strong></h2>
<p>Now that we’ve identified the bottlenecks, let’s explore how they impact web applications in terms of user experience, SEO, and business revenue.</p>
<ol>
<li><p><strong>User Experience (UX):</strong></p>
<p> A fast-loading website is crucial for keeping users engaged. According to this <a target="_blank" href="https://www.thinkwithgoogle.com/marketing-strategies/app-and-mobile/mobile-page-speed-new-industry-benchmarks/">research</a> by Google, when page load time rises from <strong>1 second to 3 seconds</strong>, bounce probability increases by <strong>32%</strong>. This escalates to <strong>90%</strong> at <strong>5 seconds</strong> and peaks at <strong>123%</strong> by <strong>10 seconds</strong>. Slow performance directly frustrates users, leading to higher abandonment rates and lower engagement.</p>
</li>
<li><p><strong>Search Engine Optimisation (SEO):</strong></p>
<p> Search engines like <a target="_blank" href="https://developers.google.com/search/docs/appearance/core-web-vitals"><strong>Google</strong></a> prioritise fast-loading websites. <strong>Key ranking factors</strong> include Google’s Core Web Vitals metrics like <strong>Largest Contentful Paint</strong> (LCP), <strong>Interaction to Next Paint</strong> (INP), and <strong>Cumulative Layout Shift</strong> (CLS). Websites that load in <strong>under 2.5 seconds</strong> tend to rank higher in search results, increasing organic traffic.</p>
</li>
<li><p><strong>Business and Revenue:</strong></p>
<p> Web performance is a critical driver of revenue and customer loyalty in the digital age. Recent studies highlight the stark financial impact of delays:</p>
<ul>
<li><p><a target="_blank" href="https://medium.com/pinterest-engineering/driving-user-growth-with-performance-improvements-cfc50dafadd7">Pinterest</a> in 2016 boosted sign-ups by <strong>15%</strong> by reducing perceived load time by <strong>40%</strong>.</p>
</li>
<li><p><a target="_blank" href="https://portent.com/blog/analytics/research-site-speed-hurting-everyones-revenue.htm">Portent’s</a> 2022 analysis reveals sites loading in <strong>1 second</strong> achieve <strong>2.5x higher conversions</strong> than those taking <strong>5 seconds</strong>.</p>
</li>
<li><p><a target="_blank" href="http://web.dev/case-studies/rakuten">Rakuten</a> streamlined its mobile experience, reducing page load time by <strong>40%</strong>, which boosted conversions by <strong>15%</strong>.</p>
</li>
<li><p><a target="_blank" href="http://web.dev/case-studies/vodafone">Vodafone</a> improved Core Web Vitals, cutting Largest Contentful Paint (LCP) by <strong>31%</strong> and increasing sales by <strong>8%</strong>.</p>
</li>
<li><p><a target="_blank" href="https://web.dev/case-studies/redbus-inp">redBus</a> optimised Interaction to Next Paint (INP) by <strong>75%</strong>, reducing checkout latency and increasing bookings by <strong>13%</strong>.</p>
</li>
</ul>
</li>
</ol>
<h2 id="heading-how-is-web-performance-measured"><strong>How is Web Performance Measured?</strong></h2>
<p>To address these bottlenecks, it’s essential to measure performance effectively. Web performance is measured using a combination of <strong>metrics</strong>, <strong>tools</strong>, and <strong>real-user data.</strong> These measurements help identify bottlenecks, track improvements, and ensure applications meet user expectations.</p>
<h3 id="heading-key-performance-metrics"><strong>Key Performance Metrics</strong></h3>
<p>Performance metrics provide quantifiable data about how a website or application behaves. Some of the most important metrics include:</p>
<ol>
<li><p><a target="_blank" href="https://web.dev/articles/lcp"><strong>Largest Contentful Paint (LCP)</strong></a>:</p>
<ul>
<li><p>Measures how long it takes for the largest content element (e.g., an image or text block) to load.</p>
</li>
<li><p><strong>Goal</strong>: Less than <strong>2.5 seconds</strong>.</p>
</li>
</ul>
</li>
<li><p><a target="_blank" href="https://web.dev/articles/inp"><strong>Interaction to Next Paint (INP):</strong></a></p>
<ul>
<li><p>Measures how quickly a page responds to user actions (e.g., clicks or taps).</p>
</li>
<li><p><strong>Goal</strong>: Less than <strong>200 milliseconds</strong>.</p>
</li>
</ul>
</li>
<li><p><a target="_blank" href="https://web.dev/articles/cls"><strong>Cumulative Layout Shift (CLS)</strong></a>:</p>
<ul>
<li><p>Measures how much the page layout shifts during loading, which can cause elements to move unexpectedly.</p>
</li>
<li><p><strong>Goal</strong>: <strong>Less than 0.1</strong> score.</p>
</li>
</ul>
</li>
<li><p><a target="_blank" href="https://web.dev/articles/fcp"><strong>First Contentful Paint (FCP)</strong></a><strong>:</strong></p>
<ul>
<li><p>Measures time until the first text, image, or other content appears on the screen.</p>
</li>
<li><p><strong>Goal</strong>: Less than <strong>1.8 seconds</strong>.</p>
</li>
</ul>
</li>
<li><p><a target="_blank" href="https://web.dev/articles/ttfb"><strong>Time to First Byte</strong> <strong>(TTFB)</strong></a>:</p>
<ul>
<li><p>Measures how long it takes for the browser to receive the first byte of data from the server.</p>
</li>
<li><p><strong>Goal</strong>: <strong>0.8 seconds</strong> or less.</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-real-world-data-vs-lab-data"><strong>Real-World Data vs. Lab Data</strong></h3>
<ul>
<li><p><strong>Lab Data</strong>: Collected in a controlled environment using tools like Lighthouse or PageSpeed Insights. Useful for identifying potential issues during development.</p>
</li>
<li><p><strong>Real-World Data</strong>: Collected from actual users using Real User Monitoring (RUM) tools. Provides insights into how real users experience the site under different conditions.</p>
</li>
</ul>
<h3 id="heading-tools-for-measuring-performance"><strong>Tools for Measuring Performance</strong></h3>
<p>Here’s a table of popular tools for measuring web performance:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Tool</strong></td><td><strong>Purpose</strong></td><td><strong>Key metrics</strong></td></tr>
</thead>
<tbody>
<tr>
<td><a target="_blank" href="https://developers.google.com/web/tools/lighthouse/">Lighthouse</a></td><td>Lab-based audits for performance, SEO, and accessibility.</td><td><a target="_blank" href="https://web.dev/articles/lcp"><strong>LCP</strong></a>, <a target="_blank" href="https://web.dev/articles/inp"><strong>INP</strong></a>, <a target="_blank" href="https://web.dev/articles/cls"><strong>CLS</strong></a>.</td></tr>
<tr>
<td><a target="_blank" href="https://pagespeed.web.dev/">PageSpeed Insights</a></td><td>Combines lab and field data (<a target="_blank" href="https://developer.chrome.com/docs/crux/">CrUX</a>) to analyse performance.</td><td><a target="_blank" href="https://web.dev/articles/lcp"><strong>LCP</strong></a>, <a target="_blank" href="https://web.dev/articles/inp"><strong>INP</strong></a>, <a target="_blank" href="https://web.dev/articles/cls"><strong>CLS</strong></a>, <a target="_blank" href="https://web.dev/articles/ttfb"><strong>TTFB</strong></a>.</td></tr>
<tr>
<td><a target="_blank" href="https://chromewebstore.google.com/detail/core-web-vitals-visualize/mcffmgagphgpgkdclllnilokablhjcge">Web Vitals Extension</a></td><td>Real-time Core Web Vitals measurement.</td><td><a target="_blank" href="https://web.dev/articles/lcp"><strong>LCP</strong></a>, <a target="_blank" href="https://web.dev/articles/inp"><strong>INP</strong></a>, <a target="_blank" href="https://web.dev/articles/cls"><strong>CLS</strong></a>.</td></tr>
<tr>
<td><a target="_blank" href="https://gtmetrix.com/">GTmetrix</a></td><td>Lab testing with waterfall analysis.</td><td><a target="_blank" href="https://web.dev/articles/ttfb"><strong>TTFB</strong></a>, Load time, page size.</td></tr>
<tr>
<td><a target="_blank" href="https://analytics.google.com/analytics/web/provision/#/provision">Google Analytics</a></td><td>Tracks real-user metrics (RUM).</td><td>Page load time, bounce rate, engagement.</td></tr>
<tr>
<td><a target="_blank" href="https://www.webpagetest.org/"><strong>WebPageTest</strong></a></td><td>Advanced lab testing for global performance analysis.</td><td>Speed Index, <a target="_blank" href="https://web.dev/articles/fcp"><strong>FCP</strong></a>, video rendering analysis.</td></tr>
<tr>
<td><a target="_blank" href="https://developer.chrome.com/docs/devtools/performance/overview"><strong>Chrome DevTools</strong></a></td><td>Web performance profiling.</td><td><a target="_blank" href="https://web.dev/articles/lcp"><strong>LCP</strong></a>, <a target="_blank" href="https://web.dev/articles/inp"><strong>INP</strong></a>, <a target="_blank" href="https://web.dev/articles/cls"><strong>CLS</strong></a>.</td></tr>
</tbody>
</table>
</div><h2 id="heading-techniques-to-optimise-web-performance"><strong>Techniques to Optimise Web Performance</strong></h2>
<p>Now that we’ve identified the bottlenecks and how to measure performance, let’s explore the strategies to optimise web performance.</p>
<h3 id="heading-frontend-optimisations"><strong>Frontend Optimisations</strong></h3>
<p>These techniques focus on optimising how the browser loads and renders content.</p>
<ol>
<li><h4 id="heading-minification"><strong>Minification</strong></h4>
<ul>
<li><p>Removes unnecessary characters (like spaces, comments, and line breaks) from code without changing its functionality.</p>
</li>
<li><p><strong>Impact</strong>: Reduces file sizes (especially for CSS/JS), improving download speeds.</p>
</li>
<li><p><strong>Tools</strong>: <a target="_blank" href="https://terser.org/">Terser</a> (JS), <a target="_blank" href="https://cssnano.github.io/cssnano/">CSSNano</a> (CSS).</p>
</li>
</ul>
</li>
</ol>
<ol start="2">
<li><h4 id="heading-code-splitting"><strong>Code Splitting</strong></h4>
<ul>
<li><p>Splits code into smaller chunks loaded on demand (e.g., per route or feature).</p>
</li>
<li><p><strong>Impact</strong>: Reduces initial bundle size, speeding up first-page loads.</p>
</li>
<li><p><strong>Tools</strong>: <a target="_blank" href="https://webpack.js.org/guides/code-splitting/">Webpack</a>, <a target="_blank" href="https://vite.dev/guide/features.html#css-code-splitting">Vite</a>, <a target="_blank" href="https://react.dev/reference/react/lazy">React.lazy</a>.</p>
</li>
</ul>
</li>
</ol>
<ol start="3">
<li><h4 id="heading-tree-shaking"><strong>Tree Shaking</strong></h4>
<ul>
<li><p>Removes unused code from dependencies.</p>
</li>
<li><p><strong>Impact</strong>: Reduces bundle bloat from third-party libraries.</p>
</li>
<li><p><strong>Tools</strong>: <a target="_blank" href="https://webpack.js.org/guides/tree-shaking/#root">Webpack</a>, <a target="_blank" href="https://rollupjs.org/faqs/#what-is-tree-shaking">Rollup</a>.</p>
</li>
</ul>
</li>
</ol>
<ol start="4">
<li><h4 id="heading-asset-optimisation"><strong>Asset Optimisation</strong></h4>
<ul>
<li><p>Compresses images (WebP/AVIF), fonts (subsetting), and videos (modern codecs).</p>
</li>
<li><p><strong>Impact</strong>: Reduces media file sizes by up to 80% without quality loss.</p>
</li>
<li><p><strong>Tools</strong>: <a target="_blank" href="https://imageoptim.com/api/start">ImageOptim</a>, <a target="_blank" href="https://squoosh.app/">Squoosh</a>, <a target="_blank" href="https://www.ffmpeg.org/documentation.html">FFmpeg</a>.</p>
</li>
</ul>
</li>
</ol>
<ol start="5">
<li><p><strong>Reducing HTTP Requests</strong></p>
<ul>
<li><p><strong>Impact:</strong> Minimises network round trips, improving load times.</p>
</li>
<li><p><strong>Methods:</strong> Combine CSS/JS files, use sprites for images, inline critical CSS, and reduce unnecessary third-party scripts.</p>
</li>
</ul>
</li>
<li><p><strong>Critical Rendering Path Optimisation</strong></p>
<ul>
<li><p>Prioritises loading styles/scripts needed for above-the-fold content.</p>
</li>
<li><p><strong>Impact:</strong> Reduces render-blocking resources, improving First Contentful Paint (FCP) and Interaction to Next Paint (INP).</p>
</li>
<li><p><strong>Methods:</strong> <code>async</code>/<code>defer</code> scripts, inline critical CSS, preload key assets.</p>
</li>
</ul>
</li>
<li><p><strong>Web Workers</strong></p>
<ul>
<li><p><strong>Impact:</strong> Enhances page responsiveness by offloading CPU-intensive tasks, improving smoothness in animations and interactions.</p>
</li>
<li><p><strong>Tools:</strong> <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers">Native Web Workers API</a>.</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-server-side-optimisations"><strong>Server-Side Optimisations</strong></h3>
<p>These techniques enhance performance by optimising how content is served and delivered.</p>
<ol>
<li><p><strong>Caching</strong></p>
<ul>
<li><p>Stores resources locally (browser) or on CDNs to avoid re-fetching.</p>
</li>
<li><p><strong>Impact:</strong> Reduces server requests and improves repeat visit load times.</p>
</li>
<li><p><strong>Tools</strong>: <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control"><code>Cache-Control</code></a> headers, <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API">Service Workers</a>, <a target="_blank" href="https://redis.io/">Redis</a>.</p>
</li>
</ul>
</li>
<li><p><strong>Content Delivery Network (CDN)</strong></p>
<ul>
<li><p>Serves assets from geographically distributed servers.</p>
</li>
<li><p><strong>Impact:</strong> Improves page load times, reduces latency, and enhances global accessibility.</p>
</li>
<li><p><strong>Tools:</strong> <a target="_blank" href="https://www.cloudflare.com/en-gb/">Cloudflare</a>, <a target="_blank" href="https://aws.amazon.com/cloudfront/">AWS CloudFront</a>, <a target="_blank" href="https://www.fastly.com/">Fastly</a>.</p>
</li>
</ul>
</li>
<li><h4 id="heading-server-side-rendering-strategies-ssr-amp-ssg"><strong>Server-Side Rendering Strategies (SSR &amp; SSG)</strong></h4>
<ul>
<li><p><strong>SSR:</strong> Generates HTML on the server per request, reducing client-side processing and improving initial load times.</p>
</li>
<li><p><strong>SSG:</strong> Pre-renders pages at build time, serving static files instantly for ultra-fast performance.</p>
</li>
</ul>
</li>
</ol>
<p>    <strong>Impact:</strong> Improves page load speeds, enhances SEO, and optimizes content delivery based on the application’s needs.</p>
<p>    <strong>Tools:</strong> <a target="_blank" href="https://nextjs.org/">Next.js</a>, <a target="_blank" href="https://nuxt.com/">Nuxt.js</a>, <a target="_blank" href="https://www.gatsbyjs.com/">Gatsby</a>, <a target="_blank" href="https://gohugo.io/">Hugo</a>.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Optimising web performance is not just a technical necessity, it’s a <strong>business imperative</strong>. By addressing common bottlenecks such as large JavaScript bundles, unoptimised assets, and inefficient network requests, developers can create faster, more efficient websites that keep users engaged.</p>
<p>A well-optimised site not only enhances user experience but also <strong>improves SEO rankings</strong>, r<strong>educes bounce rates</strong>, and ultimately <strong>drives higher conversions and revenue</strong>. In today’s competitive digital landscape, performance optimisation is a key differentiator that no business can afford to ignore.</p>
]]></content:encoded></item><item><title><![CDATA[Let's Talk Code Toolings: Linters & Formatters]]></title><description><![CDATA[Programming errors can be a developer's worst nightmare. Some errors cause minor glitches that annoy users, while others can lead to serious security vulnerabilities or system failures. No matter the type of program you're working on, avoiding these ...]]></description><link>https://blog.mycodingnotebook.com/lets-talk-code-toolings-linters-and-formatters</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/lets-talk-code-toolings-linters-and-formatters</guid><category><![CDATA[General Programming]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Programming Tips]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Wed, 12 Feb 2025 22:16:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1739188675829/d61d9572-768c-4fb8-97b7-82f85f6f95cb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Programming errors can be a developer's worst nightmare. Some errors cause minor glitches that annoy users, while others can lead to serious security vulnerabilities or system failures. No matter the type of program you're working on, avoiding these errors is crucial for delivering reliable and efficient software.</p>
<p>To help developers write cleaner, more maintainable code, two essential tools come into play: <strong>linters</strong> and <strong>formatters</strong>. These tools not only help catch errors early but also ensure that your code is consistent and easy to read, making collaboration across teams smoother and more efficient.</p>
<p>In this article, we’ll explore what linters and formatters are, how they work, and why they are indispensable in modern software development. We’ll also look at some popular tools in each category and those that combine both capabilities.</p>
<h2 id="heading-what-is-a-linter">What is a Linter?</h2>
<p>Before diving into what a linter does, let’s first understand the concept of <strong>linting</strong>. Linting is the process of analysing source code to identify potential errors, bugs, stylistic issues, and problematic patterns.</p>
<p>A <strong>linter</strong> is a tool that automates this process by scanning your code and providing warnings or errors based on predefined rules. As a form of <a target="_blank" href="https://en.wikipedia.org/wiki/Static_program_analysis"><strong>static code analysis</strong></a>, linters inspect code without executing it, helping catch issues early, improve code quality, and enforce best practices.</p>
<h3 id="heading-common-features-of-linters"><strong>Common Features of Linters</strong></h3>
<ul>
<li><p><strong>Error Detection:</strong> Identifies syntax errors, type mismatches, and undefined variables.</p>
</li>
<li><p><strong>Code Quality Checks:</strong> Flags issues like unused variables and overly complex functions.</p>
</li>
<li><p><strong>Best Practices Enforcement:</strong> Encourages coding standards by discouraging bad practices.</p>
</li>
<li><p><strong>Custom Rules:</strong> Allows teams to define and enforce their own coding guidelines.</p>
</li>
</ul>
<h3 id="heading-why-use-a-linter"><strong>Why Use a Linter?</strong></h3>
<ul>
<li><p><strong>Catch Errors Early:</strong> Detects common mistakes before running the code, saving debugging time.</p>
</li>
<li><p><strong>Improve Code Quality:</strong> Encourages cleaner, more efficient, and maintainable code.</p>
</li>
<li><p><strong>Enforce Best Practices:</strong> Many linters come with built-in rules that promote modern coding habits.</p>
</li>
<li><p><strong>Ensure Consistency:</strong> Helps teams follow a unified coding style, making collaboration easier.</p>
</li>
</ul>
<h3 id="heading-how-linters-work"><strong>How Linters Work</strong></h3>
<p>Linters follow a systematic process to analyse and report issues. Here’s a step-by-step breakdown:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739389135453/7c628cdf-241e-423a-88f0-2cfba88beeee.png" alt class="image--center mx-auto" /></p>
<ol>
<li><p><strong>Parsing</strong>:</p>
<ul>
<li><p>The linter reads the source code and parses it into an <strong>Abstract Syntax Tree (AST)</strong>. An AST is a tree representation of the code's structure, which makes it easier to analyse.</p>
</li>
<li><p><strong>Example:</strong> A JavaScript linter like <a target="_blank" href="https://eslint.org/">ESLint</a> uses a JavaScript parser (e.g. <a target="_blank" href="https://eslint.org/blog/2014/12/espree-esprima/">Espree</a>) to generate the AST.</p>
</li>
</ul>
</li>
<li><p><strong>Rule Application</strong>:</p>
<ul>
<li><p>The linter applies a set of predefined or custom rules to the AST. These rules define what constitutes an error, warning, or stylistic issue.</p>
</li>
<li><p><strong>Example:</strong> A rule might check for unused variables, missing semicolons, or inconsistent naming conventions.</p>
</li>
</ul>
</li>
<li><p><strong>Traversal</strong>:</p>
<ul>
<li>The linter traverses the AST, examining each node (e.g. variables, functions, loops) to check for violations of the rules.</li>
</ul>
</li>
<li><p><strong>Reporting</strong>:</p>
<p> When a rule violation is detected, the linter generates a warning or error message. These messages often include:</p>
<ul>
<li><p>The location of the issue (file, line, and column).</p>
</li>
<li><p>A description of the problem.</p>
</li>
<li><p>Suggestions for fixing the issue.</p>
</li>
</ul>
</li>
</ol>
<h2 id="heading-what-are-formatters">What are Formatters?</h2>
<p>While linters focus on code correctness, <strong>formatters</strong> focus on code consistency. Code formatting is the process of structuring your code in a clear and readable way.</p>
<p>A <strong>formatter</strong> is a tool that automatically adjusts your code’s indentation, spacing, line breaks, and alignment according to a predefined style guide.</p>
<h3 id="heading-common-features-of-formatters"><strong>Common Features of Formatters</strong></h3>
<ul>
<li><p><strong>Indentation:</strong> Automatically adjusts indentation for better readability.</p>
</li>
<li><p><strong>Line Length:</strong> Ensures lines don’t exceed a specified length, improving clarity.</p>
</li>
<li><p><strong>Spacing:</strong> Standardises spaces around operators, brackets, and symbols.</p>
</li>
<li><p><strong>Alignment:</strong> Keeps elements like function parameters or variable assignments neatly aligned.</p>
</li>
</ul>
<h3 id="heading-why-use-a-formatter"><strong>Why Use a Formatter?</strong></h3>
<ul>
<li><p><strong>Improved Readability:</strong> Well-structured code is easier to read and understand.</p>
</li>
<li><p><strong>Consistency Across Projects:</strong> Eliminates debates over code style and ensures uniform formatting.</p>
</li>
<li><p><strong>Saves Time:</strong> Automates code styling, so developers can focus on writing logic instead of formatting.</p>
</li>
<li><p><strong>Reduces Merge Conflicts:</strong> Consistent formatting minimises unnecessary code changes in version control.</p>
</li>
</ul>
<h3 id="heading-how-formatters-work"><strong>How Formatters Work</strong></h3>
<p>Formatters follow a similar process to linters but focus on <strong>code style rather than functionality</strong>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739390445509/87c2aa96-cb8a-4159-9670-a3ca88b1a72e.png" alt class="image--center mx-auto" /></p>
<ol>
<li><p><strong>Parsing</strong>:</p>
<ul>
<li>Like linters, formatters parse the source code into an AST or another intermediate representation.</li>
</ul>
</li>
<li><p><strong>Formatting Rules</strong>:</p>
<p> The formatter applies a set of stylistic rules to the code. These rules define:</p>
<ul>
<li><p>Indentation (e.g. spaces vs. tabs).</p>
</li>
<li><p>Line length.</p>
</li>
<li><p>Spacing around operators and brackets.</p>
</li>
<li><p>Placement of braces and parentheses.</p>
</li>
</ul>
</li>
<li><p><strong>Code Transformation</strong>:</p>
<ul>
<li>The formatter rewrites the code according to the rules. This process ensures that the code adheres to a consistent style.</li>
</ul>
</li>
<li><p><strong>Output</strong>:</p>
<ul>
<li>The formatted code is outputted, either overwriting the original file or displaying the changes.</li>
</ul>
</li>
</ol>
<h2 id="heading-linting-vs-formatting-whats-the-difference">Linting vs. Formatting: What’s the Difference?</h2>
<p>While linters and formatters are often used together, they serve different purposes:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>Linters</strong></td><td><strong>Formatters</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Purpose</strong></td><td>Detect errors and enforce rules</td><td>Standardise code style</td></tr>
<tr>
<td><strong>Focus</strong></td><td>Code functionality and quality</td><td>Code appearance and layout</td></tr>
<tr>
<td><strong>Output</strong></td><td>Warnings and errors</td><td>Reformatted code</td></tr>
<tr>
<td><strong>Customisation</strong></td><td>Highly customisable rules</td><td>Limited to stylistic preferences</td></tr>
</tbody>
</table>
</div><p>In short, <strong>linters ensure your code works correctly</strong>, while <strong>formatters ensure it looks clean and consistent</strong>.</p>
<h2 id="heading-popular-linters">Popular Linters</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Linter</strong></td><td><strong>Language(s)</strong></td></tr>
</thead>
<tbody>
<tr>
<td><a target="_blank" href="https://eslint.org/"><strong>ESLint</strong></a></td><td>JavaScript, TypeScript</td></tr>
<tr>
<td><a target="_blank" href="https://stylelint.io/"><strong>Stylelint</strong></a></td><td>CSS, SCSS, Less</td></tr>
<tr>
<td><a target="_blank" href="https://pypi.org/project/pylint/"><strong>Pylint</strong></a></td><td>Python</td></tr>
<tr>
<td><a target="_blank" href="https://jshint.com/about/"><strong>JSHint</strong></a></td><td>JavaScript</td></tr>
<tr>
<td><a target="_blank" href="https://golangci-lint.run/"><strong>Golangci-lint</strong></a></td><td>Go</td></tr>
<tr>
<td><a target="_blank" href="https://github.com/koalaman/shellcheck"><strong>ShellCheck</strong></a></td><td>Bash/Shell Scripts</td></tr>
<tr>
<td><a target="_blank" href="https://pear.php.net/package/PHP_CodeSniffer"><strong>PHP_CodeSniffer</strong></a></td><td>PHP</td></tr>
<tr>
<td><a target="_blank" href="https://github.com/DavidAnson/markdownlint"><strong>MarkdownLint</strong></a></td><td>Markdown</td></tr>
<tr>
<td><a target="_blank" href="https://swiftpackageindex.com/realm/SwiftLint"><strong>SwiftLint</strong></a></td><td>Swift</td></tr>
<tr>
<td><a target="_blank" href="https://github.com/hadolint/hadolint"><strong>Hadolint</strong></a></td><td>Dockerfile</td></tr>
<tr>
<td><a target="_blank" href="https://clang.llvm.org/extra/clang-tidy/"><strong>Clang-Tidy</strong></a></td><td>C, C++</td></tr>
<tr>
<td><a target="_blank" href="https://hexdocs.pm/credo/overview.html"><strong>Credo</strong></a></td><td>Elixir</td></tr>
<tr>
<td><a target="_blank" href="https://checkstyle.sourceforge.io/"><strong>Checkstyle</strong></a></td><td>Java</td></tr>
<tr>
<td><a target="_blank" href="https://htmlhint.com/"><strong>HTMLHint</strong></a></td><td>HTML</td></tr>
<tr>
<td><a target="_blank" href="https://yamllint.readthedocs.io/en/stable/"><strong>YAMLLint</strong></a></td><td>YAML</td></tr>
<tr>
<td><a target="_blank" href="https://sqlfluff.com/"><strong>SQLFluff</strong></a></td><td>SQL</td></tr>
</tbody>
</table>
</div><h2 id="heading-popular-code-formatters">Popular Code Formatters</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Formatter</strong></td><td><strong>Language(s)</strong></td></tr>
</thead>
<tbody>
<tr>
<td><a target="_blank" href="https://prettier.io/"><strong>Prettier</strong></a></td><td>JavaScript, CSS, HTML, JSON, Markdown, etc.</td></tr>
<tr>
<td><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=ms-python.black-formatter"><strong>Black</strong></a></td><td>Python</td></tr>
<tr>
<td><a target="_blank" href="https://pkg.go.dev/cmd/gofmt"><strong>Gofmt</strong></a></td><td>Go (Golang)</td></tr>
<tr>
<td><a target="_blank" href="https://pypi.org/project/autopep8/"><strong>autopep8</strong></a></td><td>Python</td></tr>
<tr>
<td><a target="_blank" href="https://github.com/rust-lang/rustfmt"><strong>rustfmt</strong></a></td><td>Rust</td></tr>
<tr>
<td><a target="_blank" href="https://clang.llvm.org/docs/ClangFormat.html"><strong>clang-format</strong></a></td><td>C, C++, Java, JavaScript, etc.</td></tr>
<tr>
<td><a target="_blank" href="https://webinstall.dev/shfmt/"><strong>shfmt</strong></a></td><td>Bash/Shell Scripts</td></tr>
<tr>
<td><a target="_blank" href="https://scalameta.org/scalafmt/"><strong>scalafmt</strong></a></td><td>Scala</td></tr>
</tbody>
</table>
</div><h2 id="heading-tools-with-both-linting-and-formatting-capabilities"><strong>Tools with Both Linting and Formatting Capabilities</strong></h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Tool</strong></td><td><strong>Language(s)</strong></td></tr>
</thead>
<tbody>
<tr>
<td><a target="_blank" href="https://biomejs.dev/"><strong>Biome</strong></a></td><td>JavaScript, TypeScript, JSON, CSS</td></tr>
<tr>
<td><a target="_blank" href="https://github.com/astral-sh/ruff"><strong>Ruff</strong></a></td><td>Python</td></tr>
<tr>
<td><a target="_blank" href="https://github.com/pinterest/ktlint"><strong>ktlint</strong></a></td><td>Kotlin</td></tr>
<tr>
<td><a target="_blank" href="https://rubocop.org/"><strong>RuboCop</strong></a></td><td>Ruby</td></tr>
</tbody>
</table>
</div><h2 id="heading-in-conclusion">In conclusion,</h2>
<p>Both linters and formatters play a crucial role in maintaining clean, readable, and high-quality code. While linters focus on <strong>error detection and best practices</strong>, formatters ensure <strong>consistent styling</strong>. Using them together can significantly improve your development workflow and help you write better code with minimal effort.</p>
]]></content:encoded></item><item><title><![CDATA[Let's Talk Code Toolings: Preprocessors & Postprocessors]]></title><description><![CDATA[Modern web development relies on various tools to make coding more efficient, maintainable, and optimised. Two key tools that help developers write better code are preprocessors and postprocessors.
While preprocessors allow developers to write code u...]]></description><link>https://blog.mycodingnotebook.com/lets-talk-code-toolings-preprocessors-and-postprocessors</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/lets-talk-code-toolings-preprocessors-and-postprocessors</guid><category><![CDATA[preprocessor]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[Sass]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Sun, 02 Feb 2025 23:11:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738533109799/0c1f3feb-abec-482f-8dc2-de176c1feab9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Modern web development relies on various tools to make coding more efficient, maintainable, and optimised. Two key tools that help developers write better code are <strong>preprocessors</strong> and <strong>postprocessors</strong>.</p>
<p>While preprocessors allow developers to write code using advanced features that are then compiled into standard code, postprocessors modify the output code to improve performance and compatibility.</p>
<p>Let’s first explore <strong>preprocessors</strong> before moving on to <strong>postprocessors</strong>.</p>
<h2 id="heading-what-is-a-preprocessor"><strong>What is a Preprocessor?</strong></h2>
<p>A <strong>preprocessor</strong> is a tool that <strong>enhances a programming language</strong> by introducing extra features like variables, loops, and automation. This enhanced code is then <strong>converted into a standard format</strong> that can be understood by the target environment (such as a browser, compiler, or interpreter) before execution.</p>
<p><strong>Think of it like this:</strong></p>
<p>Writing in shorthand saves time, but before submitting your work, you convert it into full sentences so that everyone can read it. Similarly, a preprocessor allows developers to write code in a more structured and flexible way, then translates it into a format that can be executed.</p>
<p>The term <strong>"preprocessor"</strong> comes from the fact that it processes code <strong>before</strong> <strong>compilation or execution.</strong></p>
<h3 id="heading-benefits-of-a-preprocessor"><strong>Benefits of a Preprocessor</strong></h3>
<ol>
<li><p><strong>Better Code Organisation</strong>:<br /> Preprocessors allow the use of features like variables, nesting, and reusable functions, making code more structured.</p>
</li>
<li><p><strong>Avoid Repetition</strong>:<br /> By defining styles, functions, or logic once and reusing them throughout the project, preprocessors help eliminate redundancy and keep the code DRY (Don't Repeat Yourself).</p>
</li>
<li><p><strong>Write Cleaner Code</strong>:<br /> Preprocessors reduce clutter by enabling concise syntax, resulting in code that is easier to read and understand.</p>
</li>
<li><p><strong>Improve Maintainability</strong>:<br /> With features like global variables and reusable components, updating styles or logic across an entire project becomes quick and efficient, saving time and effort.</p>
</li>
</ol>
<h3 id="heading-examples-of-preprocessors">Examples of Preprocessors</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Language</strong></td><td><strong>Preprocessor Examples</strong></td><td><strong>Features</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>CSS</strong></td><td><a target="_blank" href="https://sass-lang.com/documentation/">SASS</a>, <a target="_blank" href="https://lesscss.org/">LESS</a>, <a target="_blank" href="https://stylus-lang.com/">Stylus</a></td><td>Variables, <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Mixin">mixins</a>, nesting</td></tr>
<tr>
<td><strong>HTML</strong></td><td><a target="_blank" href="https://pugjs.org/api/getting-started.html">Pug</a>, <a target="_blank" href="https://haml.info/">HAML</a></td><td>Templating, loops, conditionals</td></tr>
<tr>
<td><strong>JavaScript</strong></td><td><a target="_blank" href="https://www.typescriptlang.org/">TypeScript</a></td><td>Static typing</td></tr>
</tbody>
</table>
</div><h3 id="heading-practical-example-1-css-preprocessor-sass">Practical Example 1: CSS Preprocessor (SASS)</h3>
<p>Imagine you're writing styles for a website, and you need to use the same <strong>brand color</strong> in multiple places.</p>
<p><strong>Without SASS (Vanilla CSS):</strong></p>
<pre><code class="lang-javascript">.button {
  background-color: #<span class="hljs-number">3498</span>db;
}
.card {
  background-color: #<span class="hljs-number">3498</span>db;
}
</code></pre>
<p>If you want to change the color, you have to update <strong>every occurrence manually</strong>.</p>
<h4 id="heading-with-sass-preprocessed-css"><strong>With SASS</strong> (Preprocessed CSS ):</h4>
<p>With a preprocessor like SASS in <a target="_blank" href="https://sass-lang.com/documentation/syntax/">SCSS</a> syntax, you can define <strong>variables</strong> and reuse them throughout your styles:</p>
<pre><code class="lang-javascript">$primary-color: #<span class="hljs-number">3498</span>db;

.button {
  background-color: $primary-color;
}

.card {
  background-color: $primary-color;
}
</code></pre>
<p>Now, <strong>changing</strong> <code>$primary-color</code> updates all instances automatically.</p>
<h3 id="heading-practical-example-2-html-preprocessor-pughttpspugjsorgapigetting-startedhtml">Practical Example 2: HTML Preprocessor (<a target="_blank" href="https://pugjs.org/api/getting-started.html">Pug</a>)</h3>
<p>Let’s say you're displaying a list of products, each with a <strong>name, price, and description</strong>.</p>
<h4 id="heading-without-pug-vanilla-html"><strong>Without Pug (Vanilla HTML):</strong></h4>
<p>You’d have to write the same HTML structure for every product:</p>
<pre><code class="lang-javascript">&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"product"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Product 1<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Price: GHS10<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Description: A great product!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
&lt;/div&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"product"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Product 2<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Price: GHS20<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>Description: Another great product!<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="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"product"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Product 3<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Price: GHS30<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>Description: Yet another great product!<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>If you want to add or remove products, you have to manually edit the HTML, which is tedious and prone to errors.</p>
<h4 id="heading-with-pug-preprocessed-html"><strong>With Pug (Preprocessed HTML):</strong></h4>
<p>Pug allows you to use <strong>loops</strong> to dynamically generate the product list and <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Mixin"><strong>mixins</strong></a> to define a reusable template for each product.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//- Define a reusable mixin for a product card</span>
mixin productCard(product)
  .product
    h2= product.name
    p Price: GHS#{product.price}
    p Description: #{product.description}

<span class="hljs-comment">//- Define the list of products</span>
- <span class="hljs-keyword">const</span> products = [
-   { <span class="hljs-attr">name</span>: <span class="hljs-string">"Product 1"</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">"A great product!"</span> },
-   { <span class="hljs-attr">name</span>: <span class="hljs-string">"Product 2"</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">20</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">"Another great product!"</span> },
-   { <span class="hljs-attr">name</span>: <span class="hljs-string">"Product 3"</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">30</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">"Yet another great product!"</span> }
- ]

<span class="hljs-comment">//- Loop through the products and render each one using the mixin</span>
each product <span class="hljs-keyword">in</span> products
  +productCard(product)
</code></pre>
<h4 id="heading-how-it-works"><strong>How It Works:</strong></h4>
<ol>
<li><p><strong>Reusability with Mixins</strong>:</p>
<ul>
<li><p>The <code>mixin productCard(product)</code> block defines a reusable template for a product card. It takes a <code>product</code> object as input and generates the HTML for that product.</p>
</li>
<li><p>This eliminates repetition and makes it easy to update the product card structure in one place.</p>
</li>
</ul>
</li>
<li><p><strong>Loops</strong>:</p>
<ul>
<li><p>The <code>each product in products</code> loop iterates over the <code>products</code> array.</p>
</li>
<li><p>For each product, it calls the <code>+productCard(product)</code> mixin to generate the HTML.</p>
</li>
</ul>
</li>
</ol>
<p><strong>Now, let’s move on to postprocessors.</strong></p>
<h2 id="heading-what-is-a-postprocessor"><strong>What is a Postprocessor?</strong></h2>
<p>A postprocessor is a tool that <strong>modifies code after it has been compiled or generated</strong>. Unlike preprocessors, which add extra features before compilation, postprocessors <strong>enhance, optimize, and clean up the final output</strong> to improve performance, compatibility, and readability.</p>
<p><strong>Think of it like this:</strong></p>
<p>After writing an essay, you proofread, correct grammar mistakes, and format it before submission. Similarly, a postprocessor refines code after it has been compiled or generated, ensuring it’s polished and ready for execution.</p>
<p>The term <strong>"postprocessor"</strong> comes from the fact that it processes code <strong>after compilation or generation</strong>, but <strong>before execution</strong>, to ensure the output is optimized and production-ready.</p>
<h3 id="heading-benefits-of-a-postprocessor"><strong>Benefits of a Postprocessor</strong></h3>
<ol>
<li><p><strong>Automatic Enhancements:</strong><br /> Postprocessors can add necessary adjustments without requiring manual changes in the source code.</p>
</li>
<li><p><strong>Cross-Browser Compatibility:</strong><br /> Tools like <a target="_blank" href="https://github.com/postcss/autoprefixer?tab=readme-ov-file#readme"><strong>Autoprefixer</strong></a> add missing <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix"><strong>vendor prefixes</strong></a>, ensuring CSS works across different browsers.</p>
</li>
<li><p><strong>Performance Optimisation:</strong><br /> Postprocessors can <strong>minify CSS</strong>, optimise images, and remove unused code to improve page load times.</p>
</li>
<li><p><strong>Code Consistency:</strong><br /> They help enforce best practices by <strong>reformatting styles, organising rules, and eliminating redundant code</strong>.</p>
</li>
</ol>
<h3 id="heading-examples-of-postprocessors"><strong>Examples of Postprocessors</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Language</strong></td><td><strong>Postprocessor Examples</strong></td><td><strong>Features</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>CSS</strong></td><td><a target="_blank" href="https://github.com/postcss/autoprefixer?tab=readme-ov-file#readme">Autoprefixer</a>, <a target="_blank" href="https://purgecss.com/">PurgeCSS</a>, <a target="_blank" href="https://postcss.org/">PostCSS</a></td><td>Vendor prefixes, minification, dead code removal</td></tr>
<tr>
<td><strong>JavaScript</strong></td><td><a target="_blank" href="https://babeljs.io/">Babel</a> (in some cases), <a target="_blank" href="https://github.com/mishoo/UglifyJS#readme">UglifyJS</a>, <a target="_blank" href="https://terser.org/">Terser</a></td><td>Code minification, optimisation, polyfills</td></tr>
<tr>
<td><strong>HTML</strong></td><td><a target="_blank" href="https://www.npmjs.com/package/html-minifier">HTMLMinifier</a></td><td>Compression, whitespace removal, optimisation</td></tr>
</tbody>
</table>
</div><h3 id="heading-practical-example-1-css-postprocessor-autoprefixerhttpsgithubcompostcssautoprefixertabreadme-ov-filereadme"><strong>Practical Example 1: CSS Postprocessor (</strong><a target="_blank" href="https://github.com/postcss/autoprefixer?tab=readme-ov-file#readme"><strong>Autoprefixer</strong></a><strong>)</strong></h3>
<p>Imagine you're writing CSS for animations, but some browsers require vendor prefixes for compatibility.</p>
<h4 id="heading-without-a-postprocessor-vanilla-css"><strong>Without a Postprocessor (Vanilla CSS):</strong></h4>
<pre><code class="lang-javascript">.button {
  <span class="hljs-attr">display</span>: flex;
  transition: transform <span class="hljs-number">0.3</span>s;
}
</code></pre>
<p><strong>Problem:</strong></p>
<ul>
<li>Older browsers like Internet Explorer and Safari may not support <code>display: flex</code> or <code>transition</code> without prefixes.</li>
</ul>
<h4 id="heading-with-autoprefixer-postprocessed-css"><strong>With Autoprefixer (Postprocessed CSS):</strong></h4>
<pre><code class="lang-javascript">.button {
  <span class="hljs-attr">display</span>: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-transition: transform <span class="hljs-number">0.3</span>s;
  transition: transform <span class="hljs-number">0.3</span>s;
}
</code></pre>
<p><strong>Autoprefixer automatically adds vendor prefixes</strong>, ensuring the CSS works across all major browsers without requiring manual fixes.</p>
<h3 id="heading-practical-example-2-javascript-postprocessor-terserhttpsterserorg-for-minification"><strong>Practical Example 2: JavaScript Postprocessor (</strong><a target="_blank" href="https://terser.org/"><strong>Terser</strong></a> <strong>for Minification)</strong></h3>
<p>When deploying a web app, you want to <strong>reduce file size and improve performance</strong> by minifying JavaScript.</p>
<h4 id="heading-without-a-postprocessor-vanilla-javascript-unminified"><strong>Without a Postprocessor (Vanilla JavaScript - Unminified):</strong></h4>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello, "</span> + name + <span class="hljs-string">"!"</span>);
}
greet(<span class="hljs-string">"World"</span>);
</code></pre>
<p><strong>Problem:</strong> This code takes up unnecessary space, and for large projects, unminified JavaScript slows down load times.</p>
<p><strong>With Terser (Postprocessed Minified JavaScript):</strong></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params">n</span>)</span>{<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello, "</span>+n+<span class="hljs-string">"!"</span>)}greet(<span class="hljs-string">"World"</span>);
</code></pre>
<p><strong>Terser automatically removes spaces, shortens variable names, and optimizes the script</strong>, making it smaller and faster to load.</p>
<h2 id="heading-preprocessors-vs-postprocessors"><strong>Preprocessors vs. Postprocessors</strong></h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>Preprocessor</strong></td><td><strong>Postprocessor</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>When It Runs</strong></td><td>Before compilation or execution</td><td>After compilation but before execution</td></tr>
<tr>
<td><strong>Purpose</strong></td><td>Adds new features and automation</td><td>Optimizes, enhances, and fixes final output</td></tr>
<tr>
<td><strong>Examples</strong></td><td>SASS, TypeScript, Pug</td><td>Autoprefixer, Terser, PurgeCSS</td></tr>
<tr>
<td><strong>What It Affects</strong></td><td>Improves development workflow</td><td>Improves performance and compatibility</td></tr>
</tbody>
</table>
</div><h2 id="heading-in-conclusion">In Conclusion,</h2>
<p>Both <strong>preprocessors</strong> and <strong>postprocessors</strong> enhance web development, but they serve different purposes.</p>
<ul>
<li><p><strong>Preprocessors</strong> improve <strong>developer experience</strong>, making code easier to write, read, and maintain.</p>
</li>
<li><p><strong>Postprocessors</strong> optimise <strong>browser compatibility and performance</strong>, ensuring better execution.</p>
</li>
</ul>
<p>By using both, developers can write <strong>cleaner, more maintainable code</strong> while ensuring that their final output is <strong>optimised and compatible</strong> with all environments.</p>
]]></content:encoded></item><item><title><![CDATA[Let's Talk Code Toolings: Bundlers]]></title><description><![CDATA[A bundler is a tool that takes multiple JavaScript, CSS, and other assets and combines them into a single (or a few) optimised files for efficient loading in a web browser.
What Does This Mean?
Let’s break this down with an example.
Imagine you're bu...]]></description><link>https://blog.mycodingnotebook.com/lets-talk-bundlers</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/lets-talk-bundlers</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[vite]]></category><category><![CDATA[webpack]]></category><category><![CDATA[esbuild]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Thu, 30 Jan 2025 01:43:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738197035932/f7bf645c-73f7-4da0-9975-d8c57869b283.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A <strong>bundler</strong> is a tool that takes multiple <strong>JavaScript, CSS, and other assets</strong> and combines them into a <strong>single (or a few) optimised files</strong> for efficient loading in a web browser.</p>
<h2 id="heading-what-does-this-mean"><strong>What Does This Mean?</strong></h2>
<p>Let’s break this down with an example.</p>
<p>Imagine you're building a <strong>calculator app</strong> in JavaScript. Instead of writing all your code in one massive file, you decide to split it into multiple files to keep things organised.</p>
<h3 id="heading-project-structure"><strong>Project Structure</strong></h3>
<pre><code class="lang-plaintext">calculator-app/
│── index.html
│── style.css
│── index.js
│── math.js
│── utils.js
</code></pre>
<p>Each file handles different parts of the app:</p>
<ul>
<li><p><code>index.html</code> → Serves as the entry point for the browser</p>
</li>
<li><p><code>style.css</code> → Manages the visual styling and layout of the app</p>
</li>
<li><p><code>math.js</code> → Handles calculations</p>
</li>
<li><p><code>utils.js</code> → Provides helper functions</p>
</li>
<li><p><code>index.js</code> → Controls the app’s main logic</p>
</li>
</ul>
<h3 id="heading-logic-breakdown">Logic Breakdown</h3>
<h4 id="heading-1-mathjs-handles-math-operations"><strong>1.</strong> <code>math.js</code> (Handles Math Operations)</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> add = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> a + b;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> subtract = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> a - b;
}
</code></pre>
<h4 id="heading-2-utilsjs-helper-functions"><strong>2.</strong> <code>utils.js</code> (Helper Functions)</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> printResult = <span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Result: <span class="hljs-subst">${result}</span>`</span>);
}
</code></pre>
<h4 id="heading-3-indexjs-main-application-logic"><strong>3.</strong> <code>index.js</code> (Main Application Logic)</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { add, subtract } <span class="hljs-keyword">from</span> <span class="hljs-string">"./math.js"</span>;
<span class="hljs-keyword">import</span> { printResult } <span class="hljs-keyword">from</span> <span class="hljs-string">"./utils.js"</span>;

<span class="hljs-keyword">const</span> result = add(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>);
printResult(result); <span class="hljs-comment">// Output: Result: 8</span>
</code></pre>
<p>Now, this setup <strong>seems fine</strong>, but as your project grows, you'll start facing challenges**.**</p>
<h2 id="heading-problems-without-a-bundler">Problems Without a Bundler</h2>
<ol>
<li><h3 id="heading-compatibility-issues"><strong>Compatibility Issues</strong></h3>
<p> Older browsers (like Internet Explorer) don’t support <strong>ES module imports (</strong><code>import { add } from "./math.js";</code>). You would need to manually include <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Polyfill">polyfills</a> or rewrite your code to work with older JavaScript module systems (like CommonJS).</p>
</li>
<li><h3 id="heading-redundant-code-unused-functions-and-comments"><strong>Redundant Code (Unused Functions and Comments)</strong></h3>
<p> Right now, our <code>subtract()</code> function is never used. But when the browser loads <code>math.js</code>, it still loads that function, wasting resources.</p>
<p> Other unnecessary parts of the code include:</p>
<ul>
<li><p><strong>Comments</strong> that don’t need to be in the final file</p>
</li>
<li><p><strong>Extra white spaces</strong> that make the file larger</p>
</li>
</ul>
</li>
</ol>
<ol start="3">
<li><h3 id="heading-too-many-http-requests">Too Many HTTP Requests</h3>
<p> Each <strong>import statement</strong> in <code>index.js</code> makes a separate request to the server.</p>
<p> Imagine you have <strong>50+ JavaScript files</strong>, your browser has to load each one individually, making <strong>50+ network requests</strong>. This slows down page load speed.</p>
</li>
<li><h3 id="heading-dependency-management-issues"><strong>Dependency Management Issues</strong></h3>
<p> If you use third-party libraries (like <a target="_blank" href="https://lodash.com/"><strong>Lodash</strong></a>), you typically install them via <strong>npm</strong>.</p>
<p> Let’s modify our <strong>calculator app</strong> to use Lodash:</p>
<h4 id="heading-updated-indexjs"><strong>Updated</strong> <code>index.js</code></h4>
<pre><code class="lang-javascript"> <span class="hljs-keyword">import</span> { add, substract} <span class="hljs-keyword">from</span> <span class="hljs-string">"./math.js"</span>;
 <span class="hljs-keyword">import</span> { printResult } <span class="hljs-keyword">from</span> <span class="hljs-string">"./utils.js"</span>;
 <span class="hljs-keyword">import</span> _ <span class="hljs-keyword">from</span> <span class="hljs-string">"lodash"</span>; <span class="hljs-comment">// Import Lodash (third-party library)</span>

 <span class="hljs-keyword">const</span> result = add(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>);
 printResult(result); <span class="hljs-comment">// Output: Result: 8</span>

 <span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">6</span>, <span class="hljs-number">8</span>];
 <span class="hljs-keyword">const</span> sum = _.sum(numbers); <span class="hljs-comment">// Uses Lodash to sum numbers</span>
 printResult(sum); <span class="hljs-comment">// Output: Result: 20</span>
</code></pre>
<p> However, <strong>this will fail in the browser</strong> :</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738191657931/25da393e-054c-41e4-b6b0-7e4ad778140a.png" alt class="image--center mx-auto" /></p>
<p> This occurs because:</p>
<ol>
<li><p><strong>Browsers don’t understand Node.js module resolution</strong>:</p>
<ul>
<li><p>When you use <code>import _ from "lodash"</code>, the browser doesn’t know how to resolve the <code>lodash</code> package from <code>node_modules</code>.</p>
</li>
<li><p>Browsers expect module paths to be relative (e.g., <code>./math.js</code>) or absolute (e.g., <code>/path/to/file.js</code>).</p>
</li>
</ul>
</li>
<li><p><strong>Lodash is installed in</strong> <code>node_modules</code>:</p>
<ul>
<li>The <code>lodash</code> package is installed via npm and resides in the <code>node_modules</code> folder, which browsers cannot access directly.</li>
</ul>
</li>
</ol>
</li>
</ol>
<h2 id="heading-how-does-a-bundler-solves-these-challenges">How Does a Bundler Solves These Challenges?</h2>
<p>A bundler processes your files and resolves the issues we identified earlier—making your app faster, more efficient, and browser-compatible. Let’s break down the process step by step, referencing our <strong>calculator app example</strong>.</p>
<h3 id="heading-step-1-entry-point-discovery">Step 1: Entry Point Discovery</h3>
<p>The first step in bundling is <strong>entry point discovery</strong>. The bundler starts from the <strong>main file</strong> (in this case, <code>index.js</code>) and systematically follows all <strong>import statements</strong> to determine which files and dependencies are required to run the application.</p>
<h4 id="heading-updated-indexjs-1"><strong>Updated</strong> <code>index.js</code></h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { add, substract} <span class="hljs-keyword">from</span> <span class="hljs-string">"./math.js"</span>;
<span class="hljs-keyword">import</span> { printResult } <span class="hljs-keyword">from</span> <span class="hljs-string">"./utils.js"</span>;
<span class="hljs-keyword">import</span> _ <span class="hljs-keyword">from</span> <span class="hljs-string">"lodash"</span>; <span class="hljs-comment">// Import Lodash (third-party library)</span>

<span class="hljs-keyword">const</span> result = add(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>);
printResult(result); <span class="hljs-comment">// Output: Result: 8</span>

<span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">6</span>, <span class="hljs-number">8</span>];
<span class="hljs-keyword">const</span> sum = _.sum(numbers); <span class="hljs-comment">// Uses Lodash to sum numbers</span>
printResult(sum); <span class="hljs-comment">// Output: Result: 20</span>
</code></pre>
<h4 id="heading-dependencies-identified-by-the-bundler"><strong>Dependencies Identified by the Bundler:</strong></h4>
<ol>
<li><p><code>math.js</code> → contains <code>add()</code> and <code>subtract()</code> functions</p>
</li>
<li><p><code>utils.js</code> → contains <code>printResult()</code></p>
</li>
<li><p><code>lodash</code> → an external package providing the <code>_.sum()</code> function</p>
</li>
</ol>
<h3 id="heading-step-2-creating-a-dependency-graph"><strong>Step 2: Creating a Dependency Graph</strong></h3>
<p>After discovering all dependencies in <strong>Step 1</strong>, the bundler constructs a <a target="_blank" href="https://en.wikipedia.org/wiki/Dependency_graph"><strong>dependency graph</strong></a>—a structured representation of how different files are interconnected. This ensures that no required module is left out and helps optimize how the code is bundled.</p>
<p>Given our <code>index.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { add, subtract } <span class="hljs-keyword">from</span> <span class="hljs-string">"./math.js"</span>;
<span class="hljs-keyword">import</span> { printResult } <span class="hljs-keyword">from</span> <span class="hljs-string">"./utils.js"</span>;
<span class="hljs-keyword">import</span> _ <span class="hljs-keyword">from</span> <span class="hljs-string">"lodash"</span>; <span class="hljs-comment">// Import Lodash (third-party library)</span>
</code></pre>
<p>The bundler generates the following <strong>dependency graph</strong>:</p>
<pre><code class="lang-plaintext">index.js  
 ├── math.js  
 │   ├── (add function)  
 │   ├── (subtract function)  
 ├── utils.js  
 │   ├── (printResult function)  
 └── lodash (npm package)  
     ├── (sum function)
</code></pre>
<p>This visualises how <code>index.js</code> relies on <code>math.js</code>, <code>utils.js</code>, and <code>lodash</code>, and how each of these files contribute specific functions.</p>
<h3 id="heading-step-3-code-transformation">Step 3: Code Transformation</h3>
<p>In this step, the bundler takes the modern JavaScript code (or other assets like CSS) and transforms it into a format that’s compatible with all browsers, even older ones. This is especially important because not all browsers support modern JavaScript features like ES modules (<code>import</code>/<code>export</code>).</p>
<h4 id="heading-what-happens-here">What Happens Here?</h4>
<ol>
<li><p><a target="_blank" href="https://theody.hashnode.dev/lets-talk-transpilers"><strong>Transpiling Modern JavaScript</strong></a>:</p>
<ul>
<li><p>The bundler uses tools like <a target="_blank" href="https://babeljs.io/"><strong>Babel</strong></a> or <a target="_blank" href="https://swc.rs/"><strong>SWC</strong></a> to convert modern JavaScript (ES6+) into older versions (ES5) that older browsers can understand.</p>
</li>
<li><p>Arrow functions (<code>() =&gt; {}</code>) are converted into regular functions (<code>function() {}</code>).</p>
</li>
<li><p><code>const</code> and <code>let</code> are converted to <code>var</code>.</p>
</li>
<li><p>Template literals (<code>`Result: ${result}` </code>) are converted to String concatenation (<code>"Result: " + result</code>)</p>
</li>
</ul>
</li>
<li><p><strong>Transforming</strong> <code>import</code> to <code>require</code>:</p>
<ul>
<li><p>Modern <code>import</code> statements are converted into <code>require</code> statements, which are compatible with older environments.</p>
</li>
<li><p>Similarly, <code>export</code> statements are converted into <code>module.exports</code>.</p>
</li>
</ul>
</li>
<li><p><strong>Handling Non-JavaScript Files</strong>:</p>
<ul>
<li>If your project includes CSS, images, or other assets, the bundler will process these too. For example, it might convert SCSS into plain CSS or optimise image sizes.</li>
</ul>
</li>
<li><p><strong>Resolving Module Paths</strong>:</p>
<ul>
<li>The bundler ensures that all <code>import</code> statements are correctly resolved. For example, if you import <code>lodash</code> from <code>node_modules</code>, the bundler will locate the correct file and include it in the bundle.</li>
</ul>
</li>
</ol>
<p><strong>Let’s use the</strong> <code>calculator-app</code> <strong>example to show how the bundler might transform the code.</strong></p>
<h4 id="heading-before-transformation-modern-javascript-with-es-modules">Before Transformation (Modern JavaScript with ES Modules):</h4>
<pre><code class="lang-javascript"><span class="hljs-comment">// math.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> a + b;
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">subtract</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> a - b;
}

<span class="hljs-comment">// utils.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">printResult</span>(<span class="hljs-params">result</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Result: <span class="hljs-subst">${result}</span>`</span>);
}

<span class="hljs-comment">// index.js</span>
<span class="hljs-keyword">import</span> { add } <span class="hljs-keyword">from</span> <span class="hljs-string">"./math.js"</span>;
<span class="hljs-keyword">import</span> { printResult } <span class="hljs-keyword">from</span> <span class="hljs-string">"./utils.js"</span>;
<span class="hljs-keyword">import</span> _ <span class="hljs-keyword">from</span> <span class="hljs-string">"lodash"</span>;

<span class="hljs-keyword">const</span> result = add(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>);
printResult(result);
</code></pre>
<h4 id="heading-after-transformation-commonjs-and-es5">After Transformation (CommonJS and ES5):</h4>
<pre><code class="lang-javascript"><span class="hljs-comment">// Transformed math.js</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> a + b;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">subtract</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> a - b;
}

<span class="hljs-built_in">module</span>.exports = { add, subtract };

<span class="hljs-comment">// Transformed utils.js</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">printResult</span>(<span class="hljs-params">result</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Result: "</span> + result); <span class="hljs-comment">// Template literal transformed</span>
}

<span class="hljs-built_in">module</span>.exports = { printResult };

<span class="hljs-comment">// Transformed index.js</span>
<span class="hljs-keyword">var</span> math = <span class="hljs-built_in">require</span>(<span class="hljs-string">"./math.js"</span>);
<span class="hljs-keyword">var</span> utils = <span class="hljs-built_in">require</span>(<span class="hljs-string">"./utils.js"</span>);
<span class="hljs-keyword">var</span> _ = <span class="hljs-built_in">require</span>(<span class="hljs-string">"lodash"</span>);

<span class="hljs-keyword">var</span> result = math.add(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>); <span class="hljs-comment">// const transformed to var</span>
utils.printResult(result);
</code></pre>
<h3 id="heading-step-4-code-optimisation">Step 4: Code Optimisation</h3>
<p>Once the code is transformed, the bundler optimises it to make it smaller, faster, and more efficient. This step ensures that your app loads quickly and doesn’t waste resources.</p>
<h4 id="heading-what-happens-here-1">What Happens Here?</h4>
<ol>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking"><strong>Tree Shaking</strong></a>:</p>
<p> The bundler removes unused code. For example, since the the <code>subtract</code> function in <code>math.js</code> is never used, it won’t be included in the final bundle. This reduces the file size.</p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Minification"><strong>Minification</strong></a>:</p>
<p> The bundler removes unnecessary characters <strong>like comments, whitespace, and long variable names.</strong> <strong>For example:</strong></p>
<pre><code class="lang-javascript"> <span class="hljs-comment">// Before minification</span>
 <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params">a, b</span>) </span>{
   <span class="hljs-keyword">return</span> a + b;
 }
</code></pre>
<p> <strong>After minification:</strong></p>
<pre><code class="lang-javascript"> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params">a,b</span>)</span>{<span class="hljs-keyword">return</span> a+b}
</code></pre>
</li>
<li><p><strong>Code Splitting</strong>:</p>
<p> Instead of generating <strong>one large file</strong>,, the bundler can split the code into smaller chunks (files) that load only when needed. This improves performance by reducing the initial load time.</p>
</li>
<li><p><strong>Optimising Dependencies</strong>:</p>
<p> In scenarios where third-party libraries like Lodash are used, the bundler ensures only the parts needed are included. For example, since only the <code>sum</code> function from Lodash was used, the bundler will only include that and not the entire library.</p>
</li>
</ol>
<h3 id="heading-step-5-generating-the-final-output">Step 5: Generating the Final Output</h3>
<p>After transforming and optimising the code, the bundler generates the final output—a single (or a few) bundled files that your browser can load efficiently.</p>
<h4 id="heading-what-happens-here-2">What Happens Here?</h4>
<ol>
<li><p><strong>Creating the Bundle</strong>:</p>
<p> The bundler combines all the transformed and optimised code into one or more files. For example, it might create a single <code>bundle.js</code> file that includes your app’s logic, dependencies, and assets.</p>
</li>
<li><p><strong>Generating Source Maps</strong>:</p>
<p> <a target="_blank" href="https://web.dev/articles/source-maps">Source maps</a> are files that help you debug your code in the browser. They map the bundled code back to the original source files, so you can see where errors occurred in your original code.</p>
</li>
<li><p><strong>Outputting Files</strong>:</p>
<p> The bundler saves the final files to a specified directory (e.g., <code>dist/</code> or <code>build/</code>). These files are ready to be deployed to a web server.</p>
</li>
</ol>
<h4 id="heading-example">Example:</h4>
<p>After bundling, your project might look like this:</p>
<pre><code class="lang-plaintext">calculator-app/
│── dist/
│   ├── bundle.js
│   ├── style.css
│   ├── index.html
</code></pre>
<ul>
<li><p><code>bundle.js</code> contains all your JavaScript code, including dependencies like Lodash.</p>
</li>
<li><p><code>style.css</code> contains all your CSS, optimised and minified.</p>
</li>
<li><p><code>index.html</code> is updated to include the bundled files.</p>
</li>
</ul>
<h2 id="heading-popular-bundlers-and-their-use-cases"><strong>Popular Bundlers and Their Use Cases</strong></h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Bundler</strong></td><td><strong>Usage</strong></td></tr>
</thead>
<tbody>
<tr>
<td><a target="_blank" href="https://webpack.js.org/"><strong>Webpack</strong></a></td><td>The most powerful and configurable bundler, widely used in large projects.</td></tr>
<tr>
<td><a target="_blank" href="https://vite.dev/guide/why"><strong>Vite</strong></a></td><td>Lightning-fast bundler optimised for modern frameworks like React and Vue.</td></tr>
<tr>
<td><a target="_blank" href="https://parceljs.org/"><strong>Parcel</strong></a></td><td>Zero-config bundler, great for beginners and fast builds.</td></tr>
<tr>
<td><a target="_blank" href="https://rollupjs.org/"><strong>Rollup</strong></a></td><td>Best for libraries and optimising ES modules.</td></tr>
<tr>
<td><a target="_blank" href="https://esbuild.github.io/"><strong>esbuild</strong></a></td><td>Extremely fast bundler written in Go, used for instant builds.</td></tr>
</tbody>
</table>
</div><h2 id="heading-in-conclusion">In Conclusion,</h2>
<p>A <strong>bundler</strong> is an essential tool for modern web development, transforming how we build and optimise applications. By combining multiple JavaScript, CSS, and asset files into a single (or a few) optimised bundles, it addresses critical challenges like browser compatibility, redundant code, excessive HTTP requests, and dependency management.</p>
]]></content:encoded></item><item><title><![CDATA[Let's Talk Code Toolings: Transpilers]]></title><description><![CDATA[A transpiler (short for "translating compiler") is a tool that converts code from one language or version to another while preserving its core functionality. Unlike traditional compilers, which translate high-level code into low-level machine code, t...]]></description><link>https://blog.mycodingnotebook.com/lets-talk-code-toolings-transpilers</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/lets-talk-code-toolings-transpilers</guid><category><![CDATA[transpiler]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Sun, 26 Jan 2025 08:00:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737852559185/1039986d-fce0-429d-8bfa-73188fbe41a5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A <strong>transpiler</strong> (short for "translating compiler") is a tool that converts code from one language or version to another while preserving its core functionality. Unlike traditional <a target="_blank" href="https://theody.hashnode.dev/lets-talk-compilers">compilers</a>, which translate high-level code into low-level machine code, transpilers transform code between similar programming languages or different versions of the same language without changing the underlying structure.</p>
<p>Transpilers are widely used beyond web development. In mobile development, <a target="_blank" href="https://metrobundler.dev/docs/concepts"><strong>React Native’s Metro Bundler</strong></a> transpiles modern JavaScript and JSX into JavaScript that runs efficiently on mobile devices. In game development, <a target="_blank" href="https://docs.unity3d.com/6000.0/Documentation/Manual/scripting-backends-il2cpp.html"><strong>Unity’s IL2CPP</strong></a> translates C# into C++ to optimise performance. In systems programming, tools like <a target="_blank" href="https://cheerp.io"><strong>Cheerp</strong></a> convert C++ into JavaScript or WebAssembly for running native applications in the browser.</p>
<p>However, in this article, we will focus on <strong>transpilers in web development</strong>, exploring how they enhance JavaScript compatibility, performance, and maintainability.</p>
<h2 id="heading-why-are-transpilers-important"><strong>Why Are Transpilers Important?</strong></h2>
<h3 id="heading-browser-compatibility"><strong>Browser Compatibility</strong></h3>
<p>Modern JavaScript (ES6+) includes features that older browsers don't support. A transpiler can convert new syntax into older JavaScript so that it works everywhere.</p>
<h3 id="heading-developer-productivity"><strong>Developer Productivity</strong></h3>
<p>Developers can write clean, modern code without worrying about browser limitations because transpilers handle compatibility issues automatically.</p>
<h3 id="heading-cross-language-development"><strong>Cross-Language Development</strong></h3>
<p>Some transpilers allow you to write in one language and output another. For example, TypeScript is transpiled into JavaScript.</p>
<h2 id="heading-examples-of-transpilers"><strong>Examples of Transpilers</strong></h2>
<p>Here are some common transpilers in web development and what they do:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Transpiler</strong></td><td><strong>Purpose</strong></td></tr>
</thead>
<tbody>
<tr>
<td><a target="_blank" href="https://babeljs.io/docs">Babel</a></td><td>Converts ES6+ JavaScript to ES5 (JavaScript-based)</td></tr>
<tr>
<td><a target="_blank" href="https://swc.rs">Speedy Web Compiler (SWC)</a></td><td>A Rust-based alternative to Babel, significantly faster</td></tr>
<tr>
<td><a target="_blank" href="https://code.visualstudio.com/docs/typescript/typescript-compiling">TypeScript Compiler (tsc)</a></td><td>Converts TypeScript into JavaScript</td></tr>
<tr>
<td><a target="_blank" href="https://esbuild.github.io">esbuild</a></td><td>A fast JavaScript bundler and transpiler</td></tr>
<tr>
<td><a target="_blank" href="https://svelte.dev/docs/svelte/svelte-compiler">Svelte Compiler</a></td><td>Converts Svelte components into JavaScript</td></tr>
<tr>
<td><a target="_blank" href="https://coffeescript.org/#transpilation">CoffeeScript Compiler</a></td><td>Coverts CoffeeScript into JavaScript</td></tr>
<tr>
<td><a target="_blank" href="https://elmprogramming.com/elm-compiler.html">Elm Compiler</a></td><td>Converts Elm into JavaScript</td></tr>
</tbody>
</table>
</div><h3 id="heading-note"><strong>Note:</strong></h3>
<p>Although some of these tools are called <strong>"compilers"</strong>, they are technically <strong>transpilers</strong> <strong>because they do not generate low-level machine code.</strong> Traditional <a target="_blank" href="https://theody.hashnode.dev/lets-talk-compilers"><strong>compilers</strong></a> optimise code and convert it into machine instructions that the CPU can execute directly. <strong>Transpilers</strong>, on the other hand, rewrite code into a different syntax while preserving its original structure and functionality.</p>
<p>The confusion arises because some transpilers, like the TypeScript compiler, perform additional tasks such as type checking, while others, like the Svelte compiler, apply optimisations. Since these tasks are commonly associated with compilers, the names can sometimes be misleading.</p>
<p>However, the key difference remains: <strong>transpilers do not produce native machine code but instead transform code to improve compatibility, maintainability, or performance.</strong></p>
<h2 id="heading-some-applications-of-transpilers"><strong>Some Applications of Transpilers</strong></h2>
<ol>
<li><h3 id="heading-modern-javascript-es6-to-es5"><strong>Modern JavaScript (ES6+) to ES5</strong></h3>
</li>
</ol>
<p><strong>Before Transpiling (ES6+ Code)</strong><br />Let's say we write JavaScript using arrow functions and template literals:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> sayHello = <span class="hljs-function">(<span class="hljs-params">name</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hello, <span class="hljs-subst">${name}</span>!`</span>);
};

sayHello(<span class="hljs-string">"World"</span>);
</code></pre>
<p>Older browsers don’t support arrow functions (<code>=&gt;</code>) and template literals (<code>`Hello, ${name}!` </code>). To ensure our code runs everywhere, we can use Babel or SWC to transpile it.</p>
<p><strong>After Transpiling (ES5 Code by Babel)</strong><br />Babel converts the modern JavaScript into older syntax:</p>
<pre><code class="lang-javascript"><span class="hljs-meta">"use strict"</span>;

<span class="hljs-keyword">var</span> sayHello = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">name</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello, "</span> + name + <span class="hljs-string">"!"</span>);
};

sayHello(<span class="hljs-string">"World"</span>);
</code></pre>
<p><strong>What Changed?</strong></p>
<ul>
<li><p>The arrow function (<code>=&gt;</code>) was converted into a traditional function (<code>function</code>).</p>
</li>
<li><p>The template literal (<code>`Hello, ${name}!` </code>) was converted into string concatenation (<code>"Hello, " + name + "!"</code>).</p>
</li>
<li><p><code>const</code> was replaced with <code>var</code> since older JavaScript versions don’t support <code>const</code></p>
</li>
<li><p><strong>Babel adds</strong> <code>"use strict"</code> at the top. This is a directive in JavaScript that enforces a stricter set of rules, helping to catch common coding mistakes.</p>
</li>
</ul>
<p><strong>After Transpiling (ES5 Code by SWC)</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> sayHello = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sayHello</span>(<span class="hljs-params">name</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello, "</span> + name + <span class="hljs-string">"!"</span>);
};

sayHello(<span class="hljs-string">"World"</span>);
</code></pre>
<p><strong>What Changed?</strong></p>
<ul>
<li><p>Like Babel, the arrow function (<code>=&gt;</code>) was converted into a traditional function (<code>function</code>).</p>
</li>
<li><p>The template literal (<code>`Hello, ${name}!` </code>) was converted into string concatenation (<code>"Hello, " + name + "!"</code>).</p>
</li>
<li><p><code>const</code> was replaced with <code>var</code></p>
<p>  However, <strong>there are key differences:</strong></p>
</li>
<li><p><strong>SWC does not add</strong> <code>"use strict"</code> by default. Unlike Babel, SWC leaves it out unless explicitly configured.</p>
</li>
<li><p><strong>SWC adds a function name</strong> (<code>sayHello</code>) for better debugging.</p>
</li>
</ul>
<ol start="2">
<li><h3 id="heading-typescript-to-javascript"><strong>TypeScript to JavaScript</strong></h3>
</li>
</ol>
<h4 id="heading-before-transpiling-typescript-code"><strong>Before Transpiling (TypeScript Code)</strong></h4>
<p>TypeScript introduces static types, which are not supported in JavaScript. Here’s an example:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> add = (a: <span class="hljs-built_in">number</span>, b: <span class="hljs-built_in">number</span>): <span class="hljs-function"><span class="hljs-params">number</span> =&gt;</span> a + b;

<span class="hljs-keyword">let</span> result: <span class="hljs-built_in">number</span> = add(<span class="hljs-number">5</span>, <span class="hljs-number">10</span>);
<span class="hljs-built_in">console</span>.log(result);
</code></pre>
<p><strong>TypeScript Features:</strong></p>
<ul>
<li><code>: number</code> specifies that <code>a</code>, <code>b</code>, and <code>result</code> must be numbers.</li>
</ul>
<h4 id="heading-after-transpiling-javascript-code-by-tsc"><strong>After Transpiling (JavaScript Code by</strong> <code>tsc</code><strong>)</strong></h4>
<p>JavaScript doesn't support TypeScript's type annotations, so <code>tsc</code> (TypeScript Compiler) will remove them. The resulting JavaScript code will also depend on the <strong>target</strong> you specify in the configuration (<code>tsconfig.json</code>) file, which determines which version of JavaScript to transpile to.</p>
<h5 id="heading-if-the-target-is-es5">If the target is <strong>ES5</strong>:</h5>
<p>TypeScript will convert any modern features (like arrow functions or <code>let/const</code>) to older JavaScript syntax (like <code>var</code> and regular functions). The result would look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> add = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">a, b</span>) </span>{ <span class="hljs-keyword">return</span> a + b; };

<span class="hljs-keyword">var</span> result = add(<span class="hljs-number">5</span>, <span class="hljs-number">10</span>);
<span class="hljs-built_in">console</span>.log(result);
</code></pre>
<p><strong>What Changed:</strong></p>
<ul>
<li><p>Type annotations (<code>: number</code>) are removed.</p>
</li>
<li><p>Arrow function is converted to a regular function.</p>
</li>
<li><p><code>const</code> and <code>let</code> are converted to <code>var</code>.</p>
</li>
</ul>
<h5 id="heading-if-the-target-is-es6-or-newer">If the target is <strong>ES6 or newer</strong>:</h5>
<p>TypeScript will keep the modern JavaScript features intact. The output would look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> add = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a + b;

<span class="hljs-keyword">let</span> result = add(<span class="hljs-number">5</span>, <span class="hljs-number">10</span>);
<span class="hljs-built_in">console</span>.log(result);
</code></pre>
<p><strong>What Changed:</strong></p>
<ul>
<li>Type annotations are removed, but modern syntax (like <code>const</code>, <code>let</code>, and arrow functions) is kept.</li>
</ul>
<ol start="3">
<li><h3 id="heading-jsx-to-javascript-for-react"><strong>JSX to JavaScript (for React)</strong></h3>
</li>
</ol>
<p>JSX (JavaScript XML) allows you write <strong>HTML-like</strong> syntax directly within your JavaScript code. This approach, often referred to as <a target="_blank" href="https://en.wikipedia.org/wiki/Syntactic_sugar#:~:text=Syntactic%20sugar%20is%20usually%20a,easier%20to%20type%20and%20read."><strong>syntactic sugar</strong></a>, makes it easier to create React elements in a more readable and concise way.</p>
<p>However, while JSX is more intuitive, it isn’t valid JavaScript. Since browsers can't directly understand JSX, it needs to be transpiled into regular JavaScript before it can run. This transformation is usually handled by tools like <strong>Babel</strong>, which is widely used in React applications to make sure JSX code works in the browser.</p>
<h4 id="heading-before-transpiling-jsx-code">Before Transpiling (JSX Code)</h4>
<p>In JSX, you can write HTML-like syntax directly in your JavaScript code. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, World!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>;
};
</code></pre>
<ul>
<li>Here, <code>&lt;h1&gt;Hello, World!&lt;/h1&gt;</code> looks like HTML, but it's actually JSX (a syntax extension for JavaScript).</li>
</ul>
<h4 id="heading-after-transpiling-javascript-output-by-babel">After Transpiling (JavaScript Output by Babel)</h4>
<ul>
<li><p>Babel converts JSX into standard JavaScript, which browsers can understand.</p>
</li>
<li><p>The JSX code is transformed into a call to the <code>React.createElement</code> function.</p>
</li>
<li><p>This function is used by React to create <strong>virtual DOM</strong> elements, which are JavaScript representations of UI components.</p>
</li>
<li><p>These virtual DOM elements are then compared with the actual DOM to determine the most efficient way to update the user interface.</p>
</li>
</ul>
<p>The output after Babel transpiles the JSX will look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> React.createElement(<span class="hljs-string">"h1"</span>, <span class="hljs-literal">null</span>, <span class="hljs-string">"Hello, World!"</span>);
};
</code></pre>
<p><strong>What changed?</strong></p>
<ul>
<li><p>The JSX <code>&lt;h1&gt;Hello, World!&lt;/h1&gt;</code> is converted into a <code>React.createElement</code> call.</p>
</li>
<li><p><code>React.createElement("h1", null, "Hello, World!")</code> is the JavaScript equivalent that creates a virtual DOM representation of the <code>&lt;h1&gt;</code> element.</p>
</li>
</ul>
<ol start="4">
<li><h3 id="heading-svelte-code-to-javascript"><strong>Svelte Code to JavaScript</strong></h3>
</li>
</ol>
<p>Just like Babel in React, the Svelte compiler converts Svelte-specific syntax into JavaScript that browsers can understand.</p>
<h4 id="heading-before-compilation-svelte-code"><strong>Before Compilation (Svelte Code)</strong></h4>
<p>In Svelte, components are written using a combination of <strong>HTML</strong>, <strong>JavaScript</strong>, and <strong>CSS</strong> all in the same file.</p>
<p>Here's an example of a simple Svelte component. This component displays a greeting and a button. When the user clicks the button, the greeting changes:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">let</span> name = <span class="hljs-string">'World'</span>;
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">changeName</span>(<span class="hljs-params"></span>) </span>{
    name = <span class="hljs-string">'Readers'</span>;
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, </span><span class="javascript">{name}</span><span class="xml">!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=</span></span><span class="javascript">{changeName}</span><span class="xml"><span class="hljs-tag">&gt;</span>Change Name<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span></span><span class="css">
  <span class="hljs-selector-tag">h1</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#ff3e00</span>;
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>
</code></pre>
<p><strong>After Compilation (JavaScript Output by Svelte)</strong></p>
<ul>
<li><p>The Svelte compiler takes this <code>.svelte</code> file and converts it into plain JavaScript.</p>
</li>
<li><p>It removes Svelte-specific syntax like <code>{name}</code> and <code>on:click</code>.</p>
</li>
<li><p>The compiled JavaScript directly manipulates the DOM and handles state changes, making the page update efficiently.</p>
</li>
</ul>
<p>The compiled output might look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Function to create the HTML structure for the component</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createFragment</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">let</span> name = <span class="hljs-string">'World'</span>; 
  <span class="hljs-keyword">let</span> h1 = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"h1"</span>);
  <span class="hljs-keyword">let</span> button = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"button"</span>);

  <span class="hljs-comment">// Set the initial content of the &lt;h1&gt; and button</span>
  h1.textContent = <span class="hljs-string">"Hello, "</span> + name + <span class="hljs-string">"!"</span>;
  button.textContent = <span class="hljs-string">"Change Name"</span>;

  <span class="hljs-comment">// Function to update the name when the button is clicked</span>
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">changeName</span>(<span class="hljs-params"></span>) </span>{
    name = <span class="hljs-string">'Svelte'</span>; 
    h1.textContent = <span class="hljs-string">"Hello, "</span> + name + <span class="hljs-string">"!"</span>; 
  }

  <span class="hljs-comment">// Return the element creation and interactions</span>
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">create</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-comment">// Append &lt;h1&gt; and &lt;button&gt; to the page</span>
      <span class="hljs-built_in">document</span>.body.appendChild(h1);
      <span class="hljs-built_in">document</span>.body.appendChild(button);

      <span class="hljs-comment">// Add event listener to button to change the name when clicked</span>
      button.addEventListener(<span class="hljs-string">"click"</span>, changeName);
    },

    <span class="hljs-attr">destroy</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-comment">// Remove the &lt;h1&gt; and &lt;button&gt; elements from the page</span>
      <span class="hljs-built_in">document</span>.body.removeChild(h1);
      <span class="hljs-built_in">document</span>.body.removeChild(button);
    }
  };
}

<span class="hljs-comment">// Create the component and display it on the page</span>
<span class="hljs-keyword">const</span> app = createFragment();
app.create();
</code></pre>
<p><strong>Key Changes After Compilation:</strong></p>
<ul>
<li><p><code>{name}</code> (used for dynamic data binding in Svelte) is replaced with standard JavaScript to directly manipulate the DOM.</p>
</li>
<li><p><code>on:click</code> (the event binding syntax in Svelte) is replaced with a native JavaScript event listener (<code>addEventListener</code>).</p>
</li>
</ul>
<h2 id="heading-in-conclusion">In Conclusion,</h2>
<p>Transpilers are essential in modern software development, helping developers write cleaner, more efficient code that works across different environments. By converting code to be compatible with older browsers or different versions of a language, transpilers save time and reduce compatibility issues. As technology evolves, understanding how transpilers work will help you choose the best tools for your projects, driving innovation and improving efficiency in web, mobile, or game development.</p>
]]></content:encoded></item><item><title><![CDATA[Let's Talk Code Toolings: Compilers]]></title><description><![CDATA[Introduction
In modern software development, creating efficient, optimised code is crucial for building fast, scalable applications. To achieve this, developers rely on a variety of tools that help transform and optimise code before it reaches the br...]]></description><link>https://blog.mycodingnotebook.com/lets-talk-code-toolings-compilers</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/lets-talk-code-toolings-compilers</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[optimization]]></category><category><![CDATA[compiler]]></category><category><![CDATA[Just in time compiler]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Thu, 23 Jan 2025 02:57:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737595049367/d23a3cd7-a28b-42e1-892a-50725d3c496b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<p>In modern software development, creating efficient, optimised code is crucial for building fast, scalable applications. To achieve this, developers rely on a variety of tools that help transform and optimise code before it reaches the browser or server. Among these tools, <strong>compilers</strong> play a vital role in improving performance by converting high-level code into a form that a computer can understand and execute.</p>
<p>In this article, we’ll dive deep into compilers—exploring how they work, why they’re significant in development, and how they transform source code into machine-readable instructions that run faster and more efficiently.</p>
<p><strong>Let’s dive in!</strong></p>
<h2 id="heading-what-is-a-compiler"><strong>What is a Compiler?</strong></h2>
<p>A <strong>compiler</strong> is a tool that transforms high-level programming code (like JavaScript, TypeScript, or C++) into a lower-level language that a computer can understand and execute. This lower-level language can either be <a target="_blank" href="https://en.wikipedia.org/wiki/Machine_code"><strong>machine code</strong></a> (which the computer's CPU directly executes) or <a target="_blank" href="https://en.wikipedia.org/wiki/Bytecode"><strong>bytecode</strong></a> (which is executed by a <a target="_blank" href="https://en.wikipedia.org/wiki/Virtual_machine">virtual machine</a>).</p>
<p><strong>Think of it like this:<br />Your Code</strong> (Source Code) → <strong>Compiler</strong> (Processing &amp; Optimisation) → <strong>Machine Code</strong> (Executable Instructions)</p>
<p>This entire process helps improve performance by making the code run faster and more efficiently on a computer.</p>
<h2 id="heading-importance-of-compilers"><strong>Importance of Compilers</strong></h2>
<ol>
<li><h3 id="heading-improving-performance"><strong>Improving Performance</strong></h3>
<p> By optimising the code before execution (through processes like removing redundant calculations), compilers ensure that the program runs efficiently. This reduces lag and increases speed.</p>
</li>
<li><h3 id="heading-cross-platform-compatibility">Cross-Platform Compatibility</h3>
<p> Compilers enable software written in one programming language to be executed on different platforms (Windows, macOS, Linux). By converting code into machine code or bytecode specific to a platform, developers can ensure their applications work across various environments.</p>
</li>
<li><h3 id="heading-enabling-new-technologies">Enabling New Technologies</h3>
<p> Compilers make it possible to run languages like WebAssembly in the browser. WebAssembly allows high-performance execution of code written in languages like C, C++, and Rust, expanding the types of applications that can run directly in a web browser.</p>
</li>
</ol>
<h2 id="heading-examples-of-compilers"><strong>Examples of Compilers</strong></h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Compiler</strong></td><td><strong>Language Input</strong></td><td><strong>Compilation Output</strong></td></tr>
</thead>
<tbody>
<tr>
<td><a target="_blank" href="https://v8.dev/docs"><strong>V8 Engine</strong></a></td><td>JavaScript</td><td>Machine Code</td></tr>
<tr>
<td><a target="_blank" href="https://emscripten.org/docs/introducing_emscripten/about_emscripten.html"><strong>Emscripten</strong></a></td><td>C++</td><td><a target="_blank" href="https://developer.mozilla.org/en-US/docs/WebAssembly">WebAssembly (Wasm)</a></td></tr>
<tr>
<td><a target="_blank" href="https://dart.dev/overview#native-platform"><strong>Dart Compiler</strong></a></td><td>Dart</td><td>Machine Code, JavaScript, Wasm</td></tr>
<tr>
<td><a target="_blank" href="https://rustc-dev-guide.rust-lang.org/overview.html"><strong>Rust Compiler</strong></a></td><td>Rust</td><td>WebAssembly (Wasm)</td></tr>
<tr>
<td><a target="_blank" href="https://www.assemblyscript.org/compiler.html#compiler-options"><strong>AssemblyScript Compiler</strong></a></td><td>AssemblyScript</td><td>WebAssembly (Wasm)</td></tr>
</tbody>
</table>
</div><h2 id="heading-how-do-compilers-work"><strong>How Do Compilers Work?</strong></h2>
<p>Compilers typically go through the following stages:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739397907012/1659d021-1380-48be-9f81-1b822c2f8ea0.png" alt class="image--center mx-auto" /></p>
<ol>
<li><h3 id="heading-lexical-analysis"><strong>Lexical Analysis</strong></h3>
<p> <strong>What Happens Here?</strong></p>
<p> The compiler breaks the source code into small, meaningful pieces called <strong>tokens</strong>.</p>
<p> <strong>Output Example:</strong></p>
<p> For the code <code>let a = 5;</code>, the tokens are:</p>
<ul>
<li><p><code>let</code> (keyword)</p>
</li>
<li><p><code>a</code> (identifier)</p>
</li>
<li><p><code>=</code> (operator)</p>
</li>
<li><p><code>5</code> (number)</p>
</li>
<li><p><code>;</code> (symbol)</p>
</li>
</ul>
</li>
</ol>
<p>    <strong>Why is it important?</strong></p>
<p>    Tokens simplify the code into manageable pieces for further processing.</p>
<ol start="2">
<li><h3 id="heading-syntax-analysis-parsing"><strong>Syntax Analysis (Parsing)</strong></h3>
<p> <strong>What Happens Here?</strong></p>
<p> The compiler checks if the code follows the correct syntax of the programming language and builds an <strong>Abstract Syntax Tree (AST)</strong>.</p>
<p> <strong>Output Example:</strong></p>
<p> For the code <code>let a = 5;</code>, the AST might look like this:</p>
<pre><code class="lang-json"> {
   <span class="hljs-attr">"type"</span>: <span class="hljs-string">"VariableDeclaration"</span>,
   <span class="hljs-attr">"declarations"</span>: [
     {
       <span class="hljs-attr">"type"</span>: <span class="hljs-string">"VariableDeclarator"</span>,
       <span class="hljs-attr">"id"</span>: { <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Identifier"</span>, <span class="hljs-attr">"name"</span>: <span class="hljs-string">"a"</span> },
       <span class="hljs-attr">"init"</span>: { <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Literal"</span>, <span class="hljs-attr">"value"</span>: <span class="hljs-number">5</span> }
     }
   ],
   <span class="hljs-attr">"kind"</span>: <span class="hljs-string">"let"</span>
 }
</code></pre>
<p> <strong>Why is it important?</strong></p>
<p> The AST is a tree representation of the code's structure, making it easier to analyse and manipulate.</p>
</li>
<li><h3 id="heading-semantic-analysis"><strong>Semantic Analysis</strong></h3>
<p> <strong>What Happens Here?</strong></p>
<p> The compiler checks if the code makes <strong>logical sense</strong> (e.g., no undeclared variables or type mismatches).</p>
<p> <strong>Output Example:</strong></p>
<p> For the code <code>let b = a + "hello";</code>, the output is:</p>
<ul>
<li><p>An error (e.g., "Cannot add a number and a string") if the code is invalid.</p>
</li>
<li><p>A validated AST if the code is logically correct.</p>
</li>
</ul>
</li>
</ol>
<p>    <strong>Why is it important?</strong></p>
<p>    Ensures the code is not only syntactically correct but also logically sound.</p>
<ol start="4">
<li><h3 id="heading-optimisation"><strong>Optimisation</strong></h3>
<p> <strong>What Happens Here?</strong></p>
<p> The compiler improves the code’s performance by eliminating inefficiencies (e.g., removing redundant calculations).</p>
<p> <strong>Output Example:</strong></p>
<p> For the code <code>let a = 5 + 3;</code>, the optimised output might be:</p>
<pre><code class="lang-basic"> MOV R1, <span class="hljs-number">5</span>      ; <span class="hljs-keyword">Load</span> <span class="hljs-number">5</span> into register R1
 MOV R2, <span class="hljs-number">10</span>     ; <span class="hljs-keyword">Load</span> <span class="hljs-number">10</span> into register R2
 ADD R1, R2     ; Add R1 <span class="hljs-keyword">and</span> R2, store result in R1
</code></pre>
<p> <strong>Why is it important?</strong></p>
<p> Optimised code runs faster and uses fewer resources.</p>
</li>
<li><h3 id="heading-code-generation"><strong>Code Generation</strong></h3>
<p> <strong>What Happens Here?</strong></p>
<p> The compiler converts the optimised code into <strong>machine-readable instructions</strong> (machine code).</p>
<p> <strong>Output Example:</strong></p>
<p> For the code <code>let b = a + 10;</code>, the machine code might look like this:</p>
<pre><code class="lang-basic"> MOV R1, <span class="hljs-number">5</span>      ; <span class="hljs-keyword">Load</span> <span class="hljs-number">5</span> into register R1
 MOV R2, <span class="hljs-number">10</span>     ; <span class="hljs-keyword">Load</span> <span class="hljs-number">10</span> into register R2
 ADD R1, R2     ; Add R1 <span class="hljs-keyword">and</span> R2, store result in R1
</code></pre>
<p> <strong>Why is it important?</strong></p>
<p> Produces the final executable program that the computer can run.</p>
</li>
</ol>
<h2 id="heading-compilation-strategies"><strong>Compilation Strategies</strong></h2>
<p>There are two main strategies that is used to translate a program written in a high-level language into a format that a computer can understand. These are;</p>
<ol>
<li><p><strong>Just-In-Time (JIT) Compilation</strong></p>
</li>
<li><p><strong>Ahead-Of-Time (AOT) Compilation</strong></p>
</li>
</ol>
<p>Before we explore these strategies in detail, let’s define some key terms that will help us understand how they work.</p>
<ul>
<li><p><strong>Machine Code:</strong> The <strong>binary instructions</strong> that a computer’s <strong>Central Processing Unit (CPU)</strong> directly understands and executes.</p>
</li>
<li><p><strong>Bytecode:</strong> A lower-level code representation that is not directly executed by a CPU but runs inside a virtual machine (e.g. Java bytecode runs inside the JVM, WebAssembly bytecode runs inside browsers).</p>
</li>
<li><p><strong>Execution:</strong> The fundamental process of <strong>running a program</strong> on a computer. Once the computer understands the code (through compilation or interpretation), it begins executing instructions to perform the program’s tasks.</p>
</li>
<li><p><strong>Runtime</strong>: The <strong>period during which a program is actively running.</strong> It is the phase when the compiled or interpreted code is being executed by the system.</p>
</li>
<li><p><strong>Compilation:</strong> A method of preparing code for execution by <strong>translating high-level code</strong> (e.g. JavaScript or Dart) into a <strong>lower-level language</strong> (such as machine code or bytecode) that the computer can efficiently execute.</p>
</li>
<li><p><strong>Interpretation:</strong> An alternative to compilation, where the code is <strong>translated and executed line-by-line</strong> instead of converting it into machine code beforehand.</p>
</li>
<li><p><strong>Optimisation:</strong> The process of improving code performance, such as making it run faster or use less memory.</p>
</li>
</ul>
<p>With these terms in mind, let’s explore <strong>JIT and AOT compilation</strong> and how they impact web development.</p>
<h3 id="heading-just-in-time-jit-compilation">Just-In-Time (JIT) Compilation</h3>
<p>Just-In-Time (JIT) compilation happens <strong>while the program is running</strong>. Instead of compiling the entire code before execution, a JIT compiler <strong>translates code into machine code on demand</strong>, only when it's needed.</p>
<p>At first glance, JIT compilation might seem similar to <strong>interpretation</strong>, but they work differently. Let’s explore how interpretation functions to better understand the differences.</p>
<h3 id="heading-how-interpretation-works"><strong>How Interpretation Works</strong></h3>
<ol>
<li><p>The program <strong>starts running immediately</strong> (there’s no compilation step).</p>
</li>
<li><p>The interpreter <strong>reads one line (or statement) of code</strong> at a time.</p>
</li>
<li><p>It <strong>translates and executes that line on the fly</strong>.</p>
</li>
<li><p>This process <strong>repeats for every line of the program</strong>.</p>
</li>
</ol>
<p>Since no compiled machine code is stored, the interpreter <strong>repeats this process every time the program runs</strong>, leading to slower execution speeds.</p>
<h3 id="heading-how-jit-compilation-works"><strong>How JIT Compilation Works</strong></h3>
<ol>
<li><p>The program <strong>starts running</strong>, just like with an interpreter.</p>
</li>
<li><p>The JIT compiler <strong>analyses which parts of the code are used most frequently</strong>.</p>
</li>
<li><p>These frequently used parts are <strong>compiled into machine code and stored</strong>.</p>
</li>
<li><p>The next time those parts are needed, the <strong>compiled version is executed instead of interpreting them again</strong>.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737592059594/19aad4e7-2bb8-4c44-85d4-9c8b1bd74472.png" alt class="image--center mx-auto" /></p>
<p>This optimisation allows JIT compilers to reuse machine code, making execution much <strong>faster than pure interpretation</strong>.</p>
<p>As a result, JIT compilers are well-suited for <strong>dynamic applications</strong> that require real-time user interactions or handle constantly changing data, such as <strong>web applications</strong>, <strong>games</strong>, and <strong>real-time data processing systems</strong>. By compiling frequently used code during runtime, JIT allows applications to <strong>adapt to their execution patterns</strong>, enhancing performance over time and providing <strong>faster, more responsive user experiences</strong>.</p>
<h3 id="heading-application-of-jit-compilation-javascripts-v8-enginehttpsv8devdocs"><strong>Application of JIT Compilation:</strong> <a target="_blank" href="https://v8.dev/docs"><strong>JavaScript’s V8 Engine</strong></a></h3>
<p>JavaScript was originally designed as an <strong>interpreted language</strong>, meaning its code was executed <strong>line by line</strong> without prior compilation. However, modern browsers (like <strong>Google Chrome</strong>) and runtimes (like <strong>Node.js</strong>) use <strong>JIT compilation</strong> to significantly improve performance. This is made possible by <strong>Google’s V8 engine</strong>, which powers JavaScript execution.</p>
<p><strong>How JIT Works in the V8 Engine</strong></p>
<ol>
<li><p><strong>Initial Execution</strong>: The V8 engine starts by <strong>interpreting</strong> JavaScript code line by line.</p>
</li>
<li><p><strong>Hot Code Detection</strong>: If a function is executed <strong>multiple times</strong>, V8 <strong>identifies it as frequently used (hot code)</strong>.</p>
</li>
<li><p><strong>Optimisation &amp; Caching</strong>: The JIT compiler <strong>compiles the function into optimised machine code</strong> and <strong>stores it for future executions</strong>. This eliminates the need for repeated interpretation.</p>
</li>
<li><p><strong>Further Optimisations</strong>: Over time, V8 <strong>continuously refines and optimises</strong> frequently used code, making JavaScript execution even more efficient.</p>
</li>
</ol>
<p><strong>Example: JIT Compilation in Action</strong></p>
<p>Let’s look at a simple JavaScript function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> a + b;
}

<span class="hljs-built_in">console</span>.log(add(<span class="hljs-number">8</span>, <span class="hljs-number">10</span>)); <span class="hljs-comment">// Outputs: 18</span>
</code></pre>
<p><strong>What Happens Behind the Scenes?</strong></p>
<ol>
<li><p><strong>First Run</strong>: V8 <strong>interprets</strong> the <code>add()</code> function and executes it.</p>
</li>
<li><p><strong>Repeated Execution</strong>: If <code>add()</code> is called multiple times, V8 detects it as <strong>hot code</strong>.</p>
</li>
<li><p><strong>JIT Compilation</strong>: V8 <strong>compiles</strong> <code>add()</code> into optimised machine code and stores it in memory.</p>
</li>
<li><p><strong>Subsequent Executions</strong>: The next time <code>add()</code> is called, V8 <strong>runs the compiled version directly</strong>, skipping interpretation.</p>
</li>
</ol>
<p>This approach makes JavaScript <strong>much faster</strong> than traditional interpreted languages.</p>
<h3 id="heading-ahead-of-time-aot-compilation"><strong>Ahead-Of-Time (AOT) Compilation</strong></h3>
<p>AOT compilation happens <strong>before runtime</strong>, meaning the code is fully compiled into machine code <strong>before the program starts running</strong>. This results in faster execution because the program doesn’t need to compile anything while running.</p>
<p><strong>How AOT Compilation Works</strong></p>
<ol>
<li><p>The entire program is <strong>compiled before execution</strong>, producing an optimised binary file.</p>
</li>
<li><p>The compiled file is then <strong>executed directly</strong> without additional compilation steps.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737592079669/ce22ad2a-b7a7-4819-b3c8-5e0753103317.png" alt class="image--center mx-auto" /></p>
<p>This approach makes AOT perfect for applications that need <strong>fast and predictable performance</strong>, such as <strong>mobile apps</strong>, <strong>production web frameworks</strong>, and environments where <strong>startup speed</strong> is critical. By <strong>pre-compiling code ahead of time</strong>, AOT reduces runtime work, making it especially useful for apps with <strong>stable, well-defined processes</strong> that don’t require frequent changes while running.</p>
<h3 id="heading-application-of-aot-compilation-angular-aot-compilerhttpsangulardevtoolscliaot-compiler"><strong>Application of AOT Compilation:</strong> <a target="_blank" href="https://angular.dev/tools/cli/aot-compiler"><strong>Angular AOT Compiler</strong></a></h3>
<p>Angular uses <strong>Ahead-of-Time (AOT) compilation</strong> to improve web app performance by <strong>compiling templates and TypeScript before deployment</strong>. Instead of letting the browser compile templates at runtime, Angular does this work <strong>during the build phase</strong>, ensuring the app loads faster when a user accesses it.</p>
<h4 id="heading-how-angular-aot-compilation-works"><strong>How Angular AOT Compilation Works</strong></h4>
<ol>
<li><p><strong>Build Phase (Before Deployment):</strong></p>
<ul>
<li><p>When you run <code>ng build --aot</code>, Angular compiles the <strong>HTML templates and TypeScript</strong> into optimised JavaScript.</p>
</li>
<li><p>This means the browser <strong>receives only precompiled JavaScript</strong>, not templates or TypeScript.</p>
</li>
</ul>
</li>
<li><p><strong>Production Deployment:</strong></p>
<ul>
<li>Since templates are already compiled, the browser <strong>doesn’t need to process them at runtime</strong>, leading to faster execution.</li>
</ul>
</li>
</ol>
<p><strong>Example:</strong> Angular Component Before AOT Compilation</p>
<pre><code class="lang-javascript">@Component({
  <span class="hljs-attr">selector</span>: <span class="hljs-string">'app-hello'</span>,
  <span class="hljs-attr">template</span>: <span class="hljs-string">`&lt;h1&gt;Hello, {{name}}!&lt;/h1&gt;`</span>
})
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HelloComponent</span> </span>{
  name = <span class="hljs-string">"World"</span>;
}
</code></pre>
<p><strong>What Happens in AOT?</strong></p>
<ol>
<li><p><strong>Build Time Compilation (Before Deployment)</strong></p>
<ul>
<li>Angular compiles this <strong>before it reaches the browser</strong>, replacing <code>{{name}}</code> with a <strong>direct JavaScript expression</strong>.</li>
</ul>
</li>
<li><p><strong>Optimised Output</strong></p>
<ul>
<li>Instead of shipping templates and compiling them in the browser, Angular generates <strong>efficient JavaScript code</strong> in advance.</li>
</ul>
</li>
<li><p><strong>Faster Execution in the Browser</strong></p>
<ul>
<li>Since templates are precompiled, the browser <strong>skips extra processing</strong> and directly runs the optimised JavaScript.</li>
</ul>
</li>
</ol>
<h2 id="heading-jit-vs-aot-key-differences"><strong>JIT vs AOT: Key Differences</strong></h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>JIT Compilation</strong></td><td><strong>AOT Compilation</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Compilation Time</strong></td><td>Happens <strong>at runtime</strong></td><td>Happens <strong>before execution</strong></td></tr>
<tr>
<td><strong>Performance</strong></td><td>Starts slower but optimises over time</td><td>Faster startup, optimised beforehand</td></tr>
<tr>
<td><strong>Use Cases</strong></td><td>Dynamic apps, browsers, JavaScript</td><td>Mobile apps, WebAssembly, production frameworks</td></tr>
<tr>
<td><strong>Examples</strong></td><td>V8 (JavaScript), WebAssembly JIT</td><td>Angular, Flutter (Dart), Rust to WebAssembly</td></tr>
</tbody>
</table>
</div><h2 id="heading-in-conclusion"><strong>In Conclusion,</strong></h2>
<p>Compilers are essential tools that convert high-level code into machine-readable instructions, enhancing performance and ensuring efficient execution.</p>
<p>In this article, we explored two primary compilation strategies: <strong>Just-In-Time (JIT)</strong> and <strong>Ahead-Of-Time (AOT)</strong>. <strong>JIT</strong> compiles code during runtime, optimising performance for dynamic applications, while <strong>AOT</strong> compiles code ahead of time, leading to faster startup times and more efficient execution for performance-critical apps.</p>
<p>By understanding these strategies, developers can optimise their code for faster, more scalable software. Choosing the right compilation approach can significantly boost your application's speed and efficiency.</p>
]]></content:encoded></item><item><title><![CDATA[SQL vs NoSQL Databases — Part 2]]></title><description><![CDATA[In my previous article, we explored databases, which are organized collections of data that are structured to enable efficient storage, retrieval, and manipulation of information. We specifically dived into SQL databases, also known as relational dat...]]></description><link>https://blog.mycodingnotebook.com/sql-vs-nosql-databases-part-2</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/sql-vs-nosql-databases-part-2</guid><category><![CDATA[Databases]]></category><category><![CDATA[NoSQL]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Sat, 09 Dec 2023 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738081017310/c9e41e6a-9566-480b-93f4-6036061f18d9.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my previous article, we explored databases, which are organized collections of data that are structured to enable efficient storage, retrieval, and manipulation of information. We specifically dived into SQL databases, also known as relational databases, uncovering their characteristics, functionalities, pros and cons.</p>
<p>Continuing our exploration, this article will spotlight NoSQL databases. We’ll delve into their unique features, purposes, and applications. If you missed the earlier article, you can catch up on it <a target="_blank" href="https://theody.hashnode.dev/sql-vs-nosql-databases-part-1"><strong>here</strong></a>.</p>
<p><strong>Now, let’s dive into the world of NoSQL databases.</strong></p>
<h2 id="heading-what-are-nosql-databases"><strong>What are NoSQL Databases?</strong></h2>
<p>NoSQL databases, which stands for <strong>“Not Only SQL”</strong> databases, are a diverse set of database systems designed for flexible, high-performance, and scalable data storage and retrieval. They depart from the traditional relational model of SQL databases, offering different data models and features to cater to specific use cases and scalability requirements.</p>
<p>These NoSQL databases can be categorized into <strong>four main groups</strong>, each offering unique structures and capabilities to address a wide range of data storage and retrieval necessities.</p>
<p><strong>Let’s delve into these categories to understand their distinct offerings.</strong></p>
<p><img src="https://miro.medium.com/v2/resize:fit:1168/1*p5fl0Z5tHQuyyI4SktjfOw.jpeg" alt /></p>
<p><a target="_blank" href="https://media.geeksforgeeks.org/wp-content/uploads/20220405112418/NoSQLDatabases.jpg">https://media.geeksforgeeks.org/wp-content/uploads/20220405112418/NoSQLDatabases.jpg</a></p>
<h3 id="heading-1-key-value-stores"><strong>1. Key-Value Stores</strong></h3>
<p>These are the simplest NoSQL type, where data is stored as a collection of <strong>key-value pairs.</strong> Each data entry is associated with a unique key, which is used to retrieve the corresponding value. This structure resembles a an associative array(dictionary, map or hash) where data is accessed using keys, enabling efficient and quick retrieval.</p>
<p><strong>Characteristics:</strong></p>
<ul>
<li><p><strong>Simplicity:</strong> They are the simplest form of NoSQL databases, offering basic functionalities of storing and retrieving data based on unique keys.</p>
</li>
<li><p><strong>Flexibility:</strong> Key-value stores can handle various types of data, such as strings, numbers, binary data, or more complex structures like JSON objects.</p>
</li>
<li><p><strong>Scalability:</strong> They are highly scalable, as they distribute data across nodes or servers, allowing horizontal scaling by adding more nodes to the cluster.</p>
</li>
<li><p><strong>Performance:</strong> Retrieving data by key is fast, making them suitable for use cases requiring high-speed data access.</p>
</li>
</ul>
<p><strong>Use Cases:</strong></p>
<ul>
<li><p>Caching</p>
</li>
<li><p>Session storage</p>
</li>
<li><p>Storing user preferences.</p>
</li>
</ul>
<p><strong>Examples:</strong> Redis, DynamoDB</p>
<h3 id="heading-2-document-stores"><strong>2. Document Stores</strong></h3>
<p>Document stores are a type of NoSQL database that store and retrieve data in the form of documents. These documents are self-contained units of data, typically stored in formats like JSON (JavaScript Object Notation), BSON (Binary JSON), XML(eXtensible Markup Language), or others. Each document within the database can have its own structure, allowing for flexibility and variation in the data schema.</p>
<p><strong>Characteristics:</strong></p>
<ul>
<li><p><strong>Schema Flexibility:</strong> Documents within the database can have varying structures, allowing for a flexible schema. This flexibility accommodates changes and additions to data without requiring a predefined schema for the entire database.</p>
</li>
<li><p><strong>Documents as Units:</strong> Each document stores all related data together, resembling a record or an object. This structure simplifies retrieval and manipulation of related information, reducing the need for complex joins.</p>
</li>
<li><p><strong>Scalability:</strong> They are designed to scale horizontally, distributing data across multiple nodes or servers, offering improved performance and capacity as data grows.</p>
</li>
<li><p><strong>Rich Querying:</strong> Document stores often support rich querying capabilities, allowing queries on document contents, enabling more complex and diverse retrieval options.</p>
</li>
</ul>
<p><strong>Use Cases:</strong></p>
<ul>
<li><p>Content management systems</p>
</li>
<li><p>E-commerce applications</p>
</li>
<li><p>Real-time analytics</p>
</li>
</ul>
<p><strong>Examples:</strong> MongoDB, Couchbase</p>
<h3 id="heading-3-column-family-stores-wide-column-stores"><strong>3. Column-Family Stores (Wide-Column Stores)</strong></h3>
<p>These organize data into columns instead of rows, allowing efficient access and aggregation by columns. Data is stored in column families which are containers for rows and each row can have varying columns. These databases excel in queries retrieving specific columns or aggregating data across columns.</p>
<p><strong>Characteristics:</strong></p>
<ul>
<li><p><strong>Column-Oriented Storage:</strong> Data is stored in columns rather than rows, allowing for efficient retrieval and aggregation of specific columns.</p>
</li>
<li><p><strong>Schema Flexibility:</strong> While column-family stores have a predefined column family structure, each row can have different columns, enabling flexibility within the data model.</p>
</li>
<li><p><strong>Scalability:</strong> These databases are designed for horizontal scalability, making them suitable for handling large volumes of data by distributing it across multiple nodes or servers.</p>
</li>
<li><p><strong>Fast Querying for Specific Columns:</strong> They excel in scenarios where queries involve retrieving or aggregating specific columns across a vast dataset.</p>
</li>
</ul>
<p><strong>Use Cases:</strong></p>
<ul>
<li><p>Big data analytics</p>
</li>
<li><p>Time-series data</p>
</li>
<li><p>Monitoring systems</p>
</li>
</ul>
<p><strong>Examples:</strong> Apache Cassandra, HBase.</p>
<h3 id="heading-4-graph-databases"><strong>4. Graph Databases</strong></h3>
<p>Graph databases are a type of NoSQL database that use graph structures to represent and store data. They are designed to handle complex relationships between entities, making them particularly useful for scenarios where relationships and connections between different data points are crucial.</p>
<p><strong>Characteristics:</strong></p>
<ul>
<li><p><strong>Graph Structure:</strong> Data is represented as nodes (entities) and edges (relationships) in a graph-like structure. Nodes store information, and edges define relationships between nodes, allowing for rich, interconnected data representations.</p>
</li>
<li><p><strong>Relationship Emphasis:</strong> Graph databases excel in managing relationships between entities. They store not only the data but also the connections between data points, making traversal of relationships efficient.</p>
</li>
<li><p><strong>Flexible Schema:</strong> They typically have a flexible schema, allowing for easy addition of new node types, properties, or relationships without a predefined structure.</p>
</li>
<li><p><strong>Querying and Traversal:</strong> Graph databases use specialized query languages (like Cypher for Neo4j) that allow for traversing and querying the graph structure efficiently to uncover patterns and relationships in the data.</p>
</li>
</ul>
<p><strong>Use Cases:</strong></p>
<ul>
<li><p>Social networks</p>
</li>
<li><p>Recommendation engines</p>
</li>
<li><p>Fraud detection systems</p>
</li>
<li><p>Network analysis</p>
</li>
</ul>
<p><strong>Examples:</strong> Neo4j, Amazon Neptune.</p>
<h2 id="heading-pros-of-nosql-databases"><strong>Pros of NoSQL Databases</strong></h2>
<ol>
<li><p><strong>Scalability:</strong> NoSQL databases are designed to scale horizontally, allowing for seamless expansion across multiple servers or nodes. This makes them well-suited for handling large volumes of data and accommodating growth without significant performance degradation.</p>
</li>
<li><p><strong>Flexibility in Data Models:</strong> They offer various data models (key-value, document, column-family, graph), providing flexibility to store different types of data structures, making them ideal for handling unstructured or semi-structured data.</p>
</li>
<li><p><strong>High Performance:</strong> NoSQL databases often provide high-speed read and write operations, especially when optimized for specific use cases, enabling efficient data handling for applications with high throughput(rate of data transfer) requirements.</p>
</li>
<li><p><strong>Support for Distributed Computing:</strong> Many NoSQL databases are designed for distributed computing, allowing for faster processing by distributing data across nodes or servers.</p>
</li>
<li><p><strong>Schema Flexibility:</strong> Some NoSQL databases offer schema-less or schema-flexible structures, enabling easier adaptation to changing data needs without requiring a predefined schema.</p>
</li>
</ol>
<h2 id="heading-cons-of-nosql-databases"><strong>Cons of NoSQL Databases</strong></h2>
<ol>
<li><p><strong>Limited Query Capabilities:</strong> Some NoSQL databases might lack the robust query capabilities of SQL databases, making complex querying challenging in certain scenarios.</p>
</li>
<li><p><strong>Consistency Trade-offs:</strong> Depending on the type of NoSQL database and its design choices, some can prioritize enhanced performance in distributed systems, sometimes at the expense of immediate</p>
</li>
<li><p><strong>Learning Curve:</strong> The different data models and query languages in various NoSQL databases might have a steeper learning curve for developers accustomed to SQL databases.</p>
</li>
<li><p><strong>Maturity and Tooling:</strong> While some NoSQL databases have gained maturity and support over time, the ecosystem, tooling, and community support might vary compared to well-established SQL databases.</p>
</li>
<li><p><strong>Not Always Suitable for Transactions:</strong> Some NoSQL databases prioritize scalability over ACID transactions, making them less suitable for applications requiring strict transactional consistency.</p>
</li>
</ol>
<h2 id="heading-in-conclusion"><strong>In Conclusion,</strong></h2>
<p>It is important to note that the debate between SQL and NoSQL databases doesn’t revolve around one being superior to the other. Each serves distinct purposes.</p>
<p>Deciding between them often involves considering the specific requirements of the project, the nature of the data, scalability needs, performance requirements, and the application’s use case to determine which database type aligns better with those needs. Each type has its strengths and weaknesses, making them suitable for different scenarios.</p>
<p><a target="_blank" href="https://medium.com/@theody85?source=post_page---post_author_info--6b46d77ccb7c--------------------------------">  
</a></p>
]]></content:encoded></item><item><title><![CDATA[SQL vs NoSQL Databases — Part 1]]></title><description><![CDATA[Databases are organized collections of data that are structured to enable efficient storage, retrieval, and manipulation of information. They’re the digital equivalent of a perfectly organized file cabinet, but instead of folders and papers, they han...]]></description><link>https://blog.mycodingnotebook.com/sql-vs-nosql-databases-part-1</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/sql-vs-nosql-databases-part-1</guid><category><![CDATA[Databases]]></category><category><![CDATA[Relational Database]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Tue, 28 Nov 2023 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738078520717/014ba1f0-b3a4-45b0-817a-0deb0d19b87d.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Databases are organized collections of data that are structured to enable efficient storage, retrieval, and manipulation of information. They’re the digital equivalent of a perfectly organized file cabinet, but instead of folders and papers, they handle all sorts of data — names, numbers, images, and more.</p>
<p>They’re vital across various applications — powering websites, mobile apps, financial systems, healthcare records, and countless other platforms. When it comes to types, databases mainly fall into two categories: <strong>SQL databases and NoSQL databases.</strong></p>
<p>In this article, we’ll delve into SQL databases, examining their characteristics and functionalities. Subsequently, we’ll explore NoSQL databases in the next article.</p>
<h2 id="heading-what-are-sql-databases"><strong>What are SQL Databases?</strong></h2>
<p>SQL databases, also known as <strong>relational databases</strong>, organize data in a structured manner using tables with rows and columns. The term <strong>“relational”</strong> signifies the ability to establish connections or relationships between different tables, creating a network of related data.</p>
<p><strong>Let’s explore some key characteristics of SQL databases;</strong></p>
<p><img src="https://miro.medium.com/v2/resize:fit:1400/1*zAoQK1uH0AoWECuNxK5qrQ.png" alt /></p>
<p>Database schema — <a target="_blank" href="https://popsql.com/static/images/templates/sample_db_erd.png">https://popsql.com/static/images/templates/sample_db_erd.png</a></p>
<h3 id="heading-1-tabular-structure"><strong>1. Tabular Structure</strong></h3>
<p>In SQL databases, data is structured within tables, which resemble grids or spreadsheets. These tables are composed of <strong>rows</strong> (also called records or tuples) and <strong>columns</strong> (also called fields or attributes).</p>
<p>Each <strong>column</strong> is designated for a specific type of data, such as text, numbers, or dates, representing a particular attribute.</p>
<p><strong>Rows,</strong> on the other hand, house individual instances or records of data, with each row containing a unique set of values across the columns.</p>
<p>This tabular structure helps organize and categorize information systematically, allowing for efficient storage, retrieval, and manipulation of data.</p>
<h3 id="heading-2-structured-query-language-sql"><strong>2. Structured Query Language (SQL)</strong></h3>
<p><strong>SQL,</strong> which stands for <strong>Structured Query Language</strong>, serves as the standardized language used to communicate with SQL databases. This language offers a wide array of commands and statements that allow users to perform various operations:</p>
<ol>
<li><p><strong>Data Manipulation:</strong> SQL facilitates adding, modifying, deleting, and retrieving data from the database tables.</p>
</li>
<li><p><strong>Querying:</strong> Users can formulate queries using SELECT statements to retrieve specific data based on defined criteria or conditions.</p>
</li>
<li><p><strong>Schema Modification:</strong> SQL enables the modification of the database structure, such as creating or altering tables, defining constraints, or modifying existing schema elements.</p>
</li>
<li><p><strong>Access Control:</strong> It provides mechanisms for managing user permissions, controlling access to specific data or functionalities within the database.</p>
</li>
</ol>
<p>SQL’s versatility and comprehensive syntax empower users to interact with the database efficiently, ensuring effective database management.</p>
<h3 id="heading-3-relational-model"><strong>3. Relational Model</strong></h3>
<p>SQL databases rely on the relational model to establish connections between tables using keys like <strong>primary keys</strong> and <strong>foreign keys</strong>. These keys serve as crucial components in creating relationships between different tables within the database.</p>
<ul>
<li><p><strong>Primary Keys:</strong> They uniquely identify each record in a table, ensuring that every row has a distinct identifier.</p>
</li>
<li><p><strong>Foreign Keys:</strong> These keys establish connections between tables by referencing the primary key of another table. They ensure referential integrity by enforcing relationships and constraints between linked data across tables.</p>
</li>
</ul>
<p>These relationships maintain the accuracy and consistency of data across the database. They prevent anomalies such as inconsistent or orphaned data by enforcing rules that ensure the integrity of related information.</p>
<p>Moreover, these established relationships enable powerful querying capabilities, particularly through <strong>JOIN</strong> operations. JOINs allow users to retrieve data from multiple tables simultaneously by leveraging the connections defined by primary and foreign keys.</p>
<h3 id="heading-4-predefined-schemas"><strong>4. Predefined Schemas</strong></h3>
<p>Schemas act as the architectural blueprints within relational databases, defining the structure and organization of data storage and access.</p>
<p>Here’s how schemas play a crucial role:</p>
<ol>
<li><p><strong>Table Definition:</strong> Schemas specify the tables present in the database, outlining their names, attributes, and the data types of each column. This includes defining constraints like uniqueness, not null values, or default values for columns.</p>
</li>
<li><p><strong>Relationship Establishment:</strong> They define relationships between tables through the use of keys, primarily primary keys and foreign keys. These keys establish connections, ensuring referential integrity and maintaining the relationships between related data across tables.</p>
</li>
<li><p><strong>Data Integrity Enforcement:</strong> Schemas enforce rules and constraints, ensuring data accuracy and consistency. They prevent anomalies like duplicate records, null values in mandatory fields, or data that violates defined constraints.</p>
</li>
</ol>
<h3 id="heading-5-acid-compliance"><strong>5. ACID Compliance</strong></h3>
<p>SQL databases adhere to the ACID principles which serve as the backbone of reliable and consistent database transactions within SQL databases. These principles are:</p>
<ol>
<li><p><strong>Atomicity:</strong> Atomicity guarantees that transactions are treated as <strong>indivisible</strong> or <strong>“all-or-nothing”</strong> units**.** This principle ensures that either all the tasks within a transaction are executed successfully and committed to the database, or if any part fails, none of the changes are applied.</p>
</li>
<li><p><strong>Consistency:</strong> Consistency ensures that the database <strong>moves from one valid state to another after each transaction.</strong> It involves enforcing all predefined rules, constraints, relationships, and data formats consistently, both before and after the execution of a transaction. These rules might include constraints like ensuring uniqueness in certain columns, data type adherence, or maintaining referential integrity between related tables.</p>
</li>
<li><p><strong>Isolation:</strong> Isolation ensures that <strong>multiple transactions can occur concurrently without interfering with each other.</strong> It guarantees that transactions are executed independently and in isolation, as if they were the sole operations running in the system. This prevents issues like “<strong>dirty reads</strong>”, where one transaction reads data that is being modified by another transaction.</p>
</li>
<li><p><strong>Durability:</strong> Durability guarantees that once a transaction is committed, <strong>the changes made by that transaction are permanently saved and will not be lost, even in the event of a system failure.</strong> The changes are stored in a durable form, typically on a persistent storage, ensuring that they persist even after a system crash or restart.</p>
</li>
</ol>
<h3 id="heading-6-normalization"><strong>6. Normalization</strong></h3>
<p>Normalization in relational databases is a <strong>process used to organize data efficiently by reducing redundancy and dependency.</strong> It involves structuring tables and their relationships to minimize data duplication and anomalies, ensuring data integrity and efficient querying.</p>
<h2 id="heading-examples-of-relational-database-management-systems-rdbms"><strong>Examples of Relational Database Management Systems (RDBMS)</strong></h2>
<p>RDBMS oversee the management of relational databases. They consist of software tools, applications, and services designed for creating, maintaining, and interacting with relational databases.</p>
<p>A few examples include:</p>
<ol>
<li><p><strong>MySQL:</strong> An open-source RDBMS widely used for web applications due to its reliability, ease of use, and scalability.</p>
</li>
<li><p><strong>PostgreSQL:</strong> Another open-source RDBMS known for its advanced features, extensibility, and support for complex queries and transactions.</p>
</li>
<li><p><strong>Oracle:</strong> A commercial database used for enterprise applications, known for its scalability, security, and high performance.</p>
</li>
<li><p><strong>Microsoft SQL Server:</strong> A robust RDBMS developed by Microsoft, suitable for Windows-based environments, offering strong integration with other Microsoft products.</p>
</li>
<li><p><strong>SQLite:</strong> A lightweight, self-contained SQL database engine that doesn’t require a separate server process, commonly used in embedded systems, mobile apps, and small-scale applications.</p>
</li>
<li><p><strong>MariaDB:</strong> A community-developed, forked version of MySQL, designed for compatibility with MySQL and enhanced performance and features.</p>
</li>
<li><p><strong>Microsoft Access:</strong> A desktop-based database management system part of the Microsoft Office suite, suitable for small-scale applications and individual use.</p>
</li>
</ol>
<h2 id="heading-some-use-cases-of-sql-databases"><strong>Some Use Cases of SQL Databases</strong></h2>
<ol>
<li><p><strong>Transactional Systems:</strong> SQL databases are ideal for systems requiring ACID properties, such as banking systems, e-commerce platforms, stock trading platforms, healthcare systems, booking and reservation systems, and online payment systems, where data integrity is crucial.</p>
</li>
<li><p><strong>Content Management Systems (CMS)</strong>: SQL databases often power CMS platforms that handle structured content like articles, posts, user information, etc.</p>
</li>
<li><p><strong>Data Warehousing:</strong> Data warehousing is the process of gathering, storing, and organizing vast amounts of structured data from different sources. Relational databases play a pivotal role in this environment, as they’re used to both store and analyze this structured data. They excel in handling complex queries necessary for analyzing historical data in data warehousing setups.</p>
</li>
</ol>
<h2 id="heading-pros-of-sql-databases"><strong>Pros of SQL Databases</strong></h2>
<ol>
<li><p><strong>ACID Compliance:</strong> Support for ACID properties ensures reliable transaction processing.</p>
</li>
<li><p><strong>Ensure Data Integrity:</strong> Relational databases ensure data integrity through constraints and relationships, preventing inconsistencies.</p>
</li>
<li><p><strong>Ease of Use:</strong> Relational databases have been around for a long time, leading to a wealth of resources, tools, and expertise available for developers and administrators.</p>
</li>
<li><p><strong>Facilitates Complex Queries:</strong> The relational model of relational databases enables easy data retrieval through joins, facilitating complex querying and reporting.</p>
</li>
<li><p><strong>Standardized SQL Language:</strong> The standardized SQL language fosters a common ground for working with relational databases, promoting ease of use, portability, and access to extensive resources and expertise across different database platforms.</p>
</li>
</ol>
<h2 id="heading-cons-of-sql-databases"><strong>Cons of SQL Databases</strong></h2>
<ol>
<li><p><strong>Performance Impact with Complex Queries:</strong> As queries become more complex, performance can decrease, especially with large datasets.</p>
</li>
<li><p><strong>Scalability Challenges:</strong> Horizontal scalability that is, adding more servers or nodes to handle increased load can be complex due to the emphasis on maintaining strong relationships between data.</p>
</li>
<li><p><strong>Normalization Overhead:</strong> Normalization, while ensuring data consistency, can lead to increased complexity in data retrieval across multiple tables.</p>
</li>
<li><p><strong>Rigid Schema Changes:</strong> Changes to the database schema might be challenging and require careful planning, impacting flexibility.</p>
</li>
</ol>
<h2 id="heading-in-conclusion"><strong>In Conclusion,</strong></h2>
<p>SQL databases generally refer to relational databases that use SQL as their query language and adhere to the relational model for data management and organization. This adherence to the relational model, coupled with their commitment to the ACID principles, makes them invaluable for applications demanding precise data handling, such as financial systems and e-commerce platforms.</p>
<p>Stay tuned for the <a target="_blank" href="https://theody.hashnode.dev/sql-vs-nosql-databases-part-2">next article</a> where we will shift gears towards NoSQL databases, uncovering their diverse structures, scalability advantages, and suitability for dynamic and evolving data needs.</p>
]]></content:encoded></item><item><title><![CDATA[Tricky Parts of JavaScript II — Scoping, Hoisting & `const` Keyword]]></title><description><![CDATA[This is the sequel to a previous article which we tackled the intricacies of the various data types and their behavior with the assignment operator. We also uncovered the tricky aspects of equality operators. If you missed it, you can catch up here.
...]]></description><link>https://blog.mycodingnotebook.com/tricky-parts-of-javascript-ii-scoping-hoisting-const-keyword</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/tricky-parts-of-javascript-ii-scoping-hoisting-const-keyword</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[programming languages]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Fri, 10 Nov 2023 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738075563478/fa82ac2a-e202-4dc4-a31d-d19594a68b7a.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is the sequel to a previous article which we tackled the intricacies of the various data types and their behavior with the assignment operator. We also uncovered the tricky aspects of equality operators. If you missed it, you can catch up <a target="_blank" href="https://theody.hashnode.dev/tricky-parts-of-javascript-i-data-types-vs-assignment-equality-operators">here</a>.</p>
<p><strong>Now, let's jump into the next part of our JavaScript journey and explore some of the more tricky aspects!</strong></p>
<h2 id="heading-1-scoping"><strong>1. Scoping</strong></h2>
<p>In JavaScript, <strong>scoping determines where in your code a particular variable, function, or identifier is accessible.</strong> There are two fundamental types of scope:</p>
<ul>
<li><p><strong>Global Scope:</strong> Variables declared outside any function or block have global scope, meaning they are accessible throughout the entire program.</p>
</li>
<li><p><strong>Local Scope:</strong> Variables declared inside a function or block have local scope, meaning they are only accessible within that function or block. This can be subcategorized into <strong>Function Scope</strong> and <strong>Block Scope</strong>.</p>
</li>
</ul>
<p><strong>Note:</strong> There is also the concept of lexical or static scoping in JS which is beyond the scope of this article.</p>
<p><strong>Now let’s explore how local scoping can be tricky with the</strong> <code>var</code><strong>,</strong> <code>const</code> <strong>and</strong> <code>let</code> <strong>keywords used for variable declarations:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example 1</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">scopeExampleOne</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">if</span> (<span class="hljs-literal">true</span>) {
        <span class="hljs-keyword">var</span> x = <span class="hljs-number">10</span>;
    }
    <span class="hljs-built_in">console</span>.log(x); <span class="hljs-comment">// 10</span>
}
scopeExampleOne();

<span class="hljs-comment">// Example 2</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">scopeExampleTwo</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">if</span> (<span class="hljs-literal">true</span>) {
        <span class="hljs-keyword">let</span> y = <span class="hljs-number">20</span>;
    }
    <span class="hljs-built_in">console</span>.log(y); <span class="hljs-comment">// ReferenceError: y is not defined</span>
}
scopeExampleTwo();


<span class="hljs-comment">// Example 3</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">scopeExampleThree</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">if</span> (<span class="hljs-literal">true</span>) {
        <span class="hljs-keyword">const</span> z = <span class="hljs-number">20</span>;
    }
    <span class="hljs-built_in">console</span>.log(z); <span class="hljs-comment">// ReferenceError: z is not defined</span>
}
scopeExampleThree();
</code></pre>
<p>Let’s delve into each example to understand the behaviors seen above.</p>
<h3 id="heading-example-1-var-function-scope"><strong>Example 1 — var (Function Scope)</strong></h3>
<ul>
<li><p>In this example, the variable <code>x</code> is declared using <code>var</code>, which is <strong>function-scoped.</strong></p>
</li>
<li><p>This means that the variable is accessible throughout the entire function, even though it was declared inside the <code>if</code> block.</p>
</li>
<li><p>Hence, the <code>console.log(x)</code> statement outside the <code>if</code> block successfully logs the value of <code>x</code> due to this scoping behavior.</p>
</li>
</ul>
<h3 id="heading-example-2-let-block-scope"><strong>Example 2 — let (Block Scope)</strong></h3>
<ul>
<li><p>In this case, the variable <code>y</code> is declared with <code>let</code>, which has <strong>block scope.</strong></p>
</li>
<li><p>Variables with block scope are limited to the block (in this case, the <code>if</code> block) where they are defined.</p>
</li>
<li><p>Attempting to access <code>y</code> outside the block results in a <code>ReferenceError</code> because it is not defined in that scope.</p>
</li>
</ul>
<h3 id="heading-example-3-const-block-scope"><strong>Example 3 — const (Block Scope)</strong></h3>
<ul>
<li><p>Similar to Example 2, the variable <code>z</code> is declared using <code>const</code>, which also has <strong>block scope.</strong></p>
</li>
<li><p>The attempt to log <code>z</code> outside the <code>if</code> block results in a <code>ReferenceError</code> because <code>z</code> is not defined in that scope.</p>
</li>
</ul>
<h2 id="heading-2-hoisting"><strong>2. Hoisting</strong></h2>
<p><strong>Hoisting</strong> is a behavior in JavaScript where <strong>variable and function declarations are moved to the top of their containing scope during the compilation phase.</strong> This means that you can use variables and functions in your code before they are declared.</p>
<p>There are two main types of hoisting in JavaScript: <strong>Variable Hoisting</strong> and <strong>Function Hoisting.</strong></p>
<p>Now, let’s examine some tricky aspects of hoisting with the code snippet below:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example 1</span>
<span class="hljs-built_in">console</span>.log(a); <span class="hljs-comment">// undefined, not error</span>
<span class="hljs-keyword">var</span> a = <span class="hljs-number">10</span>;

<span class="hljs-comment">// Example 2 </span>
<span class="hljs-built_in">console</span>.log(b); <span class="hljs-comment">// ReferenceError: b is not defined</span>
<span class="hljs-keyword">let</span> b = <span class="hljs-number">20</span>;

<span class="hljs-comment">// Example 3 </span>
<span class="hljs-built_in">console</span>.log(c); <span class="hljs-comment">// ReferenceError: c is not defined</span>
<span class="hljs-keyword">const</span> b = <span class="hljs-number">30</span>;

<span class="hljs-comment">// Example 4</span>
foo(); <span class="hljs-comment">// "Hello, world!"</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">foo</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello, world!"</span>);
}
</code></pre>
<h3 id="heading-example-1-hoisting-with-var"><strong>Example 1 — Hoisting with var</strong></h3>
<ul>
<li><p>In JavaScript, variables declared with <code>var</code> are hoisted to the top of their scope during compilation. This allows you to use the variable before its declaration.</p>
</li>
<li><p><strong>Note that only the declaration</strong>, not the initialization (assignment), is hoisted, and the variable is initialized with <code>undefined</code> during this process.</p>
</li>
</ul>
<p><strong>In this example,</strong></p>
<ul>
<li><p><code>a</code> is hoisted and the variable declaration is effectively moved to the top of the scope. However, the assignment (<code>var a = 10</code>) hasn't happened yet at this point.</p>
</li>
<li><p>The <code>console.log(a)</code> statement prints <code>undefined</code> because, during the initial pass, the variable <code>a</code> is recognized but not assigned a value yet.</p>
</li>
</ul>
<h3 id="heading-examples-2-amp-3-hoisting-with-let-and-const"><strong>Examples 2 &amp; 3 — Hoisting with let and const</strong></h3>
<ul>
<li><p>Variables declared with <code>let</code> and <code>const</code> are hoisted to the top of their containing block but are not initialized during this phase.</p>
</li>
<li><p>Instead of being initialized with <code>undefined</code> like variables declared with <code>var</code>, they stay in an uninitialized state.</p>
</li>
<li><p>This creates the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#temporal_dead_zone_tdz"><strong>temporal dead zone</strong></a>, which refers to the period between the start of the current scope and the point where the variable is declared. During this zone, attempting to access or read the value of the variable leads to a <code>ReferenceError</code>.</p>
</li>
</ul>
<p><strong>In these examples,</strong></p>
<ul>
<li>The lines <code>console.log(b)</code> and <code>console.log(c)</code>encounters an error because the variables <code>b</code> and <code>c</code> have not been initialized at this point. This is a temporal dead zone for the variables <code>b</code> and <code>c</code>.</li>
</ul>
<h3 id="heading-example-4-function-hoisting"><strong>Example 4 — Function Hoisting</strong></h3>
<ul>
<li><p>Function declarations are hoisted to the top of their scope during the compilation phase, similar to variable hoisting.</p>
</li>
<li><p>Unlike variables, both the declaration and the function’s body are hoisted to the top of the scope.</p>
</li>
</ul>
<p><strong>In this example,</strong></p>
<ul>
<li>When <code>foo()</code> is called, it successfully logs "Hello, world!" to the console. This is possible because the function declaration is hoisted, and the entire function is available for execution.</li>
</ul>
<h3 id="heading-note-hoisting-of-function-expressions"><strong>Note: Hoisting of Function Expressions</strong></h3>
<p>When using a function expression assigned to a variable, the declaration is hoisted, but the assignment is not. This behavior contrasts with function declarations, where the entire function is hoisted.</p>
<p><strong>Let’s look at an example:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">//Function Expressions with `var`</span>
foo(); <span class="hljs-comment">// TypeError: foo is not a function</span>
<span class="hljs-keyword">var</span> foo = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello, world!"</span>);
};

bar(); <span class="hljs-comment">// TypeError: bar is not a function</span>
<span class="hljs-keyword">var</span> bar = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello, world!"</span>); <span class="hljs-comment">// ES6 Arrow Function</span>
};


<span class="hljs-comment">//Function Expressions with `let`</span>
foo(); <span class="hljs-comment">// ReferenceError: Cannot access 'foo' before initialization</span>
<span class="hljs-keyword">let</span>  foo = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello, world!"</span>);
};

bar(); <span class="hljs-comment">// ReferenceError: Cannot access 'bar' before initialization</span>
<span class="hljs-keyword">let</span>  bar = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello, world!"</span>); <span class="hljs-comment">// ES6 Arrow Function</span>
};


<span class="hljs-comment">//Function Expressions with const</span>
foo(); <span class="hljs-comment">// ReferenceError: Cannot access 'foo' before initialization"</span>
<span class="hljs-keyword">const</span> foo = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello, world!"</span>);
};

bar(); <span class="hljs-comment">// ReferenceError: Cannot access 'bar' before initialization"</span>
<span class="hljs-keyword">const</span> bar = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello, world!"</span>); <span class="hljs-comment">// ES6 Arrow Function</span>
};
</code></pre>
<p><strong>In this code snippet,</strong></p>
<ul>
<li><p>The variables are hoisted to the top of their scopes during the compilation phase, similar to variable declarations. However, only the declaration is hoisted, not the assignment.</p>
</li>
<li><p>For <code>var</code> declarations, attempting to call <code>foo()</code> and <code>bar()</code> before the assignment results in a <code>TypeError</code> because <code>foo</code> and <code>bar()</code> are declared and initialized as <code>undefined</code>, but not yet assigned a function.</p>
</li>
<li><p>Both <code>let</code> and <code>const</code> declarations are hoisted, but they are in the "<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#temporal_dead_zone_tdz"><strong>temporal dead zone</strong></a>" until the line of code where they are assigned. Attempting to call <code>foo()</code> and <code>bar()</code> before the assignment results in a <code>ReferenceError</code> because though they are declared, they remain uninitialized.</p>
</li>
</ul>
<h2 id="heading-3-const-keyword"><strong>3.</strong> <code>const</code> <strong>Keyword</strong></h2>
<p>The use of “<strong>const</strong>” in JavaScript declares a variable that cannot be reassigned after its initialization.</p>
<p>Let’s consider the code snippet below to examine some tricky aspects of the “const” keyword:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example 1</span>
<span class="hljs-keyword">const</span> gravity = <span class="hljs-number">9.8</span>;
gravity = <span class="hljs-number">9.81</span>; <span class="hljs-comment">// TypeError: Assignment to constant variable.</span>

<span class="hljs-comment">// Example 2</span>
<span class="hljs-keyword">const</span> planet = <span class="hljs-string">"Earth"</span>;
planet = <span class="hljs-string">"Mars"</span>; <span class="hljs-comment">// TypeError: Assignment to constant variable.</span>

<span class="hljs-comment">// Example 3</span>
<span class="hljs-keyword">const</span> colors = [<span class="hljs-string">"red"</span>, <span class="hljs-string">"green"</span>, <span class="hljs-string">"blue"</span>];
colors.push(<span class="hljs-string">"yellow"</span>);
<span class="hljs-built_in">console</span>.log(colors); <span class="hljs-comment">// ["red", "green", "blue", "yellow"]</span>

<span class="hljs-comment">//Example 4</span>
<span class="hljs-keyword">const</span> person = { <span class="hljs-attr">name</span>: <span class="hljs-string">"Fred"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">25</span> };
person.age = <span class="hljs-number">26</span>;
<span class="hljs-built_in">console</span>.log(person); <span class="hljs-comment">// { name: "Fred", age: 26 }</span>
</code></pre>
<p>Before delving into the examples provided, a brief revisit to my <a target="_blank" href="https://theody.hashnode.dev/tricky-parts-of-javascript-i-data-types-vs-assignment-equality-operators">previous article</a> in this series would serve as a helpful reference.</p>
<p>This will remind us that the variables <code>gravity</code> and <code>planet</code> in examples 1 and 2 respectively belong to the category of <strong>primitive data types</strong>.</p>
<p>Similarly, the variables <code>colors</code> and <code>person</code> in examples 3 and 4 fall under the <strong>reference data types category.</strong></p>
<p><strong>Now, let’s examine each category in the code snippet above:</strong></p>
<h3 id="heading-example-1-amp-2-immutability-for-primitive-values"><strong>Example 1 &amp; 2 — Immutability for Primitive Values</strong></h3>
<ul>
<li><p>In these examples, the attempt to reassign the constant variables <code>gravity</code> and <code>planet</code> resulted in a <code>TypeError</code>.</p>
</li>
<li><p>This error occurs because the <code>const</code> declaration ensures that the variable remains constant and cannot be reassigned after initialization.</p>
</li>
</ul>
<h3 id="heading-example-3-amp-4-immutability-for-reference-types"><strong>Example 3 &amp; 4 — Immutability for Reference Types</strong></h3>
<ul>
<li><p>In these examples, despite the use of the <code>const</code> keyword, the content of arrays or objects can be modified.</p>
</li>
<li><p>This is because, for reference data types, <code>const</code> doesn't impose immutability on the contents; it merely prevents reassignment of the variable.</p>
</li>
<li><p>As such, attempting to reassign the entire array or object will result in an error:</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example 3</span>
<span class="hljs-keyword">const</span> colors = [<span class="hljs-string">"red"</span>, <span class="hljs-string">"green"</span>, <span class="hljs-string">"blue"</span>];
colors = [<span class="hljs-string">"orange"</span>, <span class="hljs-string">"purple"</span>, <span class="hljs-string">"pink"</span>]; <span class="hljs-comment">// TypeError: Assignment to a constant variable.</span>

<span class="hljs-comment">// Example 4</span>
<span class="hljs-keyword">const</span> person = { <span class="hljs-attr">name</span>: <span class="hljs-string">"Alice"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">25</span> };
person = { <span class="hljs-attr">name</span>: <span class="hljs-string">"Bob"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">30</span> }; <span class="hljs-comment">// TypeError: Assignment to a constant variable.</span>
</code></pre>
<p><strong>In these cases,</strong></p>
<ul>
<li><p>The attempt to reassign a new value to the entire variable <code>colors</code> or <code>person</code> throws an error.</p>
</li>
<li><p><code>const</code> ensures that the variable itself cannot be reassigned but allows for modification of the contents.</p>
</li>
</ul>
<h2 id="heading-in-conclusion"><strong>In Conclusion,</strong></h2>
<p>We’ve explored some tricky parts of JavaScript, from <strong>scoping</strong> and <strong>hoisting</strong> to the unique traits of <code>const</code> variables—tools that’ll help you optimize your code.</p>
<p>Stay tuned for more insights!</p>
<p><a target="_blank" href="https://medium.com/@theody85?source=post_page---post_author_info--338a106e989f--------------------------------">  
</a></p>
]]></content:encoded></item><item><title><![CDATA[Tricky Parts of JavaScript I — Data Types vs Assignment & Equality Operators]]></title><description><![CDATA[In the world of programming, JavaScript, like any language, has its fair share of tricky aspects that can stump developers. Whether you’re a seasoned pro or just starting out, these intricacies are bound to cross your path as you build web applicatio...]]></description><link>https://blog.mycodingnotebook.com/tricky-parts-of-javascript-i-data-types-vs-assignment-equality-operators</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/tricky-parts-of-javascript-i-data-types-vs-assignment-equality-operators</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[programming languages]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Wed, 08 Nov 2023 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737885591894/12b16e88-8464-45f4-b3d5-f9fff2547431.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the world of programming, JavaScript, like any language, has its fair share of tricky aspects that can stump developers. Whether you’re a seasoned pro or just starting out, these intricacies are bound to cross your path as you build web applications or tinker with server-side logic using Node.js. In this article and the next, we’ll explore some of these tricky elements.</p>
<p><strong>So, let’s dive right in.</strong></p>
<h2 id="heading-1-primitive-vs-reference-data-types-and-assignment-behaviour"><strong>1. Primitive vs. Reference Data Types and Assignment Behaviour</strong></h2>
<p>In JavaScript, data types are broadly categorised into two classes: <strong>primitive data types</strong>, often referred to as “value data types,” and <strong>reference data types.</strong> These two categories exhibit distinct behaviours when it comes to assignment.</p>
<p>Let’s delve into some examples to illuminate this concept:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example Set 1</span>
<span class="hljs-keyword">let</span> a = <span class="hljs-number">5</span>;
<span class="hljs-keyword">let</span> b = a;
b = <span class="hljs-number">10</span>;

<span class="hljs-built_in">console</span>.log(a); <span class="hljs-comment">// Output: 5</span>
<span class="hljs-built_in">console</span>.log(b); <span class="hljs-comment">// Output: 10</span>

<span class="hljs-comment">// Example Set 2</span>
<span class="hljs-keyword">let</span> str1 = <span class="hljs-string">"Hello"</span>;
<span class="hljs-keyword">let</span> str2 = str1;
str2 += <span class="hljs-string">" World"</span>;

<span class="hljs-built_in">console</span>.log(str1); <span class="hljs-comment">// Output: "Hello"</span>
<span class="hljs-built_in">console</span>.log(str2); <span class="hljs-comment">// Output: "Hello World"</span>

<span class="hljs-comment">// Example Set 3</span>
<span class="hljs-keyword">let</span> arr1 = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">let</span> arr2 = arr1;
arr2.push(<span class="hljs-number">4</span>);

<span class="hljs-built_in">console</span>.log(arr1); <span class="hljs-comment">// Output: [1, 2, 3, 4]</span>
<span class="hljs-built_in">console</span>.log(arr2); <span class="hljs-comment">// Output: [1, 2, 3, 4]</span>

<span class="hljs-comment">// Example Set 4</span>
<span class="hljs-keyword">let</span> obj1 = { <span class="hljs-attr">name</span>: <span class="hljs-string">"Ivan"</span> };
<span class="hljs-keyword">let</span> obj2 = obj1;
obj2.name = <span class="hljs-string">"Esther"</span>;

<span class="hljs-built_in">console</span>.log(obj1.name); <span class="hljs-comment">// Output: "Esther"</span>
<span class="hljs-built_in">console</span>.log(obj2.name); <span class="hljs-comment">// Output: "Esther"</span>
</code></pre>
<h3 id="heading-example-sets-1-amp-2-primitive-values-number-and-string"><strong>Example Sets 1 &amp; 2 — Primitive Values (Number and String)</strong></h3>
<p>In these set of examples, we’re working with primitive values of the Number and String data types, which belong to the category of Primitive Data Types. JavaScript also includes other primitive data types, such as booleans, null, undefined, symbols, and BigInt.</p>
<p>Let’s look at three characteristics of Primitive Data types which are essential to understanding the behaviours in these two set examples:</p>
<ol>
<li><p><strong>Direct Storage:</strong> Primitive values are stored directly in memory. What this means is that when you assign a primitive value to a variable, that variable holds the actual value directly in memory.</p>
</li>
<li><p><strong>Passed by Value:</strong> Primitive values are passed by value. What this means is that when you assign a primitive value to a another variable, a copy of the actual value is made. Modifying the copied value does not affect the original value.</p>
</li>
<li><p><strong>Immutable:</strong> Once a primitive value is created, it cannot be changed. Any operation that appears to modify a primitive value actually creates a new value.</p>
</li>
</ol>
<p><strong>In the example set 1:</strong></p>
<ul>
<li><p>Variable <code>a</code> is assigned the primitive value <code>5</code> and <code>a</code> holds the value directly in memory.</p>
</li>
<li><p>When <code>b</code> is assigned the value of <code>a</code> using <code>b = a</code>, a copy of the actual primitive value in <code>a</code> (which is <code>5</code>) is made and stored in <code>b</code> due to the passed by value property.</p>
</li>
<li><p>Subsequently, when <code>b</code> is reassigned the value of <code>10</code> , this change does not propagate back to <code>a</code> since each variable has its own independent copy of the value <code>5</code>.</p>
</li>
<li><p><code>console.log(a);</code> outputs <code>5</code> because the value of <code>a</code> remains unaffected by the subsequent assignment to <code>b</code>.</p>
</li>
<li><p><code>console.log(b);</code> outputs <code>10</code> because <code>b</code> was assigned the value <code>10</code> after initially holding the value of <code>a</code>.</p>
</li>
</ul>
<p><strong>Similarly, with strings in example set 2:</strong></p>
<ul>
<li><p>Variables <code>str1</code> and <code>str2</code> initially hold distinct copies of the primitive value <code>"Hello"</code>.</p>
</li>
<li><p>When you concatenate <code>" World"</code> to <code>str2</code> using the <code>+=</code> operator, it creates a new string(due to the immutability property) with the combined value and assigns it to <code>str2</code>.</p>
</li>
<li><p>Importantly, this operation does not modify the original string value in <code>str1</code>, and the value in <code>str1</code> remains unchanged.</p>
</li>
</ul>
<h3 id="heading-example-sets-3-amp-4-reference-typesarrays-and-objects"><strong>Example Sets 3 &amp; 4— Reference Types(Arrays and Objects)</strong></h3>
<p>In these examples, we are dealing with Arrays and Objects which are Reference data types. Other examples are Functions and Classes. Here are some key characteristics of reference data types:</p>
<ol>
<li><p><strong>Stored by Reference:</strong> When you create a variable and assign a reference data type to that variable, the variable effectively holds a reference or memory address to the location in memory where the data is stored.</p>
</li>
<li><p><strong>Passed by Reference:</strong> When you assign a reference data type to another variable, you are effectively passing or assigning the reference, not duplicating the data. As a result, any changes made through the new variable affects the original data.</p>
</li>
<li><p><strong>Mutable:</strong> Reference data types are mutable, meaning that you can modify their content after they are created. Changes made to the data through one reference affect all references pointing to the same data.</p>
</li>
</ol>
<p><strong>In example set 3:</strong></p>
<ul>
<li><p>Variables <code>arr1</code> and <code>arr2</code> hold a shared reference to the same array data.</p>
</li>
<li><p>When <code>arr2</code> is modified by pushing the value 4 into it, this change directly affects the underlying data that both <code>arr1</code> and <code>arr2</code> point to.</p>
</li>
<li><p>As a result, the data within the array is altered, and both <code>arr1</code> and <code>arr2</code> yield the same updated array with the added value 4.</p>
</li>
</ul>
<p><strong>In example set 4:</strong></p>
<ul>
<li><p>Variables <code>obj1</code> and <code>obj2</code> similarly share a reference to the same object data.</p>
</li>
<li><p>The alteration of the <code>name</code> property in <code>obj2</code> from "<strong>Ivan</strong>" to "<strong>Esther</strong>" impacts the underlying object that both variables reference.</p>
</li>
<li><p>Consequently, the change is reflected in both <code>obj1</code> and <code>obj2</code>, and they both display the updated <code>name</code> property value, which is "<strong>Esther</strong>".</p>
</li>
</ul>
<h2 id="heading-2-equality-operators"><strong>2. Equality Operators</strong></h2>
<p>JavaScript has two types of equality operators: <code>==</code> (loose equality) and <code>===</code> (strict equality). These operators can be tricky, as they don’t always behave as one might expect, particularly when comparing different data types or values.</p>
<p>Let’s explore both and see how they can be tricky with some examples:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example Set 1</span>
<span class="hljs-number">1</span> == <span class="hljs-string">'1'</span>;  <span class="hljs-comment">// true (string '1' is coerced to a number for comparison)</span>
<span class="hljs-number">0</span> == <span class="hljs-literal">false</span>;  <span class="hljs-comment">// true (coerces boolean to number for comparison)</span>
<span class="hljs-string">"0"</span> == <span class="hljs-literal">false</span>;  <span class="hljs-comment">// true (both are coerced to number 0)</span>
<span class="hljs-literal">null</span> == <span class="hljs-literal">undefined</span>;  <span class="hljs-comment">// true (both are considered equal in ==)</span>


<span class="hljs-comment">// Example Set 2</span>
<span class="hljs-number">1</span> === <span class="hljs-string">'1'</span>;  <span class="hljs-comment">// false (number is not equal to string)</span>
<span class="hljs-number">0</span> === <span class="hljs-literal">false</span>;  <span class="hljs-comment">// false (number is not equal to boolean)</span>
<span class="hljs-string">"0"</span> == <span class="hljs-literal">false</span>;  <span class="hljs-comment">// false (string is not equal to boolean)</span>
<span class="hljs-literal">null</span> === <span class="hljs-literal">undefined</span>;  <span class="hljs-comment">// false (different data types)</span>
</code></pre>
<p>To understand these behaviors, let’s dive deeper into each operator type:</p>
<h3 id="heading-loose-equality"><strong>Loose Equality (==):</strong></h3>
<p>The loose equality operator compares values while allowing type coercion, meaning it attempts to convert the values into a common type before making the comparison. This can lead to unexpected results, making it generally advisable to avoid its use.</p>
<p>In the first example set, the operands are coerced to the same data type before the comparison, hence returning true for all comparisons.</p>
<h3 id="heading-strict-equality"><strong>Strict Equality (===):</strong></h3>
<p>The strict equality operator, on the other hand, compares values for equality without performing type coercion. It checks not only the value but also the data type. This typically leads to more predictable results.</p>
<p>In the second example set, the operands aren’t coerced, and their data types are explicitly considered, leading to false results for all comparisons.</p>
<h3 id="heading-note-comparing-reference-data-types"><strong>Note: Comparing Reference Data Types</strong></h3>
<p>When comparing reference data types, such as arrays and objects, JavaScript’s equality operators check if the references point to the same data in memory, not if their content is the same.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//Will Return False</span>
<span class="hljs-keyword">const</span> arr1 = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">const</span> arr2 = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
arr1 == arr2; <span class="hljs-comment">// false (arrays are compared by reference, not by content)</span>
arr1 === arr2; <span class="hljs-comment">// false (for the same reason as above)</span>


<span class="hljs-keyword">const</span> obj1 = { <span class="hljs-attr">key</span>: <span class="hljs-string">"value"</span> };
<span class="hljs-keyword">const</span> obj2 = { <span class="hljs-attr">key</span>: <span class="hljs-string">"value"</span> };
obj1 == obj2; <span class="hljs-comment">// false (objects are compared by reference, not by content)</span>
obj1 === obj2; <span class="hljs-comment">// false (for the same reason as above)</span>


<span class="hljs-comment">//Will Return True</span>
<span class="hljs-keyword">const</span> arr1 = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">const</span> arr2 = arr1; <span class="hljs-comment">// arr2 reference the same array as arr1</span>
arr1 == arr2; <span class="hljs-comment">// true (both variables reference the same array)</span>
arr1 === arr2; <span class="hljs-comment">// true (for the same reason as above)</span>

<span class="hljs-keyword">const</span> obj1 = { <span class="hljs-attr">key</span>: <span class="hljs-string">"value"</span> };
<span class="hljs-keyword">const</span> obj2 = obj1; <span class="hljs-comment">// obj2 reference the same object as obj1</span>
obj1 == obj2; <span class="hljs-comment">// true (both variables reference the same object)</span>
obj1 === obj2; <span class="hljs-comment">// true (for the same reason as above)</span>
</code></pre>
<p><strong>For comparing the content of reference data types</strong>, you’ll usually need to iterate through their properties or elements to check for equality. Alternatively, you can serialize objects to JSON strings with <code>JSON.stringify()</code> and compare those strings, or use libraries like lodash or Underscore.js, which offer the <code>isEqual()</code> utility function for such comparisons.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In this article, we uncovered some intricacies of primitive and reference data types and their corresponding behaviors with respect to assignment operators. We also covered the differences in equality operators and how they can sometimes lead to surprising results.</p>
<p>But our journey is far from over. Stay tuned for the <a target="_blank" href="https://theody.hashnode.dev/tricky-parts-of-javascript-ii-scoping-hoisting-const-keyword?showSharer=true">next article</a> where we’ll dive into scope and hoisting, shedding light on how hoisting can sometimes lead to surprising behavior. Additionally, we’ll explore the immutability of variables created with <code>const</code> and how it can affect your code.</p>
]]></content:encoded></item><item><title><![CDATA[Programming Principles III: Writing SOLID code]]></title><description><![CDATA[Looking back on our journey, we’ve delved into a diverse collection of programming principles. From KISS, DRY, YAGNI, Clean Code, Fail Fast, SoC, LoD, LoLA, to TDA, these principles have illuminated the path to crafting code that is not only maintain...]]></description><link>https://blog.mycodingnotebook.com/programming-principles-iii-writing-solid-code</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/programming-principles-iii-writing-solid-code</guid><category><![CDATA[SOLID principles]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[Programming Tips]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Wed, 01 Nov 2023 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737643311372/fe053ec7-310f-4da3-ad2b-166b15ac93ed.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Looking back on our journey, we’ve delved into a diverse collection of programming principles. From KISS, DRY, YAGNI, Clean Code, Fail Fast, SoC, LoD, LoLA, to TDA, these principles have illuminated the path to crafting code that is not only maintainable but also elegant. If you haven’t had the chance to read the previous articles in this series, you can find the link <a target="_blank" href="https://theody.hashnode.dev/programming-principles-ii-going-beyond-the-basics">here</a>.</p>
<p>In this last article, we will delve into the SOLID principles and how they play a pivotal role in enhancing the maintainability and extensibility of code.</p>
<h2 id="heading-what-is-the-solid-principles"><strong>What is the SOLID Principles?</strong></h2>
<p>The SOLID principles are a set of five design principles that are significantly used in Object-Oriented Programming(OOP) to create software that is maintainable, flexible, and scalable. Introduced by <a target="_blank" href="https://en.wikipedia.org/wiki/Robert_C._Martin">Robert C. Martin</a> in the early 2000s, these principles are widely regarded as best practices for achieving clean, modular, and efficient software. Although initially designed for OOP, these principles are versatile and can be effectively applied across diverse programming paradigms, including Functional Programming.</p>
<p><strong>Now, let’s delve into what the SOLID acronym stands for:</strong></p>
<h2 id="heading-1-single-responsibility-principlesrp"><strong>1. Single Responsibility Principle(SRP)</strong></h2>
<p>The Single Responsibility Principle emphasizes that <strong>a class should have only one reason to change</strong>. In other words, a class should have a single, well-defined responsibility or function. This principle closely aligns with the <strong>Separation of Concerns (SoC)</strong> principle we explored in the previous <a target="_blank" href="https://theody.hashnode.dev/programming-principles-ii-going-beyond-the-basics">article</a>.</p>
<p>To better grasp the concept of SRP, let’s consider an example within the context of a basic banking application and explore how SRP can be effectively applied.</p>
<h3 id="heading-violation-of-srp"><strong>Violation of SRP :</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BankAccount</span> </span>{
  <span class="hljs-keyword">constructor</span>(accountNumber) {
    <span class="hljs-built_in">this</span>.accountNumber = accountNumber;
    <span class="hljs-built_in">this</span>.balance = <span class="hljs-number">0</span>;
  }

  deposit(amount) {
    <span class="hljs-built_in">this</span>.balance += amount;
  }

  withdraw(amount) {
    <span class="hljs-built_in">this</span>.balance -= amount;
  }

  sendNotification(message, recipient) {
    <span class="hljs-comment">// Send an email notification to the recipient</span>
    <span class="hljs-comment">// Violates SRP by handling both account management and notification</span>
  }
}
</code></pre>
<p><strong>In this code,</strong></p>
<ul>
<li><p>the <code>BankAccount</code> class is responsible for both managing the account (deposits and withdrawals) and sending notifications.</p>
</li>
<li><p>This violates the SRP because it has two distinct responsibilities.</p>
</li>
</ul>
<h3 id="heading-adherence-to-srp"><strong>Adherence to SRP :</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BankAccount</span> </span>{
  <span class="hljs-keyword">constructor</span>(accountNumber) {
    <span class="hljs-built_in">this</span>.accountNumber = accountNumber;
    <span class="hljs-built_in">this</span>.balance = <span class="hljs-number">0</span>;
  }

  deposit(amount) {
    <span class="hljs-built_in">this</span>.balance += amount;
  }

  withdraw(amount) {
    <span class="hljs-built_in">this</span>.balance -= amount;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NotificationService</span> </span>{
  sendNotification(message, recipient) {
    <span class="hljs-comment">// Send an email notification to the recipient</span>
  }
}
</code></pre>
<p><strong>In the refactored code</strong>,</p>
<ul>
<li><p>We’ve separated the responsibility of sending notifications into a separate <code>NotificationService</code> class, while the <code>BankAccount</code> class now solely focuses on managing the bank account.</p>
</li>
<li><p>This adheres to the SRP as each class has a single, well-defined responsibility.</p>
</li>
</ul>
<h2 id="heading-2-open-closed-principleocp"><strong>2. Open-Closed Principle(OCP)</strong></h2>
<p>This principle states that a <strong>software entity such as a class, a module, or a function should be open for extension but closed for modification.</strong></p>
<h3 id="heading-expanding-on-the-ocp-principle">Expanding on the OCP Principle:</h3>
<ul>
<li><p><strong>Open for Extension</strong></p>
<p>  This aspect of the OCP encourages you to design your code in a way that allows you to add new functionalities by creating new code entities, such as subclasses or additional modules, without altering the existing, working code. This promotes code reuse and extensibility.</p>
</li>
<li><p><strong>Closed For Modification:</strong></p>
<p>  This aspect emphasises that once a module is considered stable and functional, you should avoid making changes to its source code. Changing the code of a working module can introduce bugs, affect the stability of the existing features, and require extensive testing.</p>
</li>
</ul>
<p>Let’s look at a simple example of a class that calculates the area of different shapes to illustrate how OCP is applied:</p>
<h3 id="heading-violation-of-ocp"><strong>Violation of OCP :</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> </span>{
  <span class="hljs-keyword">constructor</span>(type, data) {
    <span class="hljs-built_in">this</span>.type = type;
    <span class="hljs-built_in">this</span>.data = data;
  }

  calculateArea() {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.type === <span class="hljs-string">'circle'</span>) {
      <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.PI * <span class="hljs-built_in">this</span>.data.radius ** <span class="hljs-number">2</span>;
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.type === <span class="hljs-string">'rectangle'</span>) {
      <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.data.width * <span class="hljs-built_in">this</span>.data.height;
    }
  }
}
</code></pre>
<p><strong>In this code,</strong></p>
<ul>
<li>The <code>Shape</code> class violates the OCP because every time you want to add a new shape (e.g. a triangle), you need to modify the <code>calculateArea</code> method, which should be closed for modification.</li>
</ul>
<h3 id="heading-adherence-to-ocp"><strong>Adherence to OCP :</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> </span>{
  calculateArea() {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"calculateArea method must be implemented in subclasses"</span>);
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
  <span class="hljs-keyword">constructor</span>(radius) {
    <span class="hljs-built_in">this</span>.radius = radius;
  }

  calculateArea() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.PI * <span class="hljs-built_in">this</span>.radius ** <span class="hljs-number">2</span>;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
  <span class="hljs-keyword">constructor</span>(width, height) {
    <span class="hljs-built_in">this</span>.width = width;
    <span class="hljs-built_in">this</span>.height = height;
  }

  calculateArea() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.width * <span class="hljs-built_in">this</span>.height;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Triangle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
  <span class="hljs-keyword">constructor</span>(base, height) {
    <span class="hljs-built_in">this</span>.base = base;
    <span class="hljs-built_in">this</span>.height = height;
  }

  calculateArea() {
    <span class="hljs-keyword">return</span> (<span class="hljs-built_in">this</span>.base * <span class="hljs-built_in">this</span>.height) / <span class="hljs-number">2</span>;
  }
}
</code></pre>
<p><strong>In this modified code,</strong></p>
<ul>
<li><p>We’ve created subclasses like <code>Circle</code>, <code>Rectangle</code>, and <code>Triangle</code>, each responsible for its own area calculation.</p>
</li>
<li><p>This adheres to the OCP because you can easily add new shapes by creating new subclasses without modifying the existing code.</p>
</li>
<li><p>The <code>Shape</code> class is open for extension but closed for modification.</p>
</li>
</ul>
<h2 id="heading-3-liskov-substitution-principle-lsp"><strong>3. Liskov Substitution Principle (LSP)</strong></h2>
<p>This principle states that <strong>subclasses should be substitutable for their base classes without changing the correctness of the program.</strong> In simpler terms, it means that if you have a base class and you create a subclass from it, you should be able to use the subclass wherever you use the base class, and everything should still work as expected. The subclass should respect the same rules and behaviours as the base class.</p>
<p><strong>Let’s explore this principle further with an example.</strong></p>
<h3 id="heading-violation-of-lsp"><strong>Violation of LSP :</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bird</span> </span>{
    fly() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Bird is flying'</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Sparrow</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Bird</span> </span>{
  <span class="hljs-comment">// Sparrows can fly </span>
}

<span class="hljs-comment">//Violation of LSP</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Penguin</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Bird</span> </span>{
    <span class="hljs-comment">// Penguins don't fly, but we've changed the method name to indicate that.</span>
    canFly() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Penguin cannot fly'</span>);
    }
}

<span class="hljs-keyword">const</span> bird = <span class="hljs-keyword">new</span> Bird();
<span class="hljs-keyword">const</span> sparrow = <span class="hljs-keyword">new</span> Sparrow();
<span class="hljs-keyword">const</span> penguin = <span class="hljs-keyword">new</span> Penguin();

bird.fly(); <span class="hljs-comment">// Outputs: "Bird is flying"</span>
sparrow.fly(); <span class="hljs-comment">// Outputs: "Bird is flying"</span>
penguin.canFly(); <span class="hljs-comment">// Outputs: "Penguin cannot fly"</span>
</code></pre>
<p><strong>In this code,</strong></p>
<ul>
<li><p>The <code>Penguin</code> class violates the Liskov Substitution Principle by changing the method name from <code>fly</code> to <code>canFly</code>.</p>
</li>
<li><p>Consequently, substituting a <code>Penguin</code> object for a <code>Bird</code> object can result in unexpected behaviour due to the inconsistency in method names between the base class and the derived class.</p>
</li>
<li><p>The LSP encourages maintaining a consistent contract when inheriting from base classes, including method names and signatures.</p>
</li>
</ul>
<h3 id="heading-adherence-to-lsp"><strong>Adherence to LSP:</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bird</span> </span>{
    fly() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Bird is flying'</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Sparrow</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Bird</span> </span>{
  <span class="hljs-comment">// Sparrows can fly </span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Penguin</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Bird</span> </span>{
    <span class="hljs-comment">// Penguins don't fly, but this method must be implemented.</span>
    fly() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Penguin cannot fly'</span>);
    }
}

<span class="hljs-keyword">const</span> bird = <span class="hljs-keyword">new</span> Bird();
<span class="hljs-keyword">const</span> sparrow = <span class="hljs-keyword">new</span> Sparrow();
<span class="hljs-keyword">const</span> penguin = <span class="hljs-keyword">new</span> Penguin();

bird.fly(); <span class="hljs-comment">// Outputs: "Bird is flying"</span>
sparrow.fly(); <span class="hljs-comment">// Outputs: "Bird is flying"</span>
penguin.fly(); <span class="hljs-comment">// Outputs: "Penguin cannot fly"</span>
</code></pre>
<p><strong>In this modified code,</strong></p>
<ul>
<li><p>The <code>Penguin</code> class does not violate the LSP because it doesn't change the method's signature (name and parameters) but uses method overriding to provide a behaviour appropriate for penguins, which is to indicate that they cannot fly.</p>
</li>
<li><p>The code still maintains the principle that you can use a subclass (<code>Penguin</code>) wherever the base class (<code>Bird</code>) is expected, and it behaves as expected without unexpected side effects.</p>
</li>
</ul>
<h2 id="heading-4-interface-segregation-principle-isp"><strong>4. Interface Segregation Principle (ISP)</strong></h2>
<p>This principle emphasises that clients (classes that use interfaces) <strong>should not be forced to depend on interfaces they don’t use</strong>. Instead, each client should have access to smaller, client-specific interfaces that contain only the methods and properties relevant to their needs.</p>
<p><strong>Let’s expand on the ISP with an example.</strong></p>
<h3 id="heading-violation-of-isp"><strong>Violation of ISP :</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Machine</span> </span>{
  print() {
    <span class="hljs-comment">// Print something</span>
  }

  scan() {
    <span class="hljs-comment">// Scan something</span>
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Printer</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Machine</span> </span>{
  print() {
    <span class="hljs-comment">// Implementation for printing</span>
  }
}

<span class="hljs-keyword">const</span> myPrinter = <span class="hljs-keyword">new</span> Printer();
myPrinter.print(); <span class="hljs-comment">// This works</span>
myPrinter.scan(); <span class="hljs-comment">// Empty implementation</span>
</code></pre>
<ul>
<li>This code a violation of ISP because it forces the <code>Printer</code> class to implement a method it doesn't need (the <code>scan</code> method) due to its inheritance from the <code>Machine</code> class.</li>
</ul>
<h3 id="heading-adherence-to-isp"><strong>Adherence to ISP :</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Printable</span> </span>{
  print() {
   <span class="hljs-comment">// Implementation for printing</span>
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Scannable</span> </span>{
  scan() {
   <span class="hljs-comment">// Implementation for scanning</span>
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Printer</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Printable</span> </span>{
  print() {
    <span class="hljs-comment">// Implementation for printing</span>
  }
}

<span class="hljs-keyword">const</span> myPrinter = <span class="hljs-keyword">new</span> Printer();
myPrinter.print();
</code></pre>
<p><strong>In modified code,</strong></p>
<ul>
<li><p>We’ve created separate classes (<code>Printable</code> and <code>Scannable</code>) for specific functionalities.</p>
</li>
<li><p>The <code>Printer</code> class implements the <code>Printable</code> class, and it doesn't need to implement the methods it doesn't use, which aligns with the Interface Segregation Principle.</p>
</li>
</ul>
<h2 id="heading-5-dependency-inversion-principle-dip"><strong>5. Dependency Inversion Principle (DIP)</strong></h2>
<p>This principle suggests that <strong>high-level modules should not depend directly on low-level modules but should both depend on abstractions</strong> such as interfaces or abstract classes. Much like the Law of Demeter discussed in a previous <a target="_blank" href="https://theody.hashnode.dev/programming-principles-ii-going-beyond-the-basics">article</a>, this principle fosters loose coupling and flexibility in software design.</p>
<p><strong>Let’s look at an example to further understand DIP</strong></p>
<h3 id="heading-violation-of-dip"><strong>Violation of DIP :</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Engine</span> </span>{
  start() {
    <span class="hljs-comment">// Implementation to start the engine</span>
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.engine = <span class="hljs-keyword">new</span> Engine(); <span class="hljs-comment">// Direct instantiation of a low-level module</span>
  }

  drive() {
    <span class="hljs-built_in">this</span>.engine.start(); <span class="hljs-comment">// Dependence on a specific low-level module</span>
  }
}

<span class="hljs-keyword">const</span> myCar = <span class="hljs-keyword">new</span> Car();
myCar.drive();
</code></pre>
<p><strong>In this code,</strong></p>
<ul>
<li><p>The <code>Car</code> class directly depends on the <code>Engine</code> class by instantiating it.</p>
</li>
<li><p>This is a violation of DIP because the high-level module (<code>Car</code>) should not directly depend on low-level modules (<code>Engine</code>).</p>
</li>
</ul>
<h3 id="heading-adherence-to-dip"><strong>Adherence to DIP :</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Engine</span> </span>{
  start() {
    <span class="hljs-comment">// Implementation to start the engine</span>
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{
  <span class="hljs-keyword">constructor</span>(engine) {
    <span class="hljs-built_in">this</span>.engine = engine;
  }

  drive() {
    <span class="hljs-built_in">this</span>.engine.start(); <span class="hljs-comment">// Depend on an abstraction (Engine) instead of a specific low-level module</span>
  }
}

<span class="hljs-keyword">const</span> engine = <span class="hljs-keyword">new</span> Engine();
<span class="hljs-keyword">const</span> myCar = <span class="hljs-keyword">new</span> Car(engine);
myCar.drive();
</code></pre>
<p><strong>In this modified code,</strong></p>
<ul>
<li><p>The <code>Car</code> class depends on the <code>Engine</code> class through dependency injection.</p>
</li>
<li><p>It no longer directly instantiates the low-level module, and it depends on an abstraction (the <code>Engine</code> class) instead of a specific low-level module, which aligns with the Dependency Inversion Principle.</p>
</li>
</ul>
<h2 id="heading-in-conclusion"><strong>In Conclusion,</strong></h2>
<p>The SOLID principles are essential guidelines in software design and object-oriented programming, encompassing the <strong>Single Responsibility Principle (SRP), Open-Closed Principle (OCP), Liskov Substitution Principle (LSP), Interface Segregation Principle (ISP), and Dependency Inversion Principle (DIP)</strong>. These principles <strong>promote code quality, maintainability, and flexibility</strong>.</p>
<p>By embracing the SOLID principles, developers can create software that is more comprehensible, adaptable, and extensible, leading to enhanced software design and improved overall quality.</p>
<p><a target="_blank" href="https://medium.com/@theody85?source=post_page---post_author_info--d79d587ff271--------------------------------">  
</a></p>
]]></content:encoded></item><item><title><![CDATA[Programming Principles II: Going Beyond the Basics]]></title><description><![CDATA[In our previous article, we delved into fundamental programming principles and practices, including KISS, YAGNI, DRY, Fail Fast, and Clean Code, all crucial for achieving efficient and maintainable code. If you haven’t had a chance to read it, you ca...]]></description><link>https://blog.mycodingnotebook.com/programming-principles-ii-going-beyond-the-basics</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/programming-principles-ii-going-beyond-the-basics</guid><category><![CDATA[General Programming]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[separation of concerns]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Sun, 29 Oct 2023 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737641533670/834a6f34-7293-489a-a845-916f12633d97.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In our previous article, we delved into fundamental programming principles and practices, including <strong>KISS, YAGNI, DRY, Fail Fast, and Clean Code</strong>, all crucial for achieving efficient and maintainable code. If you haven’t had a chance to read it, you can find it <a target="_blank" href="https://theody.hashnode.dev/programming-principles-i-the-basics"><strong>here</strong></a>.</p>
<p>In this article, we will further explore equally essential principles that will enable us to <strong>write code that not only functions effectively but also exhibits elegance, readability, and maintainability</strong>.</p>
<p><strong>Now, let’s delve into it.</strong></p>
<h2 id="heading-1-separation-of-concernssoc"><strong>1. Separation of Concerns(SoC)</strong></h2>
<p>SoC is a fundamental principle that promotes the idea that a software system should be divided into distinct, self-contained modules, each addressing a single concern or responsibility. The primary goal of SoC is to reduce complexity by isolating different aspects of functionality.</p>
<h2 id="heading-heres-an-example-of-the-soc-principle"><strong>Here’s an example of the SoC principle:</strong></h2>
<p>Suppose you’re building a simple web application that allows users to create and manage tasks. In this scenario, the SoC principle can be applied in the following ways:</p>
<ul>
<li><strong>User Interface(UI) Concern:</strong> The user interface is responsible for rendering and interacting with the user. We’ll create an HTML file for the UI and use CSS for styling.</li>
</ul>
<pre><code class="lang-xml"><span class="hljs-comment">&lt;!-- index.html --&gt;</span>
<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">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"styles.css"</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">h1</span>&gt;</span>Task Manager<span class="hljs-tag">&lt;/<span class="hljs-name">h1</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">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"task-description"</span>&gt;</span>Task Description:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <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">id</span>=<span class="hljs-string">"task-description"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter task description"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"add-task"</span>&gt;</span>Add Task<span class="hljs-tag">&lt;/<span class="hljs-name">button</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">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"task-list"</span>&gt;</span>
        <span class="hljs-comment">&lt;!-- Task list will be displayed here --&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">"app.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>&gt;</span>
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-comment">/* styles.css */</span>
body {
    font-family: Arial, sans-serif;
}
<span class="hljs-comment">/* Add more CSS styles as needed */</span>
</code></pre>
<ul>
<li><strong>Business Logic Concern:</strong> The business logic is responsible for handling task management functionality. We’ll create a separate JavaScript file for this.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// app.js</span>
<span class="hljs-keyword">import</span> { addTaskToDataStore, getAllTasksFromDataStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'./data-access'</span>;

<span class="hljs-comment">// Function to add a task </span>
<span class="hljs-keyword">const</span> addTask = <span class="hljs-function">(<span class="hljs-params">description</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> taskDescription = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"task-description"</span>).value;

    <span class="hljs-keyword">if</span> (taskDescription) {
        <span class="hljs-keyword">const</span> task = { <span class="hljs-attr">description</span>: taskDescription, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> };

        <span class="hljs-comment">// Use the data access function to add the task</span>
        addTaskToDataStore(task);

       <span class="hljs-comment">// Other implementation code</span>
    }
};

<span class="hljs-comment">// Function to list tasks </span>
<span class="hljs-keyword">const</span> listTasks = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> tasks = getAllTasksFromDataStore();
    <span class="hljs-keyword">const</span> taskListContainer = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"task-list"</span>);

   <span class="hljs-comment">// Other implementation code</span>
};

<span class="hljs-comment">// Event handling for adding tasks</span>
<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"add-task"</span>).addEventListener(<span class="hljs-string">"click"</span>, addTask);
</code></pre>
<ul>
<li><strong>Data Access Concern:</strong> Data access typically involves communication with a database or storage system to manage data storage and retrieval for our task management application. We’ll create another JavaScript file for this.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// data-access.js </span>

<span class="hljs-comment">// Simple in-memory data store for tasks</span>
<span class="hljs-keyword">const</span> taskData = [];

<span class="hljs-comment">// Function to add a task to the data store</span>
<span class="hljs-keyword">const</span> addTaskToDataStore = <span class="hljs-function">(<span class="hljs-params">task</span>) =&gt;</span> {
    taskData.push(task);
};

<span class="hljs-comment">// Function to retrieve all tasks from the data store</span>
<span class="hljs-keyword">const</span> getAllTasksFromDataStore = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> taskData;
};

<span class="hljs-comment">// Export the functions to be used by the business logic</span>
<span class="hljs-keyword">export</span> { addTaskToDataStore, getAllTasksFromDataStore };
</code></pre>
<p>By following the SoC principle, we’ve separated the concerns in this example:</p>
<ul>
<li><p>The UI is defined in <code>index.html</code> and <code>styles.css</code> files.</p>
</li>
<li><p>The business logic for task management is in the <code>app.js</code> file.</p>
</li>
<li><p>Data access such as saving tasks to the database is handled in <code>data-access.js</code> file.</p>
</li>
</ul>
<p>This separation makes the code more <strong>organized, maintainable, and extensible</strong>, as changes in one concern are less likely to impact other parts of the application.</p>
<h2 id="heading-2-law-of-demeterlod"><strong>2. Law of Demeter(LoD)</strong></h2>
<p>The <strong>Law of Demeter (LoD)</strong>, also known as the <strong>Principle of Least Knowledge</strong>, is a fundamental design principle in object-oriented programming (OOP). Its primary objective is to <strong>enhance the modularity, maintainability, and overall design quality of software</strong>. To better understand the aims of LoD, let’s delve into its key aspects:</p>
<ol>
<li><p><strong>Promoting Modularity</strong></p>
<p> LoD encourages a design approach that <strong>divides software into smaller, more manageable components or modules</strong>. These modules are defined by their distinct responsibilities, enhancing organisation and maintainability.</p>
</li>
<li><p><strong>Reducing Coupling</strong></p>
<p> In software engineering, <strong>“coupling”</strong> indicates the <strong>level of interdependence between different components or objects</strong>. LoD <strong>advocates for loose coupling</strong>, which means that <strong>components or objects should minimise their knowledge of the internal workings of others</strong>. This promotes independence and flexibility within the software architecture.</p>
</li>
<li><p><strong>Promoting Encapsulation</strong></p>
<p> Encapsulation emphasizes the need for <strong>objects to hide their internal details while offering well-defined, consistent interfaces for interactions</strong>. LoD reinforces this concept by discouraging direct access to an object’s internal state. Instead, it encourages interactions with objects through their publicly exposed methods and properties.</p>
</li>
<li><p><strong>Enhancing Maintainability</strong></p>
<p> By following the principles of modularity, reduced coupling and strong encapsulation, you create a codebase that is more manageable and adaptable over time. When components are loosely coupled and well encapsulated, you gain the ability to modify or enhance one part of the system without causing unintended issues in other parts.</p>
</li>
</ol>
<p>In essence, LoD can be succinctly summarised as follows: <strong>“Every unit should only interact with the specific components or objects that it directly relies on, without delving deep into the internals of other units.”</strong></p>
<p>Let’s consider this basic example:</p>
<p><strong>Without LoD Principle:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
  <span class="hljs-keyword">constructor</span>(name) {
    <span class="hljs-built_in">this</span>.name = name;
  }

  getCompanyRevenue(company) {
    <span class="hljs-comment">// Violation of LoD</span>
    <span class="hljs-keyword">return</span> company.finances.getRevenue();
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Company</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.finances = <span class="hljs-keyword">new</span> Finances();
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Finances</span> </span>{
  getRevenue() {
    <span class="hljs-keyword">return</span> <span class="hljs-number">1000000</span>;
  }
}
</code></pre>
<p><strong>In this code,</strong></p>
<ul>
<li><p>The <code>Person</code> class violates the Law of Demeter by directly accessing <code>company.finances.getRevenue()</code>.</p>
</li>
<li><p>The <code>Person</code> class knows too much about the internal structure of the <code>Company</code> and its <code>Finances</code>.</p>
</li>
</ul>
<p><strong>With LoD Principle:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
  <span class="hljs-keyword">constructor</span>(name) {
    <span class="hljs-built_in">this</span>.name = name;
  }

  getCompanyRevenue(company) {
    <span class="hljs-keyword">return</span> company.calculateRevenue();
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Company</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.finances = <span class="hljs-keyword">new</span> Finances();
  }

  calculateRevenue() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.finances.getRevenue();
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Finances</span> </span>{
  getRevenue() {
    <span class="hljs-keyword">return</span> <span class="hljs-number">1000000</span>;
  }
}
</code></pre>
<p><strong>In this refactored code,</strong></p>
<ul>
<li><p>The <code>Person</code> class interacts with the <code>Company</code> through a more limited interface, adhering more closely to the Law of Demeter.</p>
</li>
<li><p>The <code>Person</code> class doesn't directly access the internal details of the <code>Company</code>, but instead, it interacts with the more abstract and encapsulated <code>calculateRevenue</code> method, reducing coupling and making the code more maintainable.</p>
</li>
</ul>
<h2 id="heading-3-tell-dont-asktda"><strong>3. Tell, Don’t Ask(TDA)</strong></h2>
<p>The <strong>Tell, Don’t Ask</strong> <strong>(TDA)</strong> principle <strong>emphasises instructing objects to perform actions rather than querying their state and then making decisions based on that state.</strong> In other words, it encourages you to <strong>“tell”</strong> an object what you want it to do, rather than <strong>“asking”</strong> the object about its internal state and then deciding what action to take based on that information.</p>
<p>This principle aligns with the Law of Demeter principle as both emphasise the benefits of loose coupling and better encapsulation in software design.</p>
<p><strong>Here’s a simple example to illustrate the TDA principle:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Asking (violation of TDA)</span>
<span class="hljs-keyword">if</span> (account.getBalance() &gt;= <span class="hljs-number">100</span>) {
    account.withdraw(<span class="hljs-number">100</span>);
}

<span class="hljs-comment">// Telling (following TDA)</span>
account.withdrawIfSufficientBalance(<span class="hljs-number">100</span>);
</code></pre>
<ul>
<li><p><strong>In the first example,</strong> the code queries the <code>account</code> object for its balance and then decides to withdraw money based on that information, which can lead to external code making decisions for the account.</p>
</li>
<li><p>In the second example, the code directly tells the <code>account</code> to withdraw money if it has a sufficient balance, encapsulating the logic within the account itself and following the TDA principle.</p>
</li>
</ul>
<h2 id="heading-4-law-of-least-astonishmentlola"><strong>4. Law of Least Astonishment(LoLA)</strong></h2>
<p>The <strong>Law of Least Astonishment (LoLA)</strong>, also referred to as the <strong>Principle of Least Astonishment (POLA)</strong>, is a fundamental design principle that focuses on <strong>creating software and user interfaces that behave in a manner that is the least surprising or astonishing to both users and developers.</strong> The primary aim of LoLA is to minimise unexpected or counterintuitive behaviour, resulting in more user-friendly and predictable software.</p>
<p>LoLA is particularly significant in User Interface (UI) design, as it plays a crucial role in ensuring that UI elements and interactions align with users’ common expectations.</p>
<p><strong>Here’s some examples of how LoLA applies to User Interface design:</strong></p>
<ol>
<li><h3 id="heading-button-behaviour"><strong>Button Behaviour:</strong></h3>
<ul>
<li><p><strong>Expected Behaviour:</strong> In a well-designed user interface, buttons should visually appear as clickable elements, and when clicked, they should perform an action or trigger an event.</p>
</li>
<li><p><strong>Violating LoLA:</strong> If a button doesn't appear clickable or fails to respond when clicked, it would astonish users and deviate from their expected interaction with UI elements.</p>
</li>
</ul>
</li>
</ol>
<ol start="2">
<li><h3 id="heading-navigation-consistency"><strong>Navigation Consistency:</strong></h3>
</li>
</ol>
<ul>
<li><p><strong>Expected Behaviour:</strong> Navigation menus or elements should follow established conventions. For instance, users anticipate that clicking a website's logo typically returns them to the homepage, and clicking a navigation menu item leads to the corresponding section or page.</p>
</li>
<li><p><strong>Violating LoLA:</strong> If a website's logo unexpectedly takes users to an unrelated page or the navigation menu items behave inconsistently, it would surprise users and make navigation less intuitive.</p>
</li>
</ul>
<ol start="3">
<li><h3 id="heading-iconography"><strong>Iconography:</strong></h3>
</li>
</ol>
<ul>
<li><p><strong>Expected Behaviour:</strong> Icons should employ widely recognised symbols and representations. For example, a trash can icon usually signifies a delete action, and a floppy disk icon implies saving.</p>
</li>
<li><p><strong>Violating LoLA:</strong> Using non-standard or unconventional icons can bewilder users, as they might not easily understand the intended actions associated with the icons.</p>
</li>
</ul>
<p>In each of these examples, violating the Law of Least Astonishment would result in behaviours that are counterintuitive and surprising. Adhering to LoLA means designing software and user interfaces with users’ expectations in mind, ensuring that interactions and behaviours align with what users commonly anticipate.</p>
<h2 id="heading-in-summary"><strong>In Summary,</strong></h2>
<p>In this article, we’ve explored key programming principles: <strong>Separation of Concerns (SoC), Law of Demeter (LoD), Tell, Don’t Ask (TDA), and Law of Least Astonishment (LoLA).</strong> These principles form the bedrock of clean, maintainable code, emphasising modular, well-encapsulated design and user-friendly interfaces.</p>
<p>In the <a target="_blank" href="https://theody.hashnode.dev/programming-principles-iii-writing-solid-code">next article</a> in this series, we’ll delve into the SOLID principles, a set of guidelines that take software design to the next level. Stay tuned as we uncover how SOLID principles enhance extensibility and adaptability in software architecture, ensuring your code remains robust and flexible over time.</p>
]]></content:encoded></item><item><title><![CDATA[Programming Principles I: The Basics]]></title><description><![CDATA[In the field of software engineering, collaboration on codebases is a regular and integral part of our work. To ensure smooth collaboration and mitigate conflicts, it is essential to lay down a foundation of fundamental principles and best practices ...]]></description><link>https://blog.mycodingnotebook.com/programming-principles-i-the-basics</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/programming-principles-i-the-basics</guid><category><![CDATA[General Programming]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[YAGNI]]></category><category><![CDATA[KISS Principle]]></category><category><![CDATA[DRY Principle (Don't Repeat Yourself)]]></category><category><![CDATA[clean code]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Wed, 25 Oct 2023 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737639635086/1af28e16-ef1d-4d2a-87e9-397b2b917ad8.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the field of software engineering, collaboration on codebases is a regular and integral part of our work. To ensure smooth collaboration and mitigate conflicts, it is essential to lay down a foundation of fundamental principles and best practices that serve as a guiding framework for all involved.</p>
<p>By steadfastly adhering to these guidelines, you can distinguish yourself as a skilled and proficient software engineer.</p>
<p><strong>Without further delay, let’s dive right into them.</strong></p>
<h2 id="heading-1-kisskeep-it-simple-stupid"><strong>1. KISS(Keep It Simple, Stupid)</strong></h2>
<p>In software development, adhering to the KISS principle means writing code that is <strong>straightforward</strong>, <strong>easy to read</strong>, and <strong>minimizes unnecessary complexity</strong>. It involves avoiding overly complex algorithms, convoluted logic, and excessive use of features or technologies. By keeping code simple, developers can reduce the chances of bugs, improve maintainability, and enhance collaboration within development teams.</p>
<p><strong>Let’s consider an illustration of the KISS principle in the context of creating a function to find the maximum number in an array of integers.</strong></p>
<h3 id="heading-without-the-kiss-principle"><strong>Without the KISS Principle:</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">findMaxNumber</span>(<span class="hljs-params">numbers</span>) </span>{
    <span class="hljs-keyword">let</span> max = <span class="hljs-built_in">Number</span>.NEGATIVE_INFINITY; <span class="hljs-comment">// Initialize with a very low value.</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; numbers.length; i++) {
        <span class="hljs-keyword">if</span> (numbers[i] &gt; max) {
            max = numbers[i];
        }
    }
    <span class="hljs-keyword">return</span> max;
}
</code></pre>
<p><strong>In this example,</strong></p>
<ul>
<li><p>The function uses a loop and an initial <strong>“max”</strong> value set to a very low number.</p>
</li>
<li><p>It is a bit more complex, and the use of <strong>Number.NEGATIVE_INFINITY</strong> may be confusing.</p>
</li>
</ul>
<h3 id="heading-with-kiss-principle"><strong>With KISS Principle:</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">findMaxNumber</span>(<span class="hljs-params">numbers</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.max(...numbers);
}
</code></pre>
<p><strong>In this simplified version,</strong></p>
<ul>
<li><p>The <strong>Math.max</strong> function is used to find the maximum number in the array.</p>
</li>
<li><p>The <strong>spread operator</strong> <code>…</code> is employed to pass the array elements as separate arguments to the Math.max function.</p>
</li>
<li><p>This approach is simpler, more concise, and easier to understand.</p>
</li>
</ul>
<p>By applying the KISS principle in this case, we’ve achieved the same result with a much simpler and more straightforward solution. This makes the code easier to read, maintain, and less prone to errors</p>
<h2 id="heading-2-yagniyou-arent-gonna-need-it"><strong>2. YAGNI(You Aren’t Gonna Need It)</strong></h2>
<p>This principle advises <strong>against adding functionality or features to a system until they are proven to be necessary</strong>. In other words, don’t implement things in anticipation of future needs; instead, implement only what is currently needed.</p>
<p>The YAGNI principle is closely related to the KISS principle. However, YAGNI <strong>goes a step further by discouraging the addition of features or code that have not been explicitly requested or validated by the current requirements.</strong></p>
<h2 id="heading-3-dry-dont-repeat-yourself"><strong>3. DRY ( Don’t Repeat Yourself)</strong></h2>
<p>The <strong>DRY</strong> principle is a fundamental concept that encourages developers to <strong>avoid duplicating code</strong>. It promotes code reusability and maintainability by advocating for the creation of abstractions, functions, or modules to encapsulate common functionality. The primary goal is to <strong>reduce redundancy</strong> in your codebase, making it easier to manage and maintain.</p>
<p><strong>Let’s look at a basic calculator example to see how the DRY principle works.</strong></p>
<h3 id="heading-without-dry-principle"><strong>Without DRY Principle:</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params">a, b</span>) </span>{
   <span class="hljs-keyword">return</span> a + b;
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">subtract</span>(<span class="hljs-params">a, b</span>) </span>{
   <span class="hljs-keyword">return</span> a - b;
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">multiply</span>(<span class="hljs-params">a, b</span>) </span>{
   <span class="hljs-keyword">return</span> a * b;
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">divide</span>(<span class="hljs-params">a, b</span>) </span>{
   <span class="hljs-keyword">return</span> a / b;
}

<span class="hljs-keyword">const</span> result1 = add(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Result 1 (Addition):"</span>, result1);
<span class="hljs-keyword">const</span> result2 = subtract(<span class="hljs-number">8</span>, <span class="hljs-number">2</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Result 2 (Subtraction):"</span>, result2);
<span class="hljs-keyword">const</span> result3 = multiply(<span class="hljs-number">4</span>, <span class="hljs-number">6</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Result 3 (Multiplication):"</span>, result3);
<span class="hljs-keyword">const</span> result4 = divide(<span class="hljs-number">9</span>, <span class="hljs-number">3</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Result 4 (Division):"</span>, result4);
</code></pre>
<p><strong>In this example,</strong></p>
<ul>
<li><p>We have separate functions for each operation (add, subtract, multiply, divide).</p>
</li>
<li><p>This approach leads to code duplication because each function essentially performs a similar task of taking two numbers and performing a specific operation.</p>
</li>
</ul>
<h3 id="heading-with-dry-principle"><strong>With Dry Principle:</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculate</span>(<span class="hljs-params">a, b, operation</span>) </span>{
   <span class="hljs-keyword">switch</span> (operation) {
       <span class="hljs-keyword">case</span> <span class="hljs-string">"add"</span>:
           <span class="hljs-keyword">return</span> a + b;
       <span class="hljs-keyword">case</span> <span class="hljs-string">"subtract"</span>:
           <span class="hljs-keyword">return</span> a - b;
       <span class="hljs-keyword">case</span> <span class="hljs-string">"multiply"</span>:
           <span class="hljs-keyword">return</span> a * b;
       <span class="hljs-keyword">case</span> <span class="hljs-string">"divide"</span>:
           <span class="hljs-keyword">return</span> a / b;
       <span class="hljs-keyword">default</span>:
           <span class="hljs-keyword">return</span> <span class="hljs-string">"Invalid operation"</span>;
   }
}

<span class="hljs-keyword">const</span> result1 = calculate(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>, <span class="hljs-string">"add"</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Result 1 (Addition):"</span>, result1);
<span class="hljs-keyword">const</span> result2 = calculate(<span class="hljs-number">8</span>, <span class="hljs-number">2</span>, <span class="hljs-string">"subtract"</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Result 2 (Subtraction):"</span>, result2);
<span class="hljs-keyword">const</span> result3 = calculate(<span class="hljs-number">4</span>, <span class="hljs-number">6</span>, <span class="hljs-string">"multiply"</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Result 3 (Multiplication):"</span>, result3);
<span class="hljs-keyword">const</span> result4 = calculate(<span class="hljs-number">9</span>, <span class="hljs-number">3</span>, <span class="hljs-string">"divide"</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Result 4 (Division):"</span>, result4);
</code></pre>
<p><strong>In this second example,</strong></p>
<ul>
<li><p>we have reduced code duplication by introducing a <strong>single function</strong> called calculate.</p>
</li>
<li><p>This function takes <strong>three parameters</strong>: <strong>two numbers</strong> and an <strong>“operation”</strong> parameter.</p>
</li>
<li><p>The <code>operation</code> parameter is used to specify which arithmetic operation to perform.</p>
</li>
<li><p>This single function can handle a range of operations, making the code more efficient and maintaining the DRY principle.</p>
</li>
</ul>
<h2 id="heading-4-fail-fast"><strong>4. Fail Fast</strong></h2>
<p>The <strong>“Fail Fast”</strong> principle suggests <strong>detecting</strong> <strong>and</strong> <strong>reporting errors as early as possible in a program’s execution rather than allowing them to propagate and potentially cause more complex issues later</strong>. By identifying problems early, you can enhance the <strong>robustness</strong> and <strong>maintainability</strong> of your software.</p>
<p><strong>Let’s illustrate this principle with an example related to input validation:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateSquareRoot</span>(<span class="hljs-params">number</span>) </span>{
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> number !== <span class="hljs-string">'number'</span> || number &lt;= <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Input must be a positive number"</span>);
    }
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.sqrt(number);
}

<span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> result = calculateSquareRoot(<span class="hljs-number">-4</span>);
    <span class="hljs-built_in">console</span>.log(result);
} <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(error.message);
}
</code></pre>
<p><strong>In this example,</strong></p>
<ul>
<li><p>The <code>calculateSquareRoot</code> function checks whether the input is a positive number before performing the square root calculation.</p>
</li>
<li><p>If the input is invalid, it throws an error immediately, ensuring that the code doesn't continue to execute under uncertain or faulty conditions.</p>
</li>
</ul>
<h2 id="heading-5-clean-code"><strong>5. Clean Code</strong></h2>
<p><strong>Clean code</strong> is a term used to <strong>describe a source code that is well-organised, easy to read, and maintainable.</strong> While the principles mentioned earlier (KISS, YAGNI, and DRY) contribute to achieving these objectives, let’s delve deeper into the characteristics that define clean code, uncovering additional strategies for achieving this goal.</p>
<ol>
<li><p><strong>Descriptive Naming:</strong> Assign meaningful names to variables, functions, and classes that accurately convey their intended purpose. <strong>For instance,</strong> instead of <code>const x = 20</code>, use <code>const userAge = 20</code>.</p>
</li>
<li><p><strong>Consistent Naming Conventions:</strong> Adhere to consistent naming conventions throughout your codebase. <strong>For instance,</strong> if your project uses camelCase for variable names, ensure that this convention is consistently maintained in all parts of the code.</p>
</li>
<li><p><strong>Comments for Clarity:</strong> Include comments for explanations where necessary without overdoing it.</p>
</li>
<li><p><strong>Consistent Formatting:</strong> Maintain a uniform and reader-friendly coding style by using appropriate indentation and spacing throughout the code.</p>
</li>
<li><p><strong>Modular Structure:</strong> Organise code into self-contained modules or functions, with each one dedicated to a specific responsibility. For instance, a user authentication module should not also manage user profile updates.</p>
</li>
<li><p><strong>Readability Over Cleverness:</strong> Prioritise readability over clever optimisations. For instance, opt for multiple lines of code to enhance clarity and maintainability rather than relying on complex, condensed one-liners.</p>
</li>
<li><p><strong>Testability:</strong> Structure code to be easily testable with unit and integration tests.</p>
</li>
<li><p><strong>Error Handling:</strong> Incorporate effective error handling and exceptions in your code. For instance, use try-catch blocks to handle exceptions, providing clear error messages.</p>
</li>
</ol>
<h2 id="heading-in-conclusion"><strong>In Conclusion,</strong></h2>
<p>This article has laid a solid foundation, exploring key programming principles and practices such as <strong>DRY, KISS, YAGNI, Fail Fast,</strong> and <strong>Clean Code</strong>, which are essential for <strong>efficient</strong> and <strong>maintainable code</strong>.</p>
<p>However, our journey into the world of programming principles doesn’t end here. In the <a target="_blank" href="https://theody.hashnode.dev/programming-principles-ii-going-beyond-the-basics">next article</a>, we will take a deeper dive into other principles including <strong>SoC, LoD, TDA,</strong> and <strong>LoLA</strong>. These will further enrich your understanding and empower you to write code that not only works but is elegant.</p>
]]></content:encoded></item><item><title><![CDATA[Why the Hype About React, Vue and Angular? — Part 2]]></title><description><![CDATA[This is the sequel to an initial article that aimed to shed light on the reasons fueling the hype around React, Vue, Angular, and SPA (Single Page Application) frameworks in general.
In the first article, we discussed how frameworks and libraries lik...]]></description><link>https://blog.mycodingnotebook.com/why-the-hype-about-react-vue-and-angular-part-2</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/why-the-hype-about-react-vue-and-angular-part-2</guid><category><![CDATA[Single Page Application]]></category><category><![CDATA[multi page application]]></category><category><![CDATA[React]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Vue.js]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Thu, 12 Oct 2023 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737638556126/58a71c95-2a59-4c62-8bb1-1a9f2e6fb9a1.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is the sequel to an initial article that aimed to shed light on the reasons fueling the hype around <strong>React, Vue, Angular, and SPA (Single Page Application)</strong> frameworks in general.</p>
<p>In the first article, we discussed how frameworks and libraries like <strong>React, Vue, and Angular</strong> are part of a collection of tools used for building <strong>Single Page Applications (SPAs)</strong>. We started by explaining how <strong>traditional websites</strong>, also known as <strong>Multi-Page Applications (MPAs)</strong>, work, and then we transitioned into understanding the mechanics of SPAs. If you haven’t read the first part, you can find it <a target="_blank" href="https://theody.hashnode.dev/why-the-hype-about-react-vue-and-angular-part-1"><strong>here</strong></a><strong>.</strong></p>
<p>In this second part, we will thoroughly explore the pros and cons of each approach in a clear and simple manner. This will empower you to make informed decisions when building an application so you can confidently choose between the traditional approach and SPA tools like React, Vue, and Angular.</p>
<p><strong>We’ll start off by looking at the pros and cons of traditional websites or MPAs.</strong></p>
<h2 id="heading-pros-of-traditional-websites-mpas"><strong>Pros of Traditional Websites (MPAs):</strong></h2>
<ol>
<li><p><strong>SEO-friendly</strong></p>
<p> SEO, or Search Engine Optimization, is a collection of techniques and strategies aimed at enhancing a website’s visibility and ranking in search engine results to attract more traffic. Since users typically click on the first results they see, the primary aim of SEO is to make a website more appealing and relevant to search engines like Google, Yahoo and the others.</p>
<p> <strong>An SEO-friendly website</strong> is one that is <strong>well-structured</strong> and <strong>designed</strong> to <strong>optimise its visibility and ranking in search engine results</strong>.Traditional websites tend to excel in search engine rankings because each page has a unique content, URL, clear title and navigation, making it easier for search engine crawlers to index and display them in search results.</p>
</li>
<li><p><strong>Faster Initial Load</strong></p>
<p> Traditional websites typically consist of static HTML pages with fewer external requests for resources such as scripts. This streamlined structure places a lighter load on web servers during the initial page request, enabling rapid delivery of pre-rendered pages to the user’s browser. Consequently, this results in a faster initial loading.</p>
</li>
<li><p><strong>Less Complex Development</strong></p>
<p> Developing traditional websites is often simpler, especially for smaller projects. You can use basic HTML, CSS, and JavaScript to create effective MPAs.</p>
</li>
</ol>
<h2 id="heading-cons-of-traditional-websites-mpas"><strong>Cons of Traditional Websites (MPAs):</strong></h2>
<ol>
<li><p><strong>Slower Subsequent Page Loads</strong></p>
<p> While the initial page load may be fast, navigating to subsequent pages often requires reloading the entire page, resulting in slower performance.</p>
</li>
<li><p><strong>Reduced User Experience and Interactivity</strong></p>
<p> Traditional websites often necessitate users to navigate to different pages, leading to page refreshes that can disrupt the user experience and slow down interaction. Additionally, traditional websites may lack the level of interactivity and real-time features provided by modern web applications.</p>
</li>
<li><p><strong>Higher Server Load</strong></p>
<p> Each page request involves server-side processing and data transfer, potentially resulting in increased server load and operational costs.</p>
</li>
</ol>
<p><strong>Now, let’s look at the Pros and cons of SPAs.</strong></p>
<h2 id="heading-pros-of-spas"><strong>Pros of SPAs:</strong></h2>
<ol>
<li><p><strong>Faster Subsequent Page Loads</strong></p>
<p> SPAs can provide a faster user experience after the initial load because they only update the content that has changed, rather than reloading the entire page.</p>
</li>
<li><p><strong>Smooth User Experience and Interactivity</strong></p>
<p> SPAs offer a smoother and more app-like user experience with enhanced interactivity. They can dynamically update content without full page refreshes, enabling features like real-time data updates, interactive forms, and responsive user interfaces. This contributes to a highly engaging and interactive user experience.</p>
</li>
<li><p><strong>Reduced Server Load</strong></p>
<p> SPAs can reduce the load on web servers because they request data rather than entire pages. This can lead to cost savings and improved server performance.</p>
</li>
</ol>
<h2 id="heading-cons-of-spas"><strong>Cons of SPAs:</strong></h2>
<ol>
<li><p><strong>Slower Initial Load</strong></p>
<p> SPAs often experience a slower initial load due to the need to load a larger bundle of JavaScript and other assets. This can impact the bounce rate, which measures the percentage of visitors who quickly exit a page without further interaction or exploring other site pages. Consequently, it can impact overall performance and user experience.</p>
</li>
<li><p><strong>SEO Challenges</strong></p>
<p> SPAs heavily rely on JavaScript for dynamic content rendering, which can pose indexing difficulties for search engine crawlers. This may lead to content not being correctly indexed or ranked, potentially impacting SEO. Additionally, the higher bounce rate as a result of the slower initial page load is considered by search engines when ranking websites.</p>
</li>
<li><p><strong>Complex Development</strong></p>
<p> Developing SPAs can be more complex, often demanding the use of front-end frameworks or libraries, routing systems, state management, and additional tools. This complexity can lead to longer development times.</p>
</li>
</ol>
<h2 id="heading-summarized-comparison-of-mpas-and-spas"><strong>Summarized Comparison of MPAs and SPAs</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737639133214/772ccaaa-5a61-4320-85fd-913890e74bc2.webp" alt class="image--center mx-auto" /></p>
<h2 id="heading-in-conclusion"><strong>In conclusion,</strong></h2>
<p>The choice between traditional websites (MPAs) and Single Page Applications (SPAs) hinges on the specific needs and goals of your project. <strong>Traditional websites</strong> excel in areas like SEO-friendliness and faster initial loads, offering simplicity for smaller projects. <strong>On the other hand,</strong> SPAs deliver a dynamic and interactive user experience, ideal for certain modern web applications, but they may confront SEO challenges and increased complexity.</p>
<p>It’s noteworthy that the challenges associated with SPAs have not gone unaddressed. The web development community has made various attempts to combat these issues. Frameworks such as NextJS, NuxtJs, SvelteKit and Gatsby have emerged to improve SEO and initial load times for SPAs by introducing Server-Side Rendering (SSR) and React Server Components. Staying informed about these evolving solutions is crucial for delivering top-tier web experiences that align with your project’s goals.</p>
]]></content:encoded></item><item><title><![CDATA[Why the Hype About React, Vue, and Angular? — Part 1]]></title><description><![CDATA[Introduction
Entering the world of tech as a web developer, you’ll quickly notice a recurring theme: job postings and advice from seasoned developers often mention the importance of mastering tools like React, Vue, and Angular. It’s clear that to thr...]]></description><link>https://blog.mycodingnotebook.com/why-the-hype-about-react-vue-and-angular-part-1</link><guid isPermaLink="true">https://blog.mycodingnotebook.com/why-the-hype-about-react-vue-and-angular-part-1</guid><category><![CDATA[Single Page Application]]></category><category><![CDATA[multi page application]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[React]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Vue.js]]></category><dc:creator><![CDATA[MyCodingNotebook]]></dc:creator><pubDate>Tue, 10 Oct 2023 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737633021870/48925c07-1ea7-4b55-b895-a5e3c35cb939.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<p>Entering the world of tech as a web developer, you’ll quickly notice a recurring theme: job postings and advice from seasoned developers often mention the importance of mastering tools like React, Vue, and Angular. It’s clear that to thrive in the tech industry, these are skills you’ll need to acquire. However, what are these tools precisely, and what are their functions?</p>
<p><strong>React</strong>, <strong>Vue</strong>, and <strong>Angular</strong> represent just a few examples of JavaScript frameworks and libraries used extensively for building <strong>Single Page Applications (SPAs)</strong>. They’re not alone; there are a host of other tools like <strong>Ember.js, Svelte, Nuxt, Aurelia</strong>, and more, each serving a similar purpose.</p>
<h2 id="heading-now-lets-delve-into-what-spas-are"><strong>Now, let’s delve into what SPAs are.</strong></h2>
<p><strong>Single Page Applications (SPAs)</strong> are a category of web application that operates entirely on a single web page. Unlike traditional websites that load numerous separate HTML pages from the server, SPAs take a different approach. They begin by loading a single HTML page, and as users interact with the application, its content undergoes dynamic updates.</p>
<p>While this might initially seem a bit complex, stick with me, and it will become much clearer.</p>
<p>To fully grasp the concept of SPAs, it’ll be helpful to begin by understanding how <strong>traditional websites</strong>, also known as <strong>Multi-Page Applications (MPAs)</strong> work.</p>
<h2 id="heading-multi-page-applications-mpas"><strong>Multi-Page Applications (MPAs)</strong></h2>
<p><strong>A Multi-Page Application</strong> or <strong>a traditional website</strong> is a website built using fundamental web technologies, including HTML, CSS and plain JavaScript without the utilization of any additional frameworks or libraries.</p>
<p>Now, several key components and processes come together to make a traditional website accessible and functional. Here’s a simplified overview of these processes:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737633215253/a3d6eb38-2edd-4e44-ad16-fec6484d611b.webp" alt class="image--center mx-auto" /></p>
<ol>
<li><p><strong>Domain Name:</strong> A user would enter the domain name(e.g. <a target="_blank" href="http://www.example.com">www.example.com</a>) of the website into their web browser’s address bar.</p>
</li>
<li><p><strong>DNS (Domain Name System):</strong> The domain name is resolved to an <a target="_blank" href="https://en.wikipedia.org/wiki/IP_address"><strong>Internet Protocol(IP)</strong></a> address by the Domain Name System. The IP address identifies the server where the website’s files are hosted.</p>
</li>
<li><p><strong>HTTP Request:</strong> An HTTP (Hypertext Transfer Protocol) request is sent to the identified web server associated with that domain. This request asks the server to send the website’s content back to the user’s browser.</p>
</li>
<li><p><strong>Web Server:</strong> The web server receives the HTTP request, processes it, and determines which files need to be sent to the user’s browser.</p>
</li>
<li><p><strong>Content Generation:</strong> The server assembles the HTML, CSS, JavaScript, and other assets into a complete web page in a process known as Server-Side Rendering. This process often involves fetching data from databases or external APIs if necessary.</p>
</li>
<li><p><strong>HTTP Response:</strong> The web server sends the fully assembled web page along with any associated assets like stylesheets and scripts back to the user’s browser as an HTTP response.</p>
</li>
<li><p><strong>Rendering:</strong> Upon receiving the HTTP response which has a significant portion already pre-rendered on the server, the user’s web browser interprets the HTML, CSS, and JavaScript to complete the rendering of the web page. It displays the content, formatting, and interactive elements to the user.</p>
</li>
<li><p><strong>User Interaction:</strong> The user can interact with the website by clicking links to navigate to a different page, submitting a form, and performing various actions.</p>
</li>
<li><p><strong>Repeat:</strong> These interactions trigger another full-page request to the server. The browser sends new HTTP requests to the server, and the server responds with the requested content. Each page load requires a full round trip to the server.</p>
</li>
</ol>
<h2 id="heading-now-lets-compare-that-to-the-workings-of-an-spa"><strong>Now, let’s compare that to the workings of an SPA.</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737633533988/b2c187f5-e54c-4fbd-82f6-2fe28046b9c5.webp" alt class="image--center mx-auto" /></p>
<p>Like traditional websites, the process starts with the resolution of the website’s domain name into an IP address by the DNS. Subsequently, an HTTP request is made to the server and this is where it gets interesting;</p>
<ol>
<li><p><strong>Server Response:</strong> In an SPA, the initial HTML page is often minimal, acting as a shell or a template. The server sends this minimal HTML page along with JavaScript resources that contain the application logic.</p>
</li>
<li><p><strong>Client-Side Rendering:</strong> The browser then downloads and executes the JavaScript files which may include the libraries and frameworks like React, Vue or Angular in addition to the initial HTML, to set up the SPA.</p>
</li>
<li><p><strong>User Interaction:</strong> When the user interacts with the SPA, such as scrolling through a list of items, navigating to a different page or submitting a form, the application uses AJAX(Asynchronous JavaScript and XML) requests to communicate with the server. Unlike traditional websites, where each user action might trigger a full-page reload and request for an entirely new HTML page, SPAs strategically use AJAX to fetch or send data without necessitating the reload of the entire page. This means that SPAs, instead of requesting complete HTML pages, selectively fetch only the specific data or content needed for the current user interaction.</p>
</li>
<li><p><strong>Client-Side Routing:</strong> SPAs implement client-side routing, meaning that navigation within the application doesn’t require requesting new pages from the server. Instead, the routing is managed on the client side by manipulating the URL and dynamically updating the content. This approach eliminates the necessity for full-page requests.</p>
</li>
<li><p><strong>State Management:</strong> SPAs use client-side state management to keep track of the application’s data and UI state. This approach enables SPAs to efficiently update and re-render only the components or sections of the page that have changed, eliminating the need to refresh the entire page.</p>
</li>
</ol>
<h2 id="heading-in-summary"><strong>In Summary,</strong></h2>
<p>The key distinction between a traditional website and a Single Page Application (SPA) lies in their handling of user interactions. <strong>Traditional websites</strong> depend on full-page requests and server-rendered HTML for every user interaction, leading to complete page reloads. <strong>In contrast, an SPA follows a different paradigm:</strong> it initially loads a minimal page, retrieves and dynamically renders content on the client side, and manages subsequent interactions without resorting to full-page refreshes.</p>
<p>This approach offers several advantages, including a smoother and more responsive user experience, reduced server load, and enhanced performance. It particularly benefits web applications characterised by frequent user interactions and real-time updates, where the ability to fetch and display only the necessary data on-demand contributes to a more efficient and enjoyable user journey.</p>
<p>While reading this article, you might be leaning towards SPAs as the apparent choice for every application. But hold on, there’s more to consider! Find the sequel <a target="_blank" href="https://theody.hashnode.dev/why-the-hype-about-react-vue-and-angular-part-2"><strong>here</strong></a>, where I delve into the pros and cons of each approach.</p>
]]></content:encoded></item></channel></rss>