<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ optimization - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ optimization - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 27 May 2026 16:21:27 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/optimization/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Optimize Your Docker Build Cache & Cut Your CI/CD Pipeline Times by 80% ]]>
                </title>
                <description>
                    <![CDATA[ Every developer has been there. You push a one-line fix, grab your coffee, and wait. And wait. Twelve minutes later, your Docker image finishes rebuilding from scratch because something about the cach ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-optimize-your-docker-build-cache/</link>
                <guid isPermaLink="false">69bb1e218c55d6eefb64955f</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Docker ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Balajee Asish Brahmandam ]]>
                </dc:creator>
                <pubDate>Wed, 18 Mar 2026 21:50:25 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/9a5ca46f-c571-4d38-90b5-3c6d7d22c00f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Every developer has been there. You push a one-line fix, grab your coffee, and wait. And wait. Twelve minutes later, your Docker image finishes rebuilding from scratch because something about the cache broke again.</p>
<p>I spent a good chunk of last year debugging slow Docker builds across multiple teams. The pattern was always the same: builds that should take two minutes were eating up fifteen, and nobody knew why. The fix turned out to be surprisingly systematic once I understood what was actually happening under the hood.</p>
<p>This guide walks you through exactly how to fix slow Docker builds, step by step. We'll start with how the cache actually works, then tear apart the most common mistakes, and finish with production-ready patterns you can copy into your projects today.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#heading-how-docker-build-cache-actually-works">How Docker Build Cache Actually Works</a></p>
<ul>
<li><p><a href="#heading-how-cache-keys-are-computed">How Cache Keys Are Computed</a></p>
</li>
<li><p><a href="#heading-the-cache-chain-rule">The Cache Chain Rule</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-how-to-identify-common-cache-busting-mistakes">How to Identify Common Cache-Busting Mistakes</a></p>
<ul>
<li><p><a href="#heading-mistake-1-copying-everything-too-early">Mistake 1: Copying Everything Too Early</a></p>
</li>
<li><p><a href="#heading-mistake-2-not-separating-dependency-files">Mistake 2: Not Separating Dependency Files</a></p>
</li>
<li><p><a href="#heading-mistake-3-using-add-instead-of-copy">Mistake 3: Using ADD Instead of COPY</a></p>
</li>
<li><p><a href="#heading-mistake-4-splitting-apt-get-update-and-install">Mistake 4: Splitting apt-get update and install</a></p>
</li>
<li><p><a href="#heading-mistake-5-embedding-timestamps-or-git-hashes-too-early">Mistake 5: Embedding Timestamps or Git Hashes Too Early</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-how-to-structure-your-dockerfile-for-maximum-cache-reuse">How to Structure Your Dockerfile for Maximum Cache Reuse</a></p>
<ul>
<li><p><a href="#heading-step-1-apply-the-dependency-first-pattern">Step 1: Apply the Dependency-First Pattern</a></p>
</li>
<li><p><a href="#heading-step-2-add-an-aggressive-dockerignore">Step 2: Add an Aggressive .dockerignore</a></p>
</li>
<li><p><a href="#heading-step-3-use-multi-stage-builds">Step 3: Use Multi-Stage Builds</a></p>
</li>
<li><p><a href="#heading-step-4-order-layers-by-change-frequency">Step 4: Order Layers by Change Frequency</a></p>
</li>
<li><p><a href="#heading-step-5-use-buildkit-mount-caches">Step 5: Use BuildKit Mount Caches</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-how-to-set-up-cicd-cache-backends">How to Set Up CI/CD Cache Backends</a></p>
<ul>
<li><p><a href="#heading-option-a-registry-based-cache">Option A: Registry-Based Cache</a></p>
</li>
<li><p><a href="#heading-option-b-github-actions-cache">Option B: GitHub Actions Cache</a></p>
</li>
<li><p><a href="#heading-option-c-s3-or-cloud-storage">Option C: S3 or Cloud Storage</a></p>
</li>
<li><p><a href="#heading-option-d-local-cache-with-persistent-runners">Option D: Local Cache with Persistent Runners</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-how-to-implement-advanced-cache-patterns">How to Implement Advanced Cache Patterns</a></p>
<ul>
<li><p><a href="#heading-parallel-build-stages">Parallel Build Stages</a></p>
</li>
<li><p><a href="#heading-cache-warming-for-feature-branches">Cache Warming for Feature Branches</a></p>
</li>
<li><p><a href="#heading-selective-cache-invalidation-with-build-args">Selective Cache Invalidation with Build Args</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-how-to-measure-your-improvements">How to Measure Your Improvements</a></p>
<ul>
<li><p><a href="#heading-the-four-scenarios-to-benchmark">The Four Scenarios to Benchmark</a></p>
</li>
<li><p><a href="#heading-real-world-before-and-after-numbers">Real-World Before and After Numbers</a></p>
</li>
<li><p><a href="#heading-how-to-check-cache-hit-rates">How to Check Cache Hit Rates</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-complete-optimized-dockerfile-examples">Complete Optimized Dockerfile Examples</a></p>
<ul>
<li><p><a href="#heading-nodejs-full-stack-app">Node.js Full-Stack App</a></p>
</li>
<li><p><a href="#heading-python-fastapi-app">Python FastAPI App</a></p>
</li>
<li><p><a href="#heading-go-microservice">Go Microservice</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-troubleshooting-guide">Troubleshooting Guide</a></p>
</li>
<li><p><a href="#heading-quick-reference-checklist">Quick-Reference Checklist</a></p>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along, you'll need:</p>
<ul>
<li><p>A working Docker installation (Docker Desktop or Docker Engine 20.10+)</p>
</li>
<li><p>Basic comfort with writing Dockerfiles</p>
</li>
<li><p>Access to a CI/CD system like GitHub Actions, GitLab CI, or Jenkins</p>
</li>
</ul>
<h2 id="heading-how-docker-build-cache-actually-works">How Docker Build Cache Actually Works</h2>
<p>Every instruction in a Dockerfile produces a <strong>layer</strong>. Docker stores these layers and reuses them when it detects nothing has changed. That's the cache. Simple enough in theory, but the details matter a lot.</p>
<h3 id="heading-how-cache-keys-are-computed">How Cache Keys Are Computed</h3>
<p>Different instructions compute their cache keys differently:</p>
<table>
<thead>
<tr>
<th>Instruction</th>
<th>Cache Key Based On</th>
<th>What Breaks It</th>
</tr>
</thead>
<tbody><tr>
<td><code>RUN</code></td>
<td>The exact command string</td>
<td>Any change to the command text</td>
</tr>
<tr>
<td><code>COPY</code> / <code>ADD</code></td>
<td>File checksums of the source content</td>
<td>Any modification to the copied files</td>
</tr>
<tr>
<td><code>ENV</code> / <code>ARG</code></td>
<td>The variable name and value</td>
<td>Changing the value</td>
</tr>
<tr>
<td><code>FROM</code></td>
<td>The base image digest</td>
<td>A new version of the base image</td>
</tr>
</tbody></table>
<h3 id="heading-the-cache-chain-rule">The Cache Chain Rule</h3>
<p>Here's the thing most people miss: <strong>Docker cache is sequential.</strong> If any layer's cache gets invalidated, every layer after it rebuilds from scratch, even if those later layers haven't changed at all.</p>
<p>Picture a row of dominoes. Knock one over in the middle and everything after it goes down too. This is why the order of instructions in your Dockerfile is so important.</p>
<blockquote>
<p><strong>Key insight:</strong> The single most impactful optimization you can make is reordering your Dockerfile so that the stuff that changes most often comes last.</p>
</blockquote>
<h2 id="heading-how-to-identify-common-cache-busting-mistakes">How to Identify Common Cache-Busting Mistakes</h2>
<p>Before we fix anything, let's look at what's probably breaking your cache right now. I've seen these patterns in almost every unoptimized Dockerfile I've reviewed.</p>
<h3 id="heading-mistake-1-copying-everything-too-early">Mistake 1: Copying Everything Too Early</h3>
<p>This is the big one. Putting <code>COPY . .</code> near the top of the Dockerfile, before installing dependencies, means that <em>any</em> file change in your project invalidates the cache from that point forward. Changed a README? Cool, now your dependencies reinstall.</p>
<pre><code class="language-dockerfile"># BAD: Any file change invalidates the dependency install
FROM node:20-alpine
WORKDIR /app
COPY . .                    # Cache busted on every commit
RUN npm ci                  # Reinstalls every single time
RUN npm run build
</code></pre>
<h3 id="heading-mistake-2-not-separating-dependency-files">Mistake 2: Not Separating Dependency Files</h3>
<p>Your dependency manifests (<code>package.json</code>, <code>requirements.txt</code>, <code>go.mod</code>, <code>Gemfile</code>) change way less often than your source code. If you don't copy them separately, you're reinstalling all dependencies every time you touch a source file.</p>
<h3 id="heading-mistake-3-using-add-instead-of-copy">Mistake 3: Using ADD Instead of COPY</h3>
<p><code>ADD</code> has special behaviors like auto-extracting archives and fetching remote URLs. Those features make its cache behavior unpredictable. Stick with <code>COPY</code> unless you specifically need archive extraction.</p>
<h3 id="heading-mistake-4-splitting-apt-get-update-and-install">Mistake 4: Splitting apt-get update and install</h3>
<p>When you put <code>apt-get update</code> and <code>apt-get install</code> in separate <code>RUN</code> commands, the update step gets cached with stale package indexes. Then the install step fails or grabs outdated packages.</p>
<pre><code class="language-dockerfile"># BAD: Stale package index
RUN apt-get update
RUN apt-get install -y curl    # May fail with stale index

# GOOD: Always combine them
RUN apt-get update &amp;&amp; apt-get install -y curl &amp;&amp; rm -rf /var/lib/apt/lists/*
</code></pre>
<h3 id="heading-mistake-5-embedding-timestamps-or-git-hashes-too-early">Mistake 5: Embedding Timestamps or Git Hashes Too Early</h3>
<p>Injecting build-time variables like timestamps or git commit hashes via <code>ARG</code> or <code>ENV</code> early in the Dockerfile invalidates the cache on every single build. Move these to the very last layer.</p>
<blockquote>
<p>⚠️ <strong>Watch out for this:</strong> CI/CD systems often inject variables like <code>BUILD_NUMBER</code> or <code>GIT_SHA</code> as build args automatically. If those <code>ARG</code> declarations sit near the top, your cache is toast on every run.</p>
</blockquote>
<h2 id="heading-how-to-structure-your-dockerfile-for-maximum-cache-reuse">How to Structure Your Dockerfile for Maximum Cache Reuse</h2>
<p>Now let's fix those mistakes. These five steps, applied in order, will get you most of the way to an optimized build.</p>
<h3 id="heading-step-1-apply-the-dependency-first-pattern">Step 1: Apply the Dependency-First Pattern</h3>
<p>Copy only the dependency manifests first, install, and then copy the rest of the source code. This one change alone can cut your build times in half.</p>
<pre><code class="language-dockerfile"># GOOD: Dependency-first pattern for Node.js
FROM node:20-alpine
WORKDIR /app

# Copy ONLY dependency files
COPY package.json package-lock.json ./

# Install dependencies (cached unless package files change)
RUN npm ci --production

# Copy source code (only this layer rebuilds on code changes)
COPY . .

# Build
RUN npm run build
</code></pre>
<p>The same idea works across every language:</p>
<table>
<thead>
<tr>
<th>Language</th>
<th>Copy First</th>
<th>Install Command</th>
</tr>
</thead>
<tbody><tr>
<td>Node.js</td>
<td><code>package.json</code>, <code>package-lock.json</code></td>
<td><code>npm ci</code></td>
</tr>
<tr>
<td>Python</td>
<td><code>requirements.txt</code> or <code>pyproject.toml</code></td>
<td><code>pip install -r requirements.txt</code></td>
</tr>
<tr>
<td>Go</td>
<td><code>go.mod</code>, <code>go.sum</code></td>
<td><code>go mod download</code></td>
</tr>
<tr>
<td>Rust</td>
<td><code>Cargo.toml</code>, <code>Cargo.lock</code></td>
<td><code>cargo fetch</code></td>
</tr>
<tr>
<td>Java (Maven)</td>
<td><code>pom.xml</code></td>
<td><code>mvn dependency:go-offline</code></td>
</tr>
<tr>
<td>Ruby</td>
<td><code>Gemfile</code>, <code>Gemfile.lock</code></td>
<td><code>bundle install</code></td>
</tr>
</tbody></table>
<h3 id="heading-step-2-add-an-aggressive-dockerignore">Step 2: Add an Aggressive .dockerignore</h3>
<p>A <code>.dockerignore</code> file keeps irrelevant files out of the build context. Fewer files in the context means fewer things that can break your cache.</p>
<pre><code class="language-plaintext"># .dockerignore
.git
node_modules
dist
*.md
*.log
.env*
docker-compose*.yml
Dockerfile*
.github
tests
coverage
__pycache__
</code></pre>
<h3 id="heading-step-3-use-multi-stage-builds">Step 3: Use Multi-Stage Builds</h3>
<p>Multi-stage builds let you use a full development image for compiling, then copy only the finished artifacts into a slim runtime image. You get smaller images, better security, and improved cache performance because build tools and intermediate files don't carry over.</p>
<pre><code class="language-dockerfile"># Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Production
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package.json ./
EXPOSE 3000
CMD ["node", "dist/index.js"]
</code></pre>
<h3 id="heading-step-4-order-layers-by-change-frequency">Step 4: Order Layers by Change Frequency</h3>
<p>Think of your Dockerfile as a stack. Put the boring, stable stuff at the top and the volatile stuff at the bottom:</p>
<ol>
<li><p>Base image and system dependencies (rarely change)</p>
</li>
<li><p>Language runtime configuration (occasionally change)</p>
</li>
<li><p>Application dependencies (change when you add or remove packages)</p>
</li>
<li><p>Source code (changes on every commit)</p>
</li>
<li><p>Build-time metadata like git hash or version labels (changes every build)</p>
</li>
</ol>
<h3 id="heading-step-5-use-buildkit-mount-caches">Step 5: Use BuildKit Mount Caches</h3>
<p>Docker BuildKit supports <code>RUN --mount=type=cache</code>, which mounts a persistent cache directory that survives across builds. This is a game-changer for package managers that maintain their own download caches.</p>
<pre><code class="language-dockerfile"># syntax=docker/dockerfile:1

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .

# Mount pip cache so downloads persist across builds
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt

COPY . .
</code></pre>
<p>The best part: mount caches persist even when the layer itself gets invalidated. So if you add one new package, pip only downloads that one package instead of re-fetching everything.</p>
<p>Here are the common cache targets for popular package managers:</p>
<table>
<thead>
<tr>
<th>Package Manager</th>
<th>Cache Target</th>
</tr>
</thead>
<tbody><tr>
<td>pip</td>
<td><code>/root/.cache/pip</code></td>
</tr>
<tr>
<td>npm</td>
<td><code>/root/.npm</code></td>
</tr>
<tr>
<td>yarn</td>
<td><code>/usr/local/share/.cache/yarn</code></td>
</tr>
<tr>
<td>go</td>
<td><code>/go/pkg/mod</code></td>
</tr>
<tr>
<td>apt</td>
<td><code>/var/cache/apt</code></td>
</tr>
<tr>
<td>maven</td>
<td><code>/root/.m2/repository</code></td>
</tr>
</tbody></table>
<h2 id="heading-how-to-set-up-cicd-cache-backends">How to Set Up CI/CD Cache Backends</h2>
<p>Here's where things get tricky. Your local Docker cache works great on your laptop because the layers persist between builds. But CI/CD runners are usually ephemeral: each job starts with a totally empty cache. Without explicit cache configuration, every CI build is a cold build.</p>
<h3 id="heading-option-a-registry-based-cache">Option A: Registry-Based Cache</h3>
<p>BuildKit can push and pull cache layers from a container registry. This is the most portable approach and works with any CI system.</p>
<pre><code class="language-bash">docker buildx build \
  --cache-from type=registry,ref=myregistry.io/myapp:buildcache \
  --cache-to type=registry,ref=myregistry.io/myapp:buildcache,mode=max \
  --tag myregistry.io/myapp:latest \
  --push .
</code></pre>
<blockquote>
<p>💡 <strong>Use</strong> <code>mode=max</code> to cache all layers including intermediate build stages. The default <code>mode=min</code> only caches layers in the final stage, which means your build stage layers get thrown away.</p>
</blockquote>
<h3 id="heading-option-b-github-actions-cache">Option B: GitHub Actions Cache</h3>
<p>If you're on GitHub Actions, there's native integration with BuildKit through the GitHub Actions cache API. It's fast and requires minimal setup.</p>
<pre><code class="language-yaml"># .github/workflows/build.yml
- name: Set up Docker Buildx
  uses: docker/setup-buildx-action@v3

- name: Build and push
  uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: myregistry.io/myapp:latest
    cache-from: type=gha
    cache-to: type=gha,mode=max
</code></pre>
<h3 id="heading-option-c-s3-or-cloud-storage">Option C: S3 or Cloud Storage</h3>
<p>For teams on AWS, GCP, or Azure, cloud object storage makes a solid cache backend. It's fast, persistent, and works across any CI system.</p>
<pre><code class="language-bash">docker buildx build \
  --cache-from type=s3,region=us-east-1,bucket=my-docker-cache,name=myapp \
  --cache-to type=s3,region=us-east-1,bucket=my-docker-cache,name=myapp,mode=max \
  --tag myapp:latest .
</code></pre>
<h3 id="heading-option-d-local-cache-with-persistent-runners">Option D: Local Cache with Persistent Runners</h3>
<p>If your CI runners have persistent storage (self-hosted runners, GitLab runners with shared volumes), you can export cache to a local directory.</p>
<pre><code class="language-bash">docker buildx build \
  --cache-from type=local,src=/ci-cache/myapp \
  --cache-to type=local,dest=/ci-cache/myapp,mode=max \
  --tag myapp:latest .
</code></pre>
<h2 id="heading-how-to-implement-advanced-cache-patterns">How to Implement Advanced Cache Patterns</h2>
<p>Once you've nailed the basics, these patterns can squeeze out even more performance.</p>
<h3 id="heading-parallel-build-stages">Parallel Build Stages</h3>
<p>BuildKit builds independent stages in parallel. If your app has a frontend and a backend that don't depend on each other during build, split them into separate stages and let BuildKit run them simultaneously.</p>
<pre><code class="language-dockerfile"># These stages build in parallel
FROM node:20-alpine AS frontend
WORKDIR /frontend
COPY frontend/package.json frontend/package-lock.json ./
RUN npm ci
COPY frontend/ .
RUN npm run build

FROM python:3.12-slim AS backend
WORKDIR /backend
COPY backend/requirements.txt .
RUN pip install -r requirements.txt
COPY backend/ .

# Final stage combines both
FROM python:3.12-slim
COPY --from=backend /backend /app
COPY --from=frontend /frontend/dist /app/static
CMD ["python", "/app/main.py"]
</code></pre>
<h3 id="heading-cache-warming-for-feature-branches">Cache Warming for Feature Branches</h3>
<p>Feature branches often start with a cold cache because they diverge from main. You can warm the cache by specifying multiple <code>--cache-from</code> sources. Docker checks them in order.</p>
<pre><code class="language-bash">docker buildx build \
  --cache-from type=registry,ref=registry.io/app:cache-${BRANCH} \
  --cache-from type=registry,ref=registry.io/app:cache-main \
  --cache-to type=registry,ref=registry.io/app:cache-${BRANCH},mode=max \
  --tag registry.io/app:${BRANCH} .
</code></pre>
<p>If the branch cache hits, Docker uses it. If not, it falls back to main's cache, which usually shares most layers. This makes a massive difference for short-lived branches.</p>
<h3 id="heading-selective-cache-invalidation-with-build-args">Selective Cache Invalidation with Build Args</h3>
<p>You can use <code>ARG</code> instructions as cache boundaries. Anything above the <code>ARG</code> stays cached, while anything below it rebuilds when the arg value changes.</p>
<pre><code class="language-dockerfile">FROM node:20-alpine
WORKDIR /app

COPY package.json package-lock.json ./
RUN npm ci

# This ARG only invalidates layers below it
ARG CACHE_BUST_CODE=1
COPY . .
RUN npm run build

# This ARG only invalidates the label
ARG GIT_SHA=unknown
LABEL git.sha=$GIT_SHA
</code></pre>
<h2 id="heading-how-to-measure-your-improvements">How to Measure Your Improvements</h2>
<p>Optimization without measurement is just guessing. Here's how to actually prove your changes are working.</p>
<h3 id="heading-the-four-scenarios-to-benchmark">The Four Scenarios to Benchmark</h3>
<p>Run each scenario at least three times and take the median:</p>
<ol>
<li><p><strong>Cold build:</strong> No cache at all (first build or after <code>docker builder prune</code>)</p>
</li>
<li><p><strong>Warm build:</strong> No changes, full cache hit</p>
</li>
<li><p><strong>Code change:</strong> Only source code modified</p>
</li>
<li><p><strong>Dependency change:</strong> Package manifest modified</p>
</li>
</ol>
<h3 id="heading-real-world-before-and-after-numbers">Real-World Before and After Numbers</h3>
<p>Here's what I saw on a mid-sized Node.js project after applying the techniques from this guide:</p>
<table>
<thead>
<tr>
<th>Scenario</th>
<th>Before</th>
<th>After</th>
<th>Improvement</th>
</tr>
</thead>
<tbody><tr>
<td>Cold build</td>
<td>12 min 34 sec</td>
<td>8 min 10 sec</td>
<td>35%</td>
</tr>
<tr>
<td>Warm build (no changes)</td>
<td>12 min 34 sec</td>
<td>14 sec</td>
<td>98%</td>
</tr>
<tr>
<td>Code change only</td>
<td>12 min 34 sec</td>
<td>1 min 52 sec</td>
<td>85%</td>
</tr>
<tr>
<td>Dependency change</td>
<td>12 min 34 sec</td>
<td>4 min 20 sec</td>
<td>65%</td>
</tr>
</tbody></table>
<p>The "before" column is the same for all rows because without cache optimization, every build was essentially a cold build. That 85% improvement on code-only changes is the number that matters most, since that's what happens on the vast majority of commits.</p>
<h3 id="heading-how-to-check-cache-hit-rates">How to Check Cache Hit Rates</h3>
<p>Set <code>BUILDKIT_PROGRESS=plain</code> to get detailed output showing which layers hit cache:</p>
<pre><code class="language-bash">BUILDKIT_PROGRESS=plain docker buildx build . 2&gt;&amp;1 | grep -E 'CACHED|DONE'
</code></pre>
<p>Look for the <code>CACHED</code> prefix on layers. Your goal is to see <code>CACHED</code> on everything except the layers that actually needed to change.</p>
<h2 id="heading-complete-optimized-dockerfile-examples">Complete Optimized Dockerfile Examples</h2>
<p>Here are production-ready Dockerfiles you can adapt for your own projects.</p>
<h3 id="heading-nodejs-full-stack-app">Node.js Full-Stack App</h3>
<pre><code class="language-dockerfile"># syntax=docker/dockerfile:1
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm npm ci

FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup --system --gid 1001 appgroup \
    &amp;&amp; adduser --system --uid 1001 appuser
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=deps /app/node_modules ./node_modules
COPY package.json ./
USER appuser
EXPOSE 3000
CMD ["node", "dist/index.js"]
</code></pre>
<h3 id="heading-python-fastapi-app">Python FastAPI App</h3>
<pre><code class="language-dockerfile"># syntax=docker/dockerfile:1
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install --user -r requirements.txt

FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
ENV PATH=/root/.local/bin:$PATH
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
</code></pre>
<h3 id="heading-go-microservice">Go Microservice</h3>
<pre><code class="language-dockerfile"># syntax=docker/dockerfile:1
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod go mod download
COPY . .
RUN --mount=type=cache,target=/root/.cache/go-build \
    CGO_ENABLED=0 go build -ldflags='-s -w' -o /app/server ./cmd/server

FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]
</code></pre>
<h2 id="heading-troubleshooting-guide">Troubleshooting Guide</h2>
<p>When things go wrong, check this table first:</p>
<table>
<thead>
<tr>
<th>Symptom</th>
<th>Likely Cause</th>
<th>Fix</th>
</tr>
</thead>
<tbody><tr>
<td>All layers rebuild every time</td>
<td><code>COPY . .</code> is too early, or <code>.dockerignore</code> is missing</td>
<td>Move <code>COPY . .</code> after dependency install; add <code>.dockerignore</code></td>
</tr>
<tr>
<td>Cache never hits in CI</td>
<td>No cache backend configured</td>
<td>Add <code>--cache-from</code> / <code>--cache-to</code> with registry, gha, or s3 backend</td>
</tr>
<tr>
<td>Cache hits locally but not in CI</td>
<td>Different Docker versions or BuildKit not enabled</td>
<td>Set <code>DOCKER_BUILDKIT=1</code> and match Docker versions</td>
</tr>
<tr>
<td>Dependency layer always rebuilds</td>
<td>Source files copied before dependency install</td>
<td>Use the dependency-first pattern</td>
</tr>
<tr>
<td>Image size keeps growing</td>
<td>Build artifacts leaking into final image</td>
<td>Use multi-stage builds; only copy runtime artifacts</td>
</tr>
<tr>
<td>Registry cache is very slow</td>
<td><code>mode=max</code> caching too many layers</td>
<td>Try <code>mode=min</code> or switch to gha/s3 for faster backends</td>
</tr>
</tbody></table>
<h2 id="heading-quick-reference-checklist">Quick-Reference Checklist</h2>
<p>Print this out and tape it next to your monitor:</p>
<ul>
<li><p>[ ] Enable BuildKit: set <code>DOCKER_BUILDKIT=1</code> or use <code>docker buildx</code></p>
</li>
<li><p>[ ] Add a comprehensive <code>.dockerignore</code> file</p>
</li>
<li><p>[ ] Use the dependency-first pattern: copy manifests, install, then copy source</p>
</li>
<li><p>[ ] Order layers from least-changed to most-changed</p>
</li>
<li><p>[ ] Combine <code>RUN</code> commands that belong together (<code>apt-get update &amp;&amp; install</code>)</p>
</li>
<li><p>[ ] Use multi-stage builds to separate build and runtime</p>
</li>
<li><p>[ ] Add <code>RUN --mount=type=cache</code> for package manager caches</p>
</li>
<li><p>[ ] Move volatile <code>ARG</code>s (git hash, build number) to the very last layers</p>
</li>
<li><p>[ ] Configure a CI/CD cache backend (registry, gha, or s3)</p>
</li>
<li><p>[ ] Set up cache warming for feature branches from the main branch</p>
</li>
<li><p>[ ] Use <code>COPY</code> instead of <code>ADD</code> unless you need archive extraction</p>
</li>
<li><p>[ ] Benchmark all four scenarios: cold, warm, code change, dependency change</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I used to think slow Docker builds were just something you had to live with. After going through this process on a few projects, I realized the fix is pretty mechanical once you understand that one core principle: cache is sequential, and order matters.</p>
<p>Start with the dependency-first pattern and a <code>.dockerignore</code>. Those two changes alone will probably cut your build times in half. Then add multi-stage builds, mount caches, and CI/CD cache backends as you need them.</p>
<p>The teams I've worked with typically see 70-85% reductions in CI/CD pipeline times after spending a few hours on these changes. That's time you get back on every single commit, every single day.</p>
<p>If you found this helpful, consider sharing it with your team. There's a good chance whoever wrote your Dockerfile last didn't know about half of these tricks. No shade to them, I didn't either until I went looking.</p>
<p>Happy building.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Understanding Escape Analysis in Go – Explained with Example Code ]]>
                </title>
                <description>
                    <![CDATA[ In most languages, the stack and heap are two ways a program stores data in memory, managed by the language runtime. Each is optimized for different use cases, such as fast access or flexible lifetimes. Go follows the same model, but you usually don’... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/understanding-escape-analysis-in-go/</link>
                <guid isPermaLink="false">698e1c7090ca92017618cb24</guid>
                
                    <category>
                        <![CDATA[ Go Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ golang ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ stack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ heap ]]>
                    </category>
                
                    <category>
                        <![CDATA[ escape analysis ]]>
                    </category>
                
                    <category>
                        <![CDATA[ memory-management ]]>
                    </category>
                
                    <category>
                        <![CDATA[ memory ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eti Ijeoma ]]>
                </dc:creator>
                <pubDate>Thu, 12 Feb 2026 18:31:12 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1770921059389/c45b42cb-8cff-4de5-b3d1-7c7adad402c5.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In most languages, the stack and heap are two ways a program stores data in memory, managed by the language runtime. Each is optimized for different use cases, such as fast access or flexible lifetimes.</p>
<p>Go follows the same model, but you usually don’t decide between the stack and the heap directly. Instead, the Go compiler decides where values live. If the compiler can prove a value is only needed within the current function call, it can keep it on the stack. If it cannot prove that, the value “escapes” and is placed on the heap. This technique is called <strong>escape analysis</strong>.</p>
<p>This matters because heap allocations increase garbage collector work. In code that runs often, that extra work can show up as more CPU spent in GC, more allocations, and less predictable performance.</p>
<p>In this article, I’ll explain what escape analysis is, the common patterns that trigger heap allocation, and how to confirm and reduce avoidable allocations.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-do-you-really-need-to-care-about-escape-analysis">Do You Really Need to Care About Escape Analysis?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-memory-layout-and-lifecycle">Memory Layout and Lifecycle</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-sharing-down-and-sharing-up">Sharing Down and Sharing Up</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-escape-analysis-in-practice">Escape Analysis in Practice</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-escape-analysis-to-guide-performance">How to Use Escape Analysis to Guide Performance</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-further-reading">Further Reading</a></p>
</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<ul>
<li><p>Familiarity with Go fundamentals (functions, variables, structs, slices, maps)</p>
</li>
<li><p>Basic understanding of pointers in Go (<code>&amp;</code> and <code>*</code>)</p>
</li>
<li><p>A general idea of how goroutines work</p>
</li>
</ul>
<h2 id="heading-do-you-really-need-to-care-about-escape-analysis">Do You Really Need to Care About Escape Analysis?</h2>
<p>Before we go deeper, I want to call this out clearly. For the correctness of your program, it doesn’t matter whether a variable lives on the stack or on the heap, or whether you know that detail. The Go compiler is smart enough to place values where they need to be so that your program behaves correctly.</p>
<p>Most of the time, you don’t need to think about this at all. It only starts to matter when performance becomes a problem. If your program is already fast enough, you’re done, and there’s no point trying to squeeze out extra speed.</p>
<p>You should only start caring about stack vs heap when you have benchmarks that show your program is too slow, and those same benchmarks point to heavy heap allocation and garbage collection as part of the problem.</p>
<h2 id="heading-memory-layout-and-lifecycle"><strong>Memory Layout and Lifecycle</strong></h2>
<p>To get a better understanding of what escape analysis is, you first need a simple picture of how Go lays out memory while your program runs. At this level, it comes down to the stack each goroutine uses, how stack frames are carved out of that stack, and when values move to the heap where the garbage collector can see them.</p>
<h3 id="heading-goroutine-stacks-and-stack-frames">Goroutine Stacks and Stack Frames</h3>
<p>When a Go program starts, the runtime creates the <code>main</code> goroutine, and every <code>go</code> statement creates a new goroutine, each with its own stack.</p>
<p>There’s not a single global stack for the whole process. As of writing this article, with Go v1.25.7, each goroutine gets an initial contiguous block of 2,048 bytes of memory, which acts as its stack. The stack is where Go stores data that belongs to function calls. When a goroutine calls a function, Go reserves a chunk of that goroutine’s stack for the function’s local data. That chunk is called a <strong>stack frame</strong>.</p>
<p>It holds the function’s local variables and the call state needed to return and continue execution. If that function calls another function, a new frame is added on top. When the inner function returns, its frame becomes invalid, and the goroutine continues in the caller’s frame.</p>
<p>A stack frame only lives for as long as the function is active. Once the function returns, anything stored in its frame is considered invalid, even if the raw bytes are still in memory and will be reused later. Code must not rely on those values after the return</p>
<p>Go stacks can grow. A goroutine starts with a small stack and the runtime grows it when needed, but the lifetime rule stays the same. A value is safe in a stack frame only if nothing can still reference it after the function returns. If it might be referenced later, it can’t stay in that frame and must be placed somewhere safer.</p>
<h3 id="heading-pointers-and-lifetime">Pointers and Lifetime</h3>
<p>In Go, taking an address like <code>p := &amp;x</code> means you now have a pointer in one stack frame that refers to a value which may have been created in another frame. When you pass that pointer into a function, Go still passes by value. The callee gets its own pointer variable on its own stack frame, but the address inside still points to the same underlying value. So pointers are how you share access to one value across several frames without copying the value itself.</p>
<p>Lifetime becomes important when a pointer can outlive the frame where the pointed value was created. As long as both the pointer and the value live inside frames that are still active in the current call stack, everything is safe.</p>
<p>Once a pointer might still exist after the original frame has returned, the value can no longer stay in that frame, because that frame will become invalid. At that point, the value has to be placed in a safer location so that no pointer ever points into dead stack memory.</p>
<h2 id="heading-sharing-down-and-sharing-up">Sharing Down and Sharing Up</h2>
<p>Now that you have a picture of stacks, frames, and pointers, we can look at two common ways pointers move through your code. I’ll call them sharing down and sharing up. The names aren’t special Go terms. They’re just a simple way to describe how a pointer moves along the call stack.</p>
<h3 id="heading-sharing-down">Sharing Down</h3>
<p>Sharing down means a function passes a pointer or reference to functions it calls. The pointer moves deeper into the call stack, but the value it points to still belongs to a frame that is active.</p>
<p>Example code:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    n := <span class="hljs-number">10</span>
    multiply(&amp;n) 
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">multiply</span><span class="hljs-params">(v *<span class="hljs-keyword">int</span>)</span></span> {
   *v = *v * <span class="hljs-number">2</span>
}
</code></pre>
<p>In <code>main</code>, you take the address of <code>n</code> and pass it into <code>multiply</code>. While <code>multiply</code> runs, both the <code>main</code> frame and the <code>multiply</code> frames are active. The pointer in <code>multiply</code> points to a value that still lives in an active frame, so this situation is safe from a lifetime point of view.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770153560595/0681b535-3668-406d-acaf-6e27679d52e1.png" alt="Diagram showing two stack frames on one goroutine, with the upper frame pointing to a value in the lower frame to illustrate sharing down on the stack" class="image--center mx-auto" width="1252" height="1102" loading="lazy"></p>
<p>In the diagram below, after the <code>multiply</code> function runs and returns, the <code>multiply</code> frame becomes invalid, and we don’t need to do anything because the stack pointer is simply popped back to the previous frame's address. This action automatically reclaims all the memory used by that function in one step, so the garbage collector is not involved in cleaning up stack memory</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770153730555/9093b49a-a8bc-497d-be06-77738a89a6c4.png" alt="Diagram showing two stack frames with a value in the upper frame updated through a pointer stored in the lower frame, again illustrating sharing down entirely on the stack" class="image--center mx-auto" width="1346" height="1130" loading="lazy"></p>
<h3 id="heading-sharing-up">Sharing Up</h3>
<p>Sharing up means a function returns a pointer, or stores it somewhere that will still be around after the function returns. The pointer moves back up the call stack or into some longer-lived state while the frame that created the value is about to end, so that value can no longer be tied to that one frame.</p>
<p>The same idea shows up when you share a value with another goroutine, because Go doesn’t let one goroutine hold pointers into another goroutine’s stack, so shared data needs a lifetime that is not tied to a single stack.</p>
<h4 id="heading-heap-garbage-collection-and-lifetime">Heap, garbage collection, and lifetime</h4>
<p>Values that might outlive a single stack frame can’t stay in that frame. The compiler places them on the heap instead. The heap is a separate region of memory that isn’t tied to one function call. Any goroutine can hold pointers to heap values, and those values stay valid as long as something in the program can still reach them. You can think of the heap as storage for “<em>might live longer than this call</em>”.</p>
<p>The garbage collector is what keeps this safe. Periodically, the runtime starts from a set of roots (global variables, active stack frames, some internal state) and follows all the pointers it can see. Any heap value that is still reachable is kept. Any heap value that is no longer reachable is treated as garbage and its memory is reclaimed.</p>
<p>This means a pointer in <code>main</code> will never legally point into dead stack memory. Either the value stayed in an active frame, or it was placed on the heap where the GC can track its lifetime. The tradeoff is that more heap allocations and longer-lived objects require the GC to do more work.</p>
<p>Here’s an example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Car <span class="hljs-keyword">struct</span> {
    Brand <span class="hljs-keyword">string</span>
    Model <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// main receives a pointer from a function it called and this is sharing up</span>
    carPtr := makeCar(<span class="hljs-string">"Volkswagen"</span>, <span class="hljs-string">"Golf"</span>) 

    fmt.Printf(<span class="hljs-string">"I received a car: %s %s\n"</span>, carPtr.Brand, carPtr.Model)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">makeCar</span><span class="hljs-params">(b, m <span class="hljs-keyword">string</span>)</span> *<span class="hljs-title">Car</span></span> {
    myCar := Car{
        Brand: b,
        Model: m,
    }
    <span class="hljs-keyword">return</span> &amp;myCar
}
</code></pre>
<p>In the above code:</p>
<ol>
<li><p>In <code>makeCar</code> (the callee frame), Go creates a local variable <code>myCar</code>. Because you return <code>&amp;myCar</code>, the compiler allocates the <code>Car</code> value on the heap, and let’s <code>myCar</code> hold the heap address <code>0xc00029fa0</code>.</p>
</li>
<li><p>When <code>makeCar</code> returns, that address is copied into <code>carPtr</code> in <code>main</code> (the top frame). <code>carPtr</code> is just another stack variable, but its value is still <code>0xc00029fa0</code>, so now <code>main</code> also points to the same heap <code>Car</code>.</p>
</li>
<li><p>On the right, the heap bubble shows the actual <code>Car</code> value at <code>0xc00029fa0</code>. Both <code>car</code> (while <code>makeCar</code> is running) and <code>carPtr</code> (after it returns) reach that same value through their pointers.</p>
</li>
<li><p>Once <code>makeCar</code> is done, its frame drops into the “invalid memory” region, but the <code>Car</code> stays alive on the heap because <code>main</code> still holds <code>carPtr</code>. That’s the escape: the value stops being tied to the callee frame and gets heap lifetime instead.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770255008545/5ef80c9b-3203-4ca3-a26e-f1e2462912cf.png" alt="Diagram showing a caller and callee stack frame both holding a pointer to the same value in heap memory, illustrating a value being shared up and escaping the stack" class="image--center mx-auto" width="1850" height="1190" loading="lazy"></p>
<h2 id="heading-escape-analysis-in-practice">Escape Analysis in Practice</h2>
<p>Escape analysis is how the Go compiler decides whether a value lives on the stack or on the heap. It’s not only about returning pointers – it follows how addresses move through your code. If a value might outlive the current function, the compiler can’t keep it in that stack frame and moves it to the heap. Since only the compiler sees the full picture, the useful thing is to ask it to show these decisions and then link them back to your code.</p>
<p>To do that, we can pass compiler flags using <code>-gcflags</code> when running <code>go build</code> or <code>go run</code>. If you want to see the available options, you can check <code>go tool compile -h</code>. In that list, <code>-m</code> prints the compiler’s optimisation decisions, including escape analysis output. If you want more details, you can use <code>-m=2</code> or <code>-m=3</code> for a more verbose output. The <code>-l</code> flag disables inlining, so the report is easier to read because the compiler is not merging small functions into their callers.</p>
<p>So, the command will look like this:</p>
<pre><code class="lang-bash">go run -gcflags=<span class="hljs-string">'all=-m -l'</span> .
</code></pre>
<p>Or for a build:</p>
<pre><code class="lang-bash">go build -gcflags=<span class="hljs-string">'all=-m -l'</span> .
</code></pre>
<h2 id="heading-how-to-use-escape-analysis-to-guide-performance">How to Use Escape Analysis to Guide Performance</h2>
<p>You can think of escape analysis as the thing that turns your code choices into GC work. When a value escapes, it gets heap lifetime, and the garbage collector has to visit it. In hot paths, lots of small escaping values show up as extra GC time and jitter in latency. When a value stays in a stack frame, it becomes invalid and dies with the frame and the GC does not care about it.</p>
<p>Here are five simple practices that help performance without making</p>
<ol>
<li><p><strong>Prefer values for small data:</strong> If the function doesn’t need to mutate the caller’s data, use value types for small structs and basic types when passing arguments and returning results. It’s cheap to copy an <code>int</code> or a small struct, and it often keeps lifetimes local to a single call.</p>
</li>
<li><p><strong>Use pointers when sharing or mutation is part of the design:</strong> opt for pointers when you genuinely need shared mutable state or want to avoid copying large structs.</p>
</li>
<li><p><strong>Avoid creating long-lived references by accident</strong>: Be careful when returning pointers to locals, capturing variables in closures, or storing addresses in long-lived structs, maps, or interfaces. These patterns are the ones most likely to push values out of a stack frame.</p>
</li>
<li><p><strong>Pass in reusable buffers on hot paths</strong>: On code paths that run very often, the problem is usually not one big allocation, but many small ones happening in a loop. A common cause is functions that always create a new buffer inside, even when the caller could have passed one in.</p>
<p> A simple way to cut those extra allocations is to let the caller own the buffer. The caller allocates a <code>[]byte</code> once, then passes it into the function each time. The function only fills the buffer instead of creating a new one.</p>
<p> Here’s an example of how a bad function allocates a new buffer every call:</p>
<pre><code class="lang-go"> <span class="hljs-keyword">package</span> main

 <span class="hljs-comment">// Bad: helper allocates every call.</span>
 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fillBad</span><span class="hljs-params">()</span> []<span class="hljs-title">byte</span></span> {
     buf := <span class="hljs-built_in">make</span>([]<span class="hljs-keyword">byte</span>, <span class="hljs-number">4096</span>)
     <span class="hljs-comment">// pretend we read into it</span>
     buf[<span class="hljs-number">0</span>] = <span class="hljs-number">1</span>
     <span class="hljs-keyword">return</span> buf
 }

 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">hotPathBad</span><span class="hljs-params">()</span></span> {
     <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1</span>_000_000; i++ {
         b := fillBad() <span class="hljs-comment">// allocates 1,000,000 times</span>
         _ = b
     }
 }

 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
     hotPathBad()
 }
</code></pre>
<p> When we run escape analysis with this:</p>
<pre><code class="lang-bash"> go run -gcflags=<span class="hljs-string">'-m -l'</span> .
</code></pre>
<p> We see the following:</p>
<pre><code class="lang-plaintext"> ./main.go:5:13: make([]byte, 4096) escapes to heap
</code></pre>
<p> If we were only allocating a few times, we could choose not to worry – but the real problem is how this looks inside the loop. <code>hotPathBad</code> calls <code>fillBad</code> on every iteration, so each call allocates a new 4 KB slice on the heap. If this loop runs many times, you end up creating a lot of short-lived heap objects. The garbage collector then has to find and clean up all those buffers, which adds extra work that you could have avoided by reusing a single buffer.  </p>
<p> Here’s an example of a better version where the caller allocates once and reuses:</p>
<pre><code class="lang-go"> <span class="hljs-keyword">package</span> main

 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fill</span><span class="hljs-params">(buf []<span class="hljs-keyword">byte</span>)</span> <span class="hljs-title">int</span></span> {
     <span class="hljs-comment">// pretend we read into it</span>
     buf[<span class="hljs-number">0</span>] = <span class="hljs-number">1</span>
     <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>
 }

 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">hotPath</span><span class="hljs-params">()</span></span> {
     buf := <span class="hljs-built_in">make</span>([]<span class="hljs-keyword">byte</span>, <span class="hljs-number">4096</span>) 

     <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1</span>_000_000; i++ {
         n := fill(buf) 
         _ = buf[:n]
     }
 }

 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
     hotPath()
 }
</code></pre>
<p> In this version, <code>hotPath</code> controls the buffer. It allocates <code>buf</code> once, then passes it into <code>fill</code> on every loop. You still read the same data, but you avoid creating a new slice on each call. That reduces avoidable allocations in the hot path.</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In Go, where a value ends up is not decided by how you create it. It’s decided by how long that value must remain valid and how it is referenced as your code runs.</p>
<p>The practical takeaway is not to avoid pointers. It’s to be deliberate about lifetime. Value semantics can keep lifetimes tight and reduce GC work, while pointers can be the right choice when you need shared state or in-place updates. The balance is to write the clear version first, then look at your benchmarks and profiles to see if anything actually really needs to change.</p>
<h2 id="heading-further-reading">Further Reading</h2>
<p>Language Mechanics On Stacks And Pointers - William Kennedy</p>
<p><a target="_blank" href="https://go.dev/doc/gc-guide">Go Compiler: Escape Analysis Flaws</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Test and Improve AI Applications with an Evaluation Flywheel ]]>
                </title>
                <description>
                    <![CDATA[ In traditional programming, developers rely on unit tests to catch mistakes in applications. But when building AI products, that safety net doesn't exist. Responses can shift with model updates, data changes, and subtle fluctuations in prompts or ret... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-test-and-improve-ai-applications-with-an-evaluation-flywheel/</link>
                <guid isPermaLink="false">69491adc842069e2b48bbae7</guid>
                
                    <category>
                        <![CDATA[ ai agents ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yemi Ojedapo ]]>
                </dc:creator>
                <pubDate>Mon, 22 Dec 2025 10:18:04 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1766082262126/bc54e004-7acc-49fc-b228-24524f250427.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In traditional programming, developers rely on unit tests to catch mistakes in applications. But when building AI products, that safety net doesn't exist. Responses can shift with model updates, data changes, and subtle fluctuations in prompts or retrieval results. The usual testing methods like unit tests with Pytest or Jest, integration tests, CI pipelines, fail to catch accuracy drops, hallucinations, or regressions, and these silent failures can become real production risks.</p>
<p>In this article, you’ll learn why traditional testing methods fall short for AI systems and how an evaluation flywheel can be used as a practical approach to testing and improving AI applications. The sections below break the evaluation flywheel down step by step, from identifying the problem to implementing a repeatable evaluation loop.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-does-traditional-testing-fail-for-ai-applications">Why Does Traditional Testing Fail for AI applications?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-evaluation-flywheel">What is the Evaluation Flywheel?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-drawing-parallels-to-familiar-practices">Drawing Parallels to Familiar Practices</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-silent-failures-matter-a-real-world-example">Why Silent Failures Matter: A Real-World Example</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-an-evaluation-flywheel">How to Create an Evaluation Flywheel</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tools-and-frameworks-you-can-use-for-evaluation">Tools and Frameworks you can use for evaluation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-a-complete-evaluation-loop-looks-like-in-practice">What a Complete Evaluation Loop Looks Like in Practice</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-key-takeaways">Key Takeaways</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-why-does-traditional-testing-fail-for-ai-applications">Why Does Traditional Testing Fail for AI applications?</h2>
<p>In standard programming, tests assume deterministic behavior. This means the same input is expected to always produce the same output. For example:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">authenticate_user_age</span>(<span class="hljs-params">age: int</span>) -&gt; str:</span>
    limit = <span class="hljs-number">18</span>

    <span class="hljs-keyword">if</span> age &gt;= limit:
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Access granted"</span>
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-string">"User doesn't meet the age limit"</span>

<span class="hljs-comment"># Test </span>
<span class="hljs-keyword">assert</span> authenticate_user_age(<span class="hljs-number">20</span>) == <span class="hljs-string">"Access granted"</span>
<span class="hljs-keyword">assert</span> authenticate_user_age(<span class="hljs-number">16</span>) == <span class="hljs-string">"User doesn't meet the age limit"</span>
</code></pre>
<p>The response from this function is always predictable. You can write tests once and trust they'll catch errors forever.</p>
<p>However, AI models don’t behave the same way every time, they generate output based on probabilities. A query like “best programming practices” may produce strong guidance one day, and outdated or incomplete advice the next. This shift can happen because of changes in the underlying model, updates to retrieval components, or gradual data drift. Without a structured evaluation process in place, these inconsistencies slip into production unnoticed and can quietly weaken the system’s performance.</p>
<h2 id="heading-what-is-the-evaluation-flywheel">What is the Evaluation Flywheel?</h2>
<p>The evaluation flywheel is a continuous improvement system where test cases representing real user behavior are passed through multiple evaluation steps to assess the output of AI models. The results don't just tell you whether the system passed or failed, they feed directly into the next cycle of improvement.</p>
<pre><code class="lang-plaintext">┌─────────────┐
│   Collect   │
│ Test Cases  │
└──────┬──────┘
       │
       ▼
┌─────────────┐
│     Run     │
│ Evaluations │
└──────┬──────┘
       │
       ▼
┌─────────────┐      ┌─────────────┐
│  Identify   │─────▶│   Improve   │
│  Failures   │      │   System    │
└─────────────┘      └──────┬──────┘
                            │
                            ▼
                       ┌─────────────┐
                       │   Repeat    │
                       └─────────────┘
</code></pre>
<p>Here's how it works in practice:</p>
<ul>
<li><p><strong>Collect test cases</strong> — Gather examples from real user interactions or create synthetic scenarios. These should reflect the kind of tasks and input your system needs to handle.</p>
</li>
<li><p><strong>Run evaluations</strong> — Pass each test case through a series of checks. The check can either be programmatic (automated metrics like relevance scores or hallucination detectors) or require manual review (like verifying legal advice accuracy or brand voice consistency).</p>
</li>
<li><p><strong>Identify failures</strong> — Detect where the model goes wrong, this can include hallucinations, irrelevant responses, or mistakes on corner-cases.</p>
</li>
<li><p><strong>Improve the system</strong> — Based on those failures, refine prompts, improve training or retrieval data, or adjust architectural components.</p>
</li>
<li><p><strong>Repeat the cycle</strong> — Re-run the updated system on the existing and newly collected cases. Over time, this grows and strengthens your evaluation suite and boosts system reliability.</p>
</li>
</ul>
<h2 id="heading-drawing-parallels-to-familiar-practices">Drawing Parallels to Familiar Practices</h2>
<p>If you've written software before, the evaluation flywheel will feel familiar. It mirrors patterns that are already used in engineering. For instance,</p>
<p><strong>Unit tests → Evaluation datasets</strong><br>Unit tests confirm a function returns the right output. Evaluation datasets play the same role for AI: they're ground-truth queries and answers that guard against regressions.</p>
<p><strong>Test-driven development (TDD) → Evaluation-driven development (EDD)</strong><br>In TDD, you write tests before code. In EDD, you write evaluation cases before shipping prompts or updating models. This replaces assumptions with verifiable results.</p>
<p><strong>CI/CD pipelines → Continuous evaluation pipelines</strong><br>CI/CD runs checks automatically on every code change. Continuous evaluation does the same for models: it runs automated quality checks every time you tweak a prompt, retrain, or swap out a component.</p>
<p>The key difference is subtle but important. Traditional software tests check whether a function returns the right value or type. AI evaluation tests check whether the system produces the right <em>meaning</em>. That's harder to measure, but the principle is the same: build a safety net that grows stronger with every cycle.</p>
<h2 id="heading-why-silent-failures-matter-a-real-world-example">Why Silent Failures Matter: A Real-World Example</h2>
<p>AI systems often behave differently in production than they do in development. A model that seems solid in testing can drift, hallucinate, or silently fail when facing real-world input.</p>
<p><strong>Case in point</strong>: A fraud detection model passed all monitoring metrics yet missed a spike in fraud. An ML engineer shared how their production monitoring dashboards tracked latency, throughput, and error rates, everything showed green. But fraudulent transactions were slipping through at twice the normal rate. Nobody noticed because existing observability tools focused on pipeline health, not prediction quality.</p>
<p>This silent failure cost the company significant losses. The system seemed fine by traditional metrics. It measured system performance—latency, throughput, uptime—but ignored what mattered most: prediction accuracy. As fraudsters adapted their tactics, the model drifted, and without proper evaluation loops, the degradation went undetected for weeks.</p>
<p>Source: <a target="_blank" href="https://insightfinder.com/blog/model-drift-ai-observability/">InsightFinder</a>.</p>
<h3 id="heading-why-this-example-matters">Why This Example Matters</h3>
<ul>
<li><p><strong>Silent failures aren't always bugs</strong> — They often stem from models failing to adapt to shifting patterns in the real world.</p>
</li>
<li><p><strong>Static evaluation isn't enough</strong> — You need continuous, real-world feedback loops to detect when assumptions no longer hold.</p>
</li>
<li><p><strong>Data drift has business impact</strong> — Model degradation isn't just technical, it translates directly into revenue loss, security breaches, or damaged user trust.</p>
</li>
</ul>
<h2 id="heading-how-to-create-an-evaluation-flywheel">How to Create an Evaluation Flywheel</h2>
<p>To show how to build a flywheel and how it works, let's create one for a customer support chatbot that answers questions about a SaaS product.</p>
<h3 id="heading-step-1-build-your-ai-system"><strong>Step 1: Build Your AI System</strong></h3>
<p>Create your initial product: prompts, retrieval logic, and integrations. For our chatbot:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">answer_support_question</span>(<span class="hljs-params">question: str</span>) -&gt; str:</span>
    <span class="hljs-comment"># Retrieve relevant docs from knowledge base</span>
    context = retrieve_docs(question, top_k=<span class="hljs-number">5</span>)

    <span class="hljs-comment"># Generate answer using LLM</span>
    prompt = <span class="hljs-string">f"""You are a helpful customer support agent.

Context: <span class="hljs-subst">{context}</span>

Question: <span class="hljs-subst">{question}</span>

Provide a clear, accurate answer based on the context."""</span>

    response = llm.generate(prompt)
    <span class="hljs-keyword">return</span> response
</code></pre>
<p><strong>How this works:</strong> This function defines the core chat logic, it takes a customer’s question and returns an AI-generated answer. First, it searches your knowledge base to find the five most relevant documents using <code>retrieve_docs()</code>. These documents provide context about your product or policies. Next, it constructs a prompt that includes this context and the user's question, then sends it to a language model. The LLM reads the context and generates a relevant answer, which the function returns.</p>
<h3 id="heading-step-2-identify-test-cases">Step 2: Identify Test Cases</h3>
<p>Build an evaluation set that reflects real user behavior. The more representative your test cases are, including common cases, edge cases, and ambiguous inputs, the better your model can catch failures before they reach production.</p>
<p><strong>Sources for test cases:</strong></p>
<ul>
<li><p>Previous customer support tickets</p>
</li>
<li><p>Common FAQ topics</p>
</li>
<li><p>Edge cases discovered in beta testing</p>
</li>
<li><p>Synthetic scenarios (hypothetical but realistic queries)</p>
</li>
</ul>
<p>Example test cases:</p>
<pre><code class="lang-python">test_cases = [
    {
        <span class="hljs-string">"question"</span>: <span class="hljs-string">"How do I reset my password?"</span>,
        <span class="hljs-string">"expected_elements"</span>: [<span class="hljs-string">"settings page"</span>, <span class="hljs-string">"reset link"</span>, <span class="hljs-string">"email"</span>],
        <span class="hljs-string">"category"</span>: <span class="hljs-string">"account_management"</span>
    },
    {
        <span class="hljs-string">"question"</span>: <span class="hljs-string">"What's your refund policy?"</span>,
        <span class="hljs-string">"expected_elements"</span>: [<span class="hljs-string">"30 days"</span>, <span class="hljs-string">"full refund"</span>, <span class="hljs-string">"contact support"</span>],
        <span class="hljs-string">"category"</span>: <span class="hljs-string">"billing"</span>
    },
    {
        <span class="hljs-string">"question"</span>: <span class="hljs-string">"Can I export my data to CSV?"</span>,
        <span class="hljs-string">"expected_elements"</span>: [<span class="hljs-string">"yes"</span>, <span class="hljs-string">"export button"</span>, <span class="hljs-string">"dashboard"</span>],
        <span class="hljs-string">"category"</span>: <span class="hljs-string">"features"</span>
    },
    {
        <span class="hljs-string">"question"</span>: <span class="hljs-string">"Does your API support webhooks?"</span>,
        <span class="hljs-string">"expected_elements"</span>: [<span class="hljs-string">"yes"</span>, <span class="hljs-string">"webhook endpoints"</span>, <span class="hljs-string">"documentation"</span>],
        <span class="hljs-string">"category"</span>: <span class="hljs-string">"technical"</span>
    }
]
</code></pre>
<p><strong>How this works:</strong> Here, we define a set of representative test cases to evaluate the AI system. Each test case includes the user’s question, a list of key elements expected in the answer, and a category for organization. These cases help ensure the chatbot is tested against real-world scenarios, edge cases, and important information that should appear in responses.</p>
<h3 id="heading-step-3-evaluate-outputs">Step 3: Evaluate Outputs</h3>
<p>Define evaluation criteria based on what matters for your use case: accuracy, faithfulness, safety, relevance, tone. Then measure the output against these criteria.</p>
<p>Evaluation happens in two main ways:</p>
<h4 id="heading-automated-evaluation">Automated Evaluation</h4>
<p>Use programmatic metrics and LLM-as-judge patterns:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">evaluate_response</span>(<span class="hljs-params">question: str, response: str, expected_elements: list</span>) -&gt; dict:</span>
    scores = {}

    <span class="hljs-comment"># 1. Faithfulness: Does response contain expected elements?</span>
    scores[<span class="hljs-string">'contains_key_info'</span>] = all(
        elem.lower() <span class="hljs-keyword">in</span> response.lower() 
        <span class="hljs-keyword">for</span> elem <span class="hljs-keyword">in</span> expected_elements
    )

    <span class="hljs-comment"># 2. Relevance: Semantic similarity to question</span>
    scores[<span class="hljs-string">'relevance'</span>] = calculate_semantic_similarity(question, response)

    <span class="hljs-comment"># 3. Safety: Check for problematic content</span>
    scores[<span class="hljs-string">'is_safe'</span>] = <span class="hljs-keyword">not</span> contains_harmful_content(response)

    <span class="hljs-comment"># 4. Tone: Use LLM-as-judge</span>
    judge_prompt = <span class="hljs-string">f"""Rate the helpfulness of this support response on a scale of 1-5.

Question: <span class="hljs-subst">{question}</span>
Response: <span class="hljs-subst">{response}</span>

Score (1-5):"""</span>

    scores[<span class="hljs-string">'helpfulness'</span>] = int(llm.generate(judge_prompt))

    <span class="hljs-keyword">return</span> scores

<span class="hljs-comment"># Run evaluation</span>
<span class="hljs-keyword">for</span> test_case <span class="hljs-keyword">in</span> test_cases:
    response = answer_support_question(test_case[<span class="hljs-string">'question'</span>])
    scores = evaluate_response(
        test_case[<span class="hljs-string">'question'</span>],
        response,
        test_case[<span class="hljs-string">'expected_elements'</span>]
    )
    test_case[<span class="hljs-string">'scores'</span>] = scores
    test_case[<span class="hljs-string">'response'</span>] = response
</code></pre>
<p><strong>How this works:</strong> The <code>evaluate_response()</code> function applies four different checks to each AI response:</p>
<ul>
<li><p>First, it verifies faithfulness by checking if all expected elements appear in the response using simple string matching.</p>
</li>
<li><p>Second, it calculates semantic similarity, a measure of how closely the responses meaning match the intent of the questions, using embeddings.</p>
</li>
<li><p>Third, it runs a safety check to flag any problematic content.</p>
</li>
<li><p>Fourth, it uses an LLM as a judge by asking a more powerful model (like GPT-4) to rate the helpfulness of the response on a 1-5 scale.</p>
</li>
</ul>
<p>The loop then runs the evaluation for every test case. It generates a response for each question, evaluates it using the <code>evaluate_response</code> function, and then stores both the scores and the response back in the test case. This creates a complete dataset of test results for analysis and further improvements.</p>
<p>Common Automated Metrics:</p>
<ul>
<li><p><strong>Semantic similarity (0.0–1.0):</strong> This is measured by converting the question and response into vector embeddings and calculating cosine similarity. The score shows how closely the response matches the intent of the question, even if the wording differs.</p>
</li>
<li><p><strong>ROUGE / BLEU scores:</strong> The model’s output is compared to reference answers by checking n-gram overlap. These metrics help spot regressions, though scores can be modest for open-ended answers.</p>
</li>
<li><p><strong>LLM-as-judge:</strong> A stronger model (like GPT-4 or Claude) can rate the response on a fixed scale, such as 1–5. These ratings give a sense of quality and are useful for tracking improvements or drops over time.</p>
</li>
<li><p><strong>Retrieval metrics (Precision@k, Recall@k):</strong> For retrieval-based systems, these metrics calculate how many relevant documents appear in the top-k results. Precision shows accuracy of the retrieved set, and recall indicates completeness.</p>
</li>
<li><p><strong>Custom validators:</strong> Simple rule-based checks, like regex patterns, keywords, or length limits, ensure responses meet hard requirements. These help catch issues automated metrics might miss.</p>
</li>
</ul>
<h4 id="heading-manual-evaluation">Manual Evaluation</h4>
<p>Automated metrics can't capture everything. Subjective qualities like tone, empathy, and brand voice require human judgment, as do small factual errors that slip past keyword checks and similarity scores.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Flag cases for human review</span>
needs_review = [
    case <span class="hljs-keyword">for</span> case <span class="hljs-keyword">in</span> test_cases 
    <span class="hljs-keyword">if</span> case[<span class="hljs-string">'scores'</span>][<span class="hljs-string">'helpfulness'</span>] &lt; <span class="hljs-number">3</span> 
    <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> case[<span class="hljs-string">'scores'</span>][<span class="hljs-string">'contains_key_info'</span>]
]

<span class="hljs-comment"># SMEs review and annotate</span>
<span class="hljs-keyword">for</span> case <span class="hljs-keyword">in</span> needs_review:
    annotation = get_sme_feedback(case)
    case[<span class="hljs-string">'human_rating'</span>] = annotation[<span class="hljs-string">'rating'</span>]
    case[<span class="hljs-string">'improvement_notes'</span>] = annotation[<span class="hljs-string">'notes'</span>]
</code></pre>
<p>This code filters test cases to find responses that need human attention, those scoring below 3 for helpfulness or missing important information. Subject matter experts review these flagged cases and provide ratings with helpful feedback. Their input helps you spot patterns that automated metrics miss and shows you where to improve your prompts, retrieval setup, or system settings.</p>
<p><strong>When to use manual evaluation:</strong></p>
<ul>
<li><p>Assessing tone, empathy, or brand voice</p>
</li>
<li><p>Detecting subtle hallucinations automated checks miss</p>
</li>
<li><p>Validating edge cases with domain-specific nuance</p>
</li>
<li><p>Creating ground truth labels for training evaluation models</p>
</li>
</ul>
<h3 id="heading-step-4-learn-and-improve">Step 4: Learn and Improve</h3>
<p>Once you've identified failures, adjust the controllable parts of your AI system (the "configs"):</p>
<p><strong>Common configuration levers:</strong></p>
<ul>
<li><p><strong>Prompts</strong> — Add instructions, examples, constraints</p>
</li>
<li><p><strong>Retrieval</strong> — Change chunk size, top-k, reranking strategy</p>
</li>
<li><p><strong>Model</strong> — Switch models, adjust temperature, max tokens</p>
</li>
<li><p><strong>Context</strong> — Modify system instructions, add memory</p>
</li>
<li><p><strong>Post-processing</strong> — Add validation, formatting, safety filters</p>
</li>
</ul>
<p><strong>Example improvement cycle:</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Problem discovered: Chatbot missing key details</span>
failing_case = {
    <span class="hljs-string">"question"</span>: <span class="hljs-string">"What's your refund policy?"</span>,
    <span class="hljs-string">"response"</span>: <span class="hljs-string">"We offer refunds in certain cases."</span>,
    <span class="hljs-string">"issue"</span>: <span class="hljs-string">"Too vague, missing 30-day window and process"</span>
}

<span class="hljs-comment"># Root cause: Retrieval returning wrong docs</span>
retrieved_docs = retrieve_docs(failing_case[<span class="hljs-string">'question'</span>], top_k=<span class="hljs-number">5</span>)
<span class="hljs-comment"># Docs about "payment processing" ranked higher than "refund policy"</span>

<span class="hljs-comment"># Solution 1: Improve retrieval with reranking</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">retrieve_docs_v2</span>(<span class="hljs-params">question: str, top_k: int</span>) -&gt; str:</span>
    <span class="hljs-comment"># Initial retrieval</span>
    candidates = vector_search(question, top_k=<span class="hljs-number">20</span>)

    <span class="hljs-comment"># Rerank by relevance</span>
    reranked = rerank_by_relevance(question, candidates)

    <span class="hljs-keyword">return</span> reranked[:top_k]

<span class="hljs-comment"># Solution 2: Update prompt to require specificity</span>
prompt_v2 = <span class="hljs-string">f"""You are a helpful customer support agent.

Context: <span class="hljs-subst">{context}</span>

Question: <span class="hljs-subst">{question}</span>

Provide a clear, accurate answer based on the context. Include specific details like:
- Time windows (e.g., "within 30 days")
- Step-by-step processes
- Relevant links or contact methods

Answer:"""</span>

<span class="hljs-comment"># Re-evaluate</span>
new_response = answer_support_question_v2(failing_case[<span class="hljs-string">'question'</span>])
new_scores = evaluate_response(
    failing_case[<span class="hljs-string">'question'</span>],
    new_response,
    [<span class="hljs-string">"30 days"</span>, <span class="hljs-string">"full refund"</span>, <span class="hljs-string">"contact support"</span>]
)

<span class="hljs-comment"># Verify improvement</span>
<span class="hljs-keyword">assert</span> new_scores[<span class="hljs-string">'contains_key_info'</span>] == <span class="hljs-literal">True</span>
<span class="hljs-keyword">assert</span> new_scores[<span class="hljs-string">'helpfulness'</span>] &gt;= <span class="hljs-number">4</span>
</code></pre>
<p><strong>How this works:</strong> In this example, the chatbot's refund answer was too vague. After checking what went wrong, the problem was that the system retrieved docs about payment processing instead of the refund policy.</p>
<p>To resolve this, two changes can be made. First, retrieval is improved by grabbing twenty documents, then picking the best five. Second, the prompt is updated to ask for specific details like dates and steps.</p>
<p>After making these changes, the test runs again to confirm it works: the response now has all the key info and scores at least 4 out of 5. This process turns problems into fixes you can measure.</p>
<h3 id="heading-step-5-automate-and-repeat">Step 5: Automate and Repeat</h3>
<p>Integrate evaluation into your development workflow using CI/CD:</p>
<pre><code class="lang-yaml"><span class="hljs-comment"># .github/workflows/eval.yml</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">Continuous</span> <span class="hljs-string">Evaluation</span>

<span class="hljs-attr">on:</span>
  <span class="hljs-attr">pull_request:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span> [<span class="hljs-string">main</span>]

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">evaluate:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v2</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">evaluation</span> <span class="hljs-string">suite</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">python</span> <span class="hljs-string">run_evals.py</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Check</span> <span class="hljs-string">pass</span> <span class="hljs-string">rate</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">|
          PASS_RATE=$(python calculate_pass_rate.py)
          if (( $(echo "$PASS_RATE &lt; 0.85" | bc -l) )); then
            echo "Pass rate $PASS_RATE below threshold"
            exit 1
          fi
</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Upload</span> <span class="hljs-string">results</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/upload-artifact@v2</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">name:</span> <span class="hljs-string">eval-results</span>
          <span class="hljs-attr">path:</span> <span class="hljs-string">results/</span>
</code></pre>
<p><strong>Explanation:</strong> This GitHub Actions workflow automates your evaluation process so it runs automatically on every code change. The workflow triggers whenever someone opens a pull request or pushes code to the main branch. It checks out your code, runs your full evaluation suite using <code>run_</code><a target="_blank" href="http://evals.py"><code>evals.py</code></a>, then calculates what percentage of test cases passed. If the pass rate drops below 85%, the workflow fails and blocks the code from being merged, preventing quality regressions from reaching production.</p>
<p><strong>Key practices for automation:</strong></p>
<ul>
<li><p><strong>Version your test cases</strong> — Track them in Git alongside code</p>
</li>
<li><p><strong>Set quality gates</strong> — Block deployments if pass rate drops below threshold</p>
</li>
<li><p><strong>Monitor trends</strong> — Track metrics over time to catch gradual drift</p>
</li>
<li><p><strong>Alert on regressions</strong> — Notify team when specific test cases start failing</p>
</li>
<li><p><strong>Sample production traffic</strong> — Continuously add real queries to eval dataset</p>
</li>
</ul>
<h2 id="heading-tools-and-frameworks-you-can-use-for-evaluation">Tools and Frameworks you can use for evaluation</h2>
<p>Several platforms can help implement continuous evaluation. The one you choose depends on your stack and needs:</p>
<p><strong>If you're building with LLMs:</strong> Try LangSmith or Braintrust first. Both handle prompt versioning, evaluation datasets, and tracing out of the box.</p>
<p><strong>If you're doing traditional ML:</strong> Weights &amp; Biases is the industry standard. If you're in the Microsoft ecosystem, PromptFlow integrates well with Azure.</p>
<p><strong>If you want full control:</strong> Build custom with pytest for test execution and MLflow for tracking results. More setup, but you own the entire pipeline</p>
<h2 id="heading-what-a-complete-evaluation-loop-looks-like-in-practice">What a Complete Evaluation Loop Looks Like in Practice</h2>
<p>This walkthrough shows how a support chatbot improves after running a single cycle of evaluations. Each stage shows how evaluation signals guide improvements and lock in quality for the next release.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Stage</td><td>Before</td><td>After</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Test Case</strong></td><td>"Can I use your API on the free plan?"</td><td>Same question</td></tr>
<tr>
<td><strong>Model Response</strong></td><td>"Yes, you can access our API."</td><td>"Yes, you can access our API on the free plan with a rate limit of 100 requests per day. For higher limits, upgrade to Pro or Enterprise."</td></tr>
<tr>
<td><strong>Evaluation Scores</strong></td><td>contains_key_info=False, helpfulness=2/5</td><td>contains_key_info=True, helpfulness=5/5</td></tr>
<tr>
<td><strong>Issue Identified</strong></td><td>Missing crucial detail: free plan rate limits</td><td>N/A (issue resolved)</td></tr>
<tr>
<td><strong>Analysis / Root Cause</strong></td><td>Retrieval returned general API docs; prompt didn’t emphasize limitations</td><td>N/A (analysis led to fix)</td></tr>
<tr>
<td><strong>Fixes Applied</strong></td><td>1. Improved retrieval to fetch plan comparison docs2. Updated prompt: "Always mention plan-specific restrictions"3. Added validation: Response must mention rate limits if asked</td><td>N/A (fix implemented)</td></tr>
<tr>
<td><strong>Outcome</strong></td><td>Test failed, regression not prevented</td><td>Test passes, regression prevented</td></tr>
<tr>
<td><strong>Next Cycle Actions</strong></td><td>N/A</td><td>1. Add this test case to permanent suite 2. Look for similar issues (other plan-related questions) 3. Monitor production queries for this pattern</td></tr>
</tbody>
</table>
</div><p><strong>Next cycle:</strong></p>
<ul>
<li><p>Add this test case to permanent suite</p>
</li>
<li><p>Look for similar issues (other plan-related questions)</p>
</li>
<li><p>Monitor if this pattern appears in production queries</p>
</li>
</ul>
<h2 id="heading-key-takeaways">Key Takeaways</h2>
<ul>
<li><p><strong>AI systems need continuous evaluation, not one-time testing</strong> — Models drift, data changes, and silent failures accumulate without ongoing checks.</p>
</li>
<li><p><strong>Build evaluation into your workflow from day one</strong> — Don't wait until production failures force you to retrofit evaluation.</p>
</li>
<li><p><strong>Start simple, then scale</strong> — Begin with 10-20 test cases and basic metrics. Grow your suite as you encounter edge cases.</p>
</li>
<li><p><strong>Automate what you can, involve humans for what you can't</strong> — Use programmatic checks for speed, SME review for nuance.</p>
</li>
<li><p><strong>Treat evaluation datasets as first-class artifacts</strong> — Version control them, review changes, and grow them over time.</p>
</li>
<li><p><strong>Make evaluation a team sport</strong> — Product, engineering, and domain experts should all contribute test cases and evaluation criteria.</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Every developer has felt the relief of seeing "all tests passing." In AI systems, that reassurance is often misleading. A model can deploy successfully, meet performance benchmarks, and still produce incorrect, incomplete, or misleading outputs in ways traditional tests miss.</p>
<p>The evaluation flywheel addresses this gap by making model behavior testable in practice. Instead of assuming correctness, it forces the system to answer real questions, measures the quality of those answers, and highlights where performance degrades over time. This shifts evaluation from a one-off validation step into an ongoing part of development.</p>
<p>Evaluation won't eliminate uncertainty completely, but it makes failures visible before they reach users. With failures clearly exposed, teams stop guessing and start fixing based on results. This might mean adjusting prompts, improving retrieval logic, or refining evaluation criteria. Over time, this leads to AI systems that evolve in controlled ways rather than breaking silently.</p>
<p><strong>Resources for further reading</strong></p>
<ul>
<li><p><strong>Anthropic's eval guide</strong>: <a target="_blank" href="https://docs.anthropic.com/en/docs/build-with-claude/develop-tests">https://docs.anthropic.com/en/docs/build-with-claude/develop-tests</a></p>
</li>
<li><p><strong>OpenAI's evals framework</strong>: <a target="_blank" href="https://github.com/openai/evals">https://github.com/openai/evals</a></p>
</li>
<li><p><strong>LangChain evaluation</strong>: <a target="_blank" href="https://python.langchain.com/docs/guides/evaluation">https://python.langchain.com/docs/guides/evaluation</a></p>
</li>
<li><p><strong>Arize AI blog</strong>: Comprehensive resources on ML observability</p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Reduce Latency in Your Generative AI Apps with Gemini and Cloud Run ]]>
                </title>
                <description>
                    <![CDATA[ You've built your first Generative AI feature. Now what? When deploying AI, the challenge is no longer if the model can answer, but how fast it can answer for a user halfway across the globe. Low latency is not a luxury, it's a requirement for good u... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-reduce-latency-in-your-generative-ai-apps-with-gemini-and-cloud-run/</link>
                <guid isPermaLink="false">69398520ef68a953062588d1</guid>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Load Balancing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Amina Lawal ]]>
                </dc:creator>
                <pubDate>Wed, 10 Dec 2025 14:35:12 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1765370930321/e4256d2f-cab3-4ae3-9486-c6651e363366.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You've built your first Generative AI feature. Now what? When deploying AI, the challenge is no longer <em>if</em> the model can answer, but <em>how fast</em> it can answer for a user halfway across the globe. Low latency is not a luxury, it's a requirement for good user experience.</p>
<p>Today, we’ve moved beyond simple container deployments and into building <strong>Global AI Architectures</strong>. This setup leverages Google’s infrastructure to deliver context-aware, instant Gen AI responses anywhere in the world. If you're ready to get your hands dirty, let's build the future of global, intelligent features.</p>
<p>In this article, you’re not just going to deploy a container, you’ll be building a global AI architecture.</p>
<p>A global AI architecture is a design pattern that leverages a worldwide network to deploy and manage AI services, ensuring the fastest possible response time (low latency) for users, no matter where they are located. Instead of deploying a feature to a single region, this architecture distributes the service across multiple continents.</p>
<p>Most people may deploy a service to a single region. That’s fine for a local user, but physical distance, and the speed of light, creates terrible latency for everyone else. We are going to eliminate this problem by leveraging Google’s global network to deploy the service in a "triangle" of locations.</p>
<p>The generative AI service you’ll be building is a "Local Guide." This application will be designed to be deeply <strong>hyper-personalized</strong>, changing its personality and providing recommendations based on the user's detected geographical context. For example, if a user is in Paris, the guide will greet them warmly, mentioning their city and suggesting a local activity.</p>
<p>You’re going to build this service to achieve three critical goals:</p>
<ul>
<li><p><strong>Lives Almost Everywhere:</strong> Deployed to three continents simultaneously (USA, Europe, and Asia).</p>
</li>
<li><p><strong>Feels Instant:</strong> Uses Google's global fiber network and Anycast IP to route users to the nearest server, ensuring the lowest possible latency.</p>
</li>
<li><p><strong>Knows Where You Are:</strong> Automatically detects the user's location (without relying on client-side GPS permissions) to provide deeply personalized, location-aware suggestions.</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-phase-1-the-location-aware-code">Phase 1: The "Location-Aware" Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-phase-2-build-amp-push">Phase 2: Build &amp; Push</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-phase-3-the-triangle-deployment">Phase 3: The "Triangle" Deployment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-phase-4-the-global-network-the-glue">Phase 4: The Global Network (The Glue)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-phase-5-testing-teleportation-time">Phase 5: Testing (Teleportation Time)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion-the-global-ai-edge">Conclusion: The Global AI Edge</a></p>
</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>To follow along, you need:</p>
<ol>
<li><p><strong>A Google Cloud Project</strong> (with billing enabled).</p>
</li>
<li><p><strong>Google Cloud Shell</strong> (Recommended! No local setup required). Click the icon in the top right of the GCP Console that looks like a terminal prompt <code>&gt;_</code>.</p>
</li>
</ol>
<p><strong>Note</strong>: The project utilizes various Google Cloud services (Cloud Run, Artifact Registry, Load Balancer, Vertex AI), all of which require a Google Cloud Project with billing enabled to function. While many of these services offer a free tier, you must link a billing account to your project. Although a billing account is required, new Google Cloud users may be eligible for a <a target="_blank" href="https://console.cloud.google.com/freetrial?hl=en&amp;facet_utm_source=google&amp;facet_utm_campaign=%28organic%29&amp;facet_utm_medium=organic&amp;facet_url=https%3A%2F%2Fcloud.google.com%2Fsignup-faqs"><strong>free trial credit</strong></a> that should cover the cost of this lab. <a target="_blank" href="https://cloud.google.com/free/docs/free-cloud-features#free-trial">See credit program eligibility and coverage</a></p>
<h2 id="heading-phase-1-the-location-aware-code"><strong>Phase 1: The "Location-Aware" Code</strong></h2>
<p>We don’t want to build a generic chatbot, so we’ll be building a "Local Guide" that changes its personality based on where the request comes from.</p>
<h3 id="heading-enable-the-apis"><strong>Enable the APIs</strong></h3>
<p>To wake up the services, run this in your terminal:</p>
<pre><code class="lang-bash">gcloud services <span class="hljs-built_in">enable</span> \
  run.googleapis.com \
  artifactregistry.googleapis.com \
  compute.googleapis.com \
  aiplatform.googleapis.com \
  cloudbuild.googleapis.com
</code></pre>
<p>This command enables the necessary Google Cloud APIs for the project:</p>
<ul>
<li><p>Cloud Run (<a target="_blank" href="http://run.googleapis.com">run.googleapis.com</a>)</p>
</li>
<li><p>Artifact Registry (<a target="_blank" href="http://artifactregistry.googleapis.com">artifactregistry.googleapis.com</a>)</p>
</li>
<li><p>Compute Engine (<a target="_blank" href="http://compute.googleapis.com">compute.googleapis.com</a>)</p>
</li>
<li><p>Vertex AI (<a target="_blank" href="http://aiplatform.googleapis.com">aiplatform.googleapis.com</a>)</p>
</li>
<li><p>Cloud Build (<a target="_blank" href="http://cloudbuild.googleapis.com">cloudbuild.googleapis.com</a>).</p>
</li>
</ul>
<p>Enabling them ensures that the services we need are ready to be used.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764156603095/fb2ffd56-12e4-4b9f-ac2d-8fbb30fc0a2d.png" alt="Screenshot showing the Google Cloud APIs being successfully completed" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-create-and-populate-mainpyhttpmainpy">Create and Populate <a target="_blank" href="http://main.py"><code>main.py</code></a></h3>
<p>This is the brain of our service. In your Cloud Shell terminal, create a file named <a target="_blank" href="http://main.py"><code>main.py</code></a> and paste the following code into it:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> logging
<span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, request, jsonify
<span class="hljs-keyword">import</span> vertexai
<span class="hljs-keyword">from</span> vertexai.generative_models <span class="hljs-keyword">import</span> GenerativeModel

app = Flask(__name__)

<span class="hljs-comment"># Initialize Vertex AI</span>
PROJECT_ID = os.environ.get(<span class="hljs-string">"GOOGLE_CLOUD_PROJECT"</span>)
vertexai.init(project=PROJECT_ID)

<span class="hljs-meta">@app.route("/", methods=["GET", "POST"])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">generate</span>():</span>
    <span class="hljs-comment"># 1. Identify where the code is physically running (We set this ENV var later)</span>
    service_region = os.environ.get(<span class="hljs-string">"SERVICE_REGION"</span>, <span class="hljs-string">"unknown-region"</span>)

    <span class="hljs-comment"># 2. Identify where the user is (Header comes from Global Load Balancer)</span>
    <span class="hljs-comment"># Format typically: "City,State,Country"</span>
    user_location = request.headers.get(<span class="hljs-string">"X-Client-Geo-Location"</span>, <span class="hljs-string">"Unknown Location"</span>)

    model = GenerativeModel(<span class="hljs-string">"gemini-2.5-flash"</span>)

    <span class="hljs-comment"># 3. Construct a location-aware prompt</span>
    prompt = (
        <span class="hljs-string">f"You are a helpful local guide. The user is currently in <span class="hljs-subst">{user_location}</span>. "</span>
        <span class="hljs-string">"Greet them warmly mentioning their city, and suggest one "</span>
        <span class="hljs-string">"hidden gem activity to do nearby right now. Keep it under 50 words."</span>
    )

    <span class="hljs-keyword">try</span>:
        response = model.generate_content(prompt)
        <span class="hljs-keyword">return</span> jsonify({
            <span class="hljs-string">"ai_response"</span>: response.text,
            <span class="hljs-string">"meta"</span>: {
                <span class="hljs-string">"served_from_region"</span>: service_region,
                <span class="hljs-string">"user_detected_location"</span>: user_location
            }
        })
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"error"</span>: str(e)}), <span class="hljs-number">500</span>

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    app.run(debug=<span class="hljs-literal">True</span>, host=<span class="hljs-string">"0.0.0.0"</span>, port=int(os.environ.get(<span class="hljs-string">"PORT"</span>, <span class="hljs-number">8080</span>)))
</code></pre>
<p>It’s a simple Flask web application that relies entirely on a specific HTTP header (<code>X-Client-Geo-Location</code>) that the global load balancer will inject later in the process. This design choice keeps the Python code clean, fast, and focused on using the context that the powerful Google Cloud infrastructure provides. The script uses Vertex AI and the high-performance Gemini 2.5 Flash generative model.</p>
<p>This core logic of the application is a simple Flask web service. It does the following:</p>
<ul>
<li><p><strong>Initialization:</strong> Sets up the Flask app, logging, and initializes the Vertex AI client using the project ID.</p>
</li>
<li><p><strong>Context:</strong> It extracts two critical pieces of information: the <code>SERVICE_REGION</code> (where the code is physically running) from the environment variable, and the <code>X-Client-Geo-Location</code> (the user's detected location) from the request header, which will be injected by the global load balancer.</p>
</li>
<li><p><strong>AI Generation:</strong> It uses the high-performance <code>gemini-2.5-flash</code> model.</p>
</li>
<li><p><strong>Prompt Construction:</strong> A dynamic, location-aware prompt is built using the detected city to instruct Gemini to act as a helpful local guide and provide a personalized suggestion.</p>
</li>
<li><p><strong>Response:</strong> The response includes the AI's generated text and a <code>meta</code> section containing both the serving region and the user's detected location, which helps in verification.</p>
</li>
</ul>
<h3 id="heading-create-the-dockerfile"><strong>Create the</strong> <code>Dockerfile</code></h3>
<p>This Dockerfile tells Cloud Run how to build the Python application into a container image. Create a file named <code>Dockerfile</code> in the same directory as <code>main.py</code> and paste the following content into it:</p>
<pre><code class="lang-dockerfile"><span class="hljs-keyword">FROM</span> python:<span class="hljs-number">3.9</span>-slim

<span class="hljs-keyword">WORKDIR</span><span class="bash"> /app</span>
<span class="hljs-keyword">COPY</span><span class="bash"> main.py .</span>

<span class="hljs-comment"># Install Flask and Vertex AI SDK</span>
<span class="hljs-keyword">RUN</span><span class="bash"> pip install flask google-cloud-aiplatform</span>

<span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">"python"</span>, <span class="hljs-string">"main.py"</span>]</span>
</code></pre>
<p>Here’s what the code does:</p>
<ul>
<li><p>Starts with a lightweight Python base image <code>python:3.9-slim</code>.</p>
</li>
<li><p>Sets the working directory inside the container <code>WORKDIR /app</code>.</p>
</li>
<li><p>Copies your application code into the container.</p>
</li>
<li><p><code>RUN pip install...</code> installs the required Python packages: Flask for the web server and <code>google-cloud-aiplatform</code> for accessing the Gemini model.</p>
</li>
<li><p><code>CMD</code> specifies the command to run when the container starts.</p>
</li>
</ul>
<h2 id="heading-phase-2-build-amp-push"><strong>Phase 2: Build &amp; Push</strong></h2>
<p>Let's package this up. For efficiency and consistency, we’ll follow the best practice of Build Once, Deploy Many. We’ll build the container image once using Cloud Build and store it in Google's Artifact Registry. This guarantees that the same tested application code runs in New York, Belgium, and Tokyo.</p>
<p>First, sets an environment variable for your Google Cloud Project ID to simplify later commands.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># 1. Set your Project ID variable</span>
<span class="hljs-built_in">export</span> PROJECT_ID=$(gcloud config get-value project)
</code></pre>
<p>Then create a new Docker repository named <code>gemini-global-repo</code> in the <code>us-central1</code> region to store the application container image:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># 2. Create the repository</span>
gcloud artifacts repositories create gemini-global-repo \
    --repository-format=docker \
    --location=us-central1 \
    --description=<span class="hljs-string">"Repo for Global Gemini App"</span>
</code></pre>
<p>Using the <code>mkdir gemini-app</code> command, create and navigate into a directory where you should place your <a target="_blank" href="http://main.py"><code>main.py</code></a> and <code>Dockerfile</code>:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># 3. Prepare the Build Environment (Crucial Step! 💡). To ensure the build process only includes our necessary code and avoids including temporary files from Cloud Shell's home directory </span>
mkdir gemini-app
<span class="hljs-built_in">cd</span> gemini-app
</code></pre>
<p>Next, use <code>gcloud builds submit --tag</code> to build the container image from the files in the current directory and push the resulting image to the newly created Artifact Registry repository:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># 4. Build the image (This takes about 2 minutes)</span>
gcloud builds submit --tag us-central1-docker.pkg.dev/<span class="hljs-variable">$PROJECT_ID</span>/gemini-global-repo/region-ai:v
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764159484475/97a5b2b6-f3c2-4d1b-8bf8-6f302748e744.png" alt="Screenshot of Cloud Shell Editor showing Dockerfile and terminal build output." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><strong>NOTE:</strong> You might notice that we created the Artifact Registry repository (<code>gemini-global-repo</code>) in the <code>us-central1</code> region. This choice is purely for management and storage of the container image. When you create an image and push it to a regional Artifact Registry, the resulting image is still accessible globally. For this lab, <code>us-central1</code> serves as a reliable, central location for our single, canonical container image, the single source of truth, which is then pulled by Cloud Run in the three separate global regions.</p>
<h2 id="heading-phase-3-the-triangle-deployment"><strong>Phase 3: The "Triangle" Deployment</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764661657796/0890a47b-589a-4cf8-b537-bb61e5e65ee7.png" alt="Diagram of the Global AI Architecture Triangle Deployment." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>We’ll deploy the same image to three corners of the world, forming our "Triangle". This ensures that whether a user is in Lagos, London, or Tokyo, they’ll be geographically close to a server. This is the low-latency core of our architecture.</p>
<p>We’ll use Cloud Run to deploy our services. Cloud Run is a fully managed serverless platform on Google Cloud that enables you to run stateless containers via web requests or events. Crucially, it is serverless, meaning you don't manage any virtual machines, operating system updates, or scaling infrastructure. You provide a container image, and Cloud Run automatically scales it up (and down to zero) in the region you specify.</p>
<p>For this project, we’ll use its regional deployment capability to easily and consistently deploy the exact same container image to New York, Belgium, and Tokyo.</p>
<p><strong>Note:</strong> Setting it up primarily involves enabling the API (done in Phase 1) and using the <code>gcloud run deploy</code> command, which handles provisioning and managing the service in the specified region.</p>
<p>Now, we’ll proceed to deploy the single, canonical container image to three separate Cloud Run regions, forming the "Triangle Deployment".</p>
<p>First, set a variable for the image path, pointing to the image stored in Artifact Registry.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Define our image URL</span>
<span class="hljs-built_in">export</span> IMAGE_URL=us-central1-docker.pkg.dev/<span class="hljs-variable">$PROJECT_ID</span>/gemini-global-repo/region-ai:v1
</code></pre>
<pre><code class="lang-bash">
<span class="hljs-comment"># 1. Deploy to USA (New York)</span>
gcloud run deploy gemini-service \
    --image <span class="hljs-variable">$IMAGE_URL</span> \
    --region us-east4 \
    --set-env-vars SERVICE_REGION=us-east4 \
    --allow-unauthenticated

<span class="hljs-comment"># 2. Deploy to Europe (Belgium)</span>
gcloud run deploy gemini-service \
    --image <span class="hljs-variable">$IMAGE_URL</span> \
    --region europe-west1 \
    --set-env-vars SERVICE_REGION=europe-west1 \
    --allow-unauthenticated

<span class="hljs-comment"># 3. Deploy to Asia (Tokyo)</span>
gcloud run deploy gemini-service \
    --image <span class="hljs-variable">$IMAGE_URL</span> \
    --region asia-northeast1 \
    --set-env-vars SERVICE_REGION=asia-northeast1 \
    --allow-unauthenticated
</code></pre>
<p><code>gcloud run deploy gemini-service...</code> deploys the service. Key flags:</p>
<ul>
<li><p><code>--image \$IMAGE_URL</code> specifies the container image to use.</p>
</li>
<li><p><code>--region</code> specifies the deployment region (for example, <code>us-east4</code> for New York).</p>
</li>
<li><p><code>--set-env-vars SERVICE_REGION=...</code> injects an environment variable into the running container to let the <a target="_blank" href="http://main.py"><code>main.py</code></a> code know its own physical region.</p>
</li>
<li><p><code>--allow-unauthenticated</code> makes the service publicly accessible, as required for the Load Balancer to connect.</p>
</li>
</ul>
<p><strong>Note:</strong> The commands are repeated for Europe (<code>europe-west1</code>) and Asia (<code>asia-northeast1</code>) regions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764160600271/fbb6a810-7496-4b29-a405-b67a22a988ed.png" alt="Screenshot of Cloud Shell terminal showing the execution of the cloud run services." class="image--right mx-auto mr-0" width="600" height="400" loading="lazy"></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764160624375/dd4dc7e7-22a9-4d8b-a36c-7a0988068f57.png" alt="Cloud run Service Url (asia region) terminal screenshot showing the successful execution of the service" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764160656898/1b6ca938-9ce4-48f6-bb3b-d09900dbde68.png" alt="Cloud run Service Url (europe region) terminal screenshot showing the successful execution of the service" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764160665595/39c2524d-62c8-4187-8b8f-15f7ebbffba4.png" alt="Cloud run Service Url (us-east region) terminal screenshot showing the successful execution of the service" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><code>user_detected_location</code> is always "Unknown Location". This is expected. You are accessing the Cloud Run URLs directly, not via the global load balancer, so the <code>X-Client-Geo-Location</code> header is not yet being injected.</p>
<h2 id="heading-phase-4-the-global-network-the-glue"><strong>Phase 4: The Global Network (The Glue)</strong></h2>
<p>You are now ready to execute the steps to create the <strong>Global External HTTP Load Balancer</strong> infrastructure. This is the "magic" that stitches the three regional services together behind a single <strong>Anycast IP Address</strong>. The load balancer performs two critical functions:</p>
<ol>
<li><p><strong>Global Routing:</strong> It uses Google’s high-speed network to automatically route the user to the closest available region (for example, Tokyo user → Asia service).</p>
</li>
<li><p><strong>Context Injection:</strong> It dynamically adds the <code>X-Client-Geo-Location</code> header to the request, telling your code exactly where the user is<sup>.</sup></p>
</li>
</ol>
<h3 id="heading-the-global-ip"><strong>The Global IP</strong></h3>
<p><code>gcloud compute addresses create...</code> creates a single, global, static Anycast IP address (<code>gemini-global-ip</code>) that will serve as the single public entry point for users worldwide. That is</p>
<pre><code class="lang-bash">gcloud compute addresses create gemini-global-ip \
    --global \
    --ip-version IPV4
</code></pre>
<h3 id="heading-the-network-endpoint-groups-negs"><strong>The Network Endpoint Groups (NEGs)</strong></h3>
<p><code>gcloud compute network-endpoint-groups create...</code> creates a <strong>Serverless Network Endpoint Group (NEG)</strong> for each regional Cloud Run deployment. For example, <code>neg-us</code> is created in <code>us-east4</code> and points to the <code>gemini-service</code> in that region. These map your Cloud Run services to the Load Balancer's backend service:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># USA NEG</span>
gcloud compute network-endpoint-groups create neg-us \
    --region=us-east4 \
    --network-endpoint-type=serverless  \
    --cloud-run-service=gemini-service

<span class="hljs-comment"># Europe NEG</span>
gcloud compute network-endpoint-groups create neg-eu \
    --region=europe-west1 \
    --network-endpoint-type=serverless \
    --cloud-run-service=gemini-service

<span class="hljs-comment"># Asia NEG</span>
gcloud compute network-endpoint-groups create neg-asia \
    --region=asia-northeast1 \
    --network-endpoint-type=serverless \
    --cloud-run-service=gemini-service
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764161003478/549c959d-8ab5-45d6-a2ae-94129529b5b4.png" alt="Screenshot of Cloud Shell terminal showing the execution of global load balancer setup commands." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-the-backend-service-amp-routing"><strong>The Backend Service &amp; Routing</strong></h3>
<p>This is the load balancer's core, distributing traffic across your regions. Connect the NEGs to a global backend.</p>
<p><code>gcloud compute backend-services create...</code> creates the global backend service (<code>gemini-backend-global</code>), which is the core component that manages traffic distribution:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create the backend service</span>
gcloud compute backend-services create gemini-backend-global \
    --global \
    --protocol=HTTP
</code></pre>
<p><code>gcloud compute backend-services add-backend...</code> adds all three regional NEGs (<code>neg-us</code>, <code>neg-eu</code>, <code>neg-asia</code>) as backends to the global service. This tells the load balancer where all the services are located:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Add the 3 regions to the backend</span>
gcloud compute backend-services add-backend gemini-backend-global \
    --global --network-endpoint-group=neg-us --network-endpoint-group-region=us-east4
gcloud compute backend-services add-backend gemini-backend-global \
    --global --network-endpoint-group=neg-eu --network-endpoint-group-region=europe-west1
gcloud compute backend-services add-backend gemini-backend-global \
    --global --network-endpoint-group=neg-asia --network-endpoint-group-region=asia-northeast1
</code></pre>
<h3 id="heading-the-url-map-amp-frontend"><strong>The URL Map &amp; Frontend</strong></h3>
<p>Now we can finalize the connection.</p>
<p><code>gcloud compute url-maps create...</code> creates a URL Map (<code>gemini-url-map</code>) to direct all incoming traffic to the Backend Service:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create URL Map (Maps incoming requests to the backend service)</span>
gcloud compute url-maps create gemini-url-map \
    --default-service gemini-backend-global
</code></pre>
<p><code>gcloud compute target-http-proxies create...</code> creates an HTTP Proxy (<code>gemini-http-proxy</code>) that inspects the request and directs it based on the URL map.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create HTTP Proxy (The component that inspects the request headers)</span>
gcloud compute target-http-proxies create gemini-http-proxy \
    --url-map gemini-url-map
</code></pre>
<p><code>export VIP=...</code> retrieves the final, public IP address of the newly created Global IP and stores it in the <code>VIP</code> environment variable.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Get your IP Address variable</span>
<span class="hljs-built_in">export</span> VIP=$(gcloud compute addresses describe gemini-global-ip --global --format=<span class="hljs-string">"value(address)"</span>)
</code></pre>
<p><code>gcloud compute forwarding-rules create...</code> creates the final global Forwarding Rule (<code>gemini-forwarding-rule</code>). This links the Global IP (<code>$VIP</code>) to the HTTP Proxy and opens port 80 for public traffic.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create Forwarding Rule (Open port 80)</span>
gcloud compute forwarding-rules create gemini-forwarding-rule \
    --address=<span class="hljs-variable">$VIP</span> \
    --global \
    --target-http-proxy=gemini-http-proxy \
    --ports=80
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764161323862/299c6c43-9074-493c-95b1-2c08208aa2ec.png" alt="Cloud Shell terminal screenshot showing the successful execution of commands to create the gemini-backend-global service" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-phase-5-testing-teleportation-time"><strong>Phase 5: Testing (Teleportation Time)</strong></h2>
<p>Global load balancers take about <strong>5-7 minutes</strong> to propagate worldwide. This is how you verify that the global load balancer is working correctly:</p>
<ul>
<li><p>Using the single <strong>VIP</strong> (Virtual IP) address.</p>
</li>
<li><p><strong>Routing traffic</strong> to the nearest server.</p>
</li>
<li><p><strong>Injecting the</strong> <code>X-Client-Geo-Location</code> header to tell your code where the user is.</p>
</li>
</ul>
<h3 id="heading-1-get-your-global-ip"><strong>1. Get your Global IP</strong></h3>
<p>First, ensure your <code>VIP</code> variable is set and retrieve the final address:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"http://<span class="hljs-variable">$VIP</span>/"</span>
</code></pre>
<p>The output will be your single point of entry for the entire global architecture.</p>
<h3 id="heading-2-test-teleportation"><strong>2. Test "Teleportation"</strong></h3>
<p>These <code>curl</code> commands simulate a user requesting the service from different geographical locations by manually injecting the <code>X-Client-Geo-Location</code> header. This bypasses the need to be physically in those locations for testing.</p>
<h4 id="heading-simulate-europe-paris">Simulate Europe (Paris)</h4>
<p>We expect this to be served by the <code>europe-west1</code> region because it's the closest server.</p>
<pre><code class="lang-bash">curl -H <span class="hljs-string">"X-Client-Geo-Location: Paris,France"</span> http://<span class="hljs-variable">$VIP</span>/
</code></pre>
<p><em>Expected Output:</em> Gemini should say "Bonjour" and mention Paris. The <code>served_from_region</code> should be <code>europe-west1</code>.</p>
<p><strong>Simulate Asia (Tokyo)</strong></p>
<p>We expect this to be served by the <code>asia-northeast1</code> region.</p>
<pre><code class="lang-bash">curl -H <span class="hljs-string">"X-Client-Geo-Location: Tokyo,Japan"</span> http://<span class="hljs-variable">$VIP</span>/
</code></pre>
<p><em>Expected Output:</em> Gemini should mention Tokyo. The <code>served_from_region</code> should be <code>asia-northeast1</code>.</p>
<h4 id="heading-simulate-usa-new-york">Simulate USA (New York)</h4>
<p>We expect this to be served by the <code>us-east4</code> region.</p>
<pre><code class="lang-bash">curl -s -H <span class="hljs-string">"X-Client-Geo-Location: New York,USA"</span> http://<span class="hljs-variable">$VIP</span>/ | jq .
</code></pre>
<p><em>Expected Output:</em> Gemini should mention USA. The <code>served_from_region</code> should be <code>us-east4</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764161891891/ecc290ef-1c75-4088-b453-093a92b404ff.png" alt="Cloud Shell terminal screenshot showing the results of curl commands simulating users in Paris, Tokyo, and New York." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><strong>Note:</strong> The <code>| jq .</code> part is optional, but highly recommended as it formats the JSON output, making it much easier to read the <code>served_from_region</code> and <code>ai_response</code> details. If <code>jq</code> isn't available, you can just run <code>curl ...</code> without it.</p>
<h2 id="heading-conclusion-the-global-ai-edge">Conclusion: The Global AI Edge</h2>
<p>Congratulations! You have successfully built a sophisticated, global AI architecture that solves the challenges of latency and personalization for generative AI features. By combining the following technologies, you achieved two critical outcomes:</p>
<ul>
<li><p><strong>Guaranteed Low Latency:</strong> By deploying the <strong>Cloud Run</strong> service to a "Triangle" of global regions (USA, Europe, Asia) and using the <strong>Global External HTTP Load Balancer's Anycast IP</strong>, your users are automatically routed across Google’s private fiber network to the closest available server.</p>
</li>
<li><p><strong>Hyper-Personalization:</strong> The global load balancer was configured to dynamically inject the user's geographical location via the <code>X-Client-Geo-Location</code> header. This context was passed directly to the <strong>Gemini 2.5 Flash</strong> model, allowing it to act as a truly location-aware "Local Guide".</p>
</li>
</ul>
<p>This pattern allows you to scale intelligent features globally and is immediately applicable to any application where speed and context are essential, from real-time translations to hyper-local recommendations.</p>
<h3 id="heading-cleanup"><strong>Cleanup</strong></h3>
<p>Don't leave the meter running! Remember to execute the cleanup commands to ensure you don't incur unnecessary charges</p>
<pre><code class="lang-bash">gcloud run services delete gemini-service --region us-east4 --quiet
gcloud run services delete gemini-service --region europe-west1 --quiet
gcloud run services delete gemini-service --region asia-northeast1 --quiet
gcloud compute forwarding-rules delete gemini-forwarding-rule --global --quiet
gcloud compute addresses delete gemini-global-ip --global --quiet
gcloud compute backend-services delete gemini-backend-global --global --quiet
gcloud compute url-maps delete gemini-url-map --global --quiet
gcloud compute target-http-proxies delete gemini-http-proxy --global --quiet
</code></pre>
<h3 id="heading-resources">Resources</h3>
<ul>
<li><p>Google Cloud Shell Documentation</p>
</li>
<li><p><a target="_blank" href="https://www.google.com/search?q=https://cloud.google.com/vertex-ai/docs/generative-ai/learn/sdk">Vertex AI Generative AI SDK</a></p>
</li>
<li><p><a target="_blank" href="https://cloud.google.com/artifact-registry/docs">Artifact Registry Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://cloud.google.com/run/docs">Cloud Run Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://www.google.com/search?q=https://cloud.google.com/load-balancing/docs/load-balancing-overview%23external_http_s_load_balancing">Global External HTTP(S) Load Balancer Overview</a></p>
</li>
<li><p><a target="_blank" href="https://www.google.com/search?q=https://cloud.google.com/load-balancing/docs/negs/serverless-neg-overview">Serverless Network Endpoint Groups (NEGs)</a></p>
</li>
<li><p><a target="_blank" href="https://docs.cloud.google.com/run/docs/multiple-regions">Serve traffic from multiple regions</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A Game Developer’s Guide to Understanding Screen Resolution ]]>
                </title>
                <description>
                    <![CDATA[ Every game developer obsesses over performance, textures, and frame rates, but resolution is the quiet foundation that makes or breaks visual quality.  Whether you are building a pixel-art indie game or a high-fidelity 3D world, understanding how res... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-game-developers-guide-to-understanding-screen-resolution/</link>
                <guid isPermaLink="false">691de96a0dec4f292a0f8ff0</guid>
                
                    <category>
                        <![CDATA[ Game Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Accessibility ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Manish Shivanandhan ]]>
                </dc:creator>
                <pubDate>Wed, 19 Nov 2025 15:59:38 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1763567809746/3fb2c926-9602-4765-9ef4-5ea565e0e148.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Every game developer obsesses over performance, textures, and frame rates, but resolution is the quiet foundation that makes or breaks visual quality. </p>
<p>Whether you are building a pixel-art indie game or a high-fidelity 3D world, understanding how resolution works is essential. </p>
<p>It affects how your art assets scale, how your UI appears, and how your game feels on different screens. Yet, many developers still treat resolution as a simple number instead of a design decision.</p>
<p>Let’s learn what resolutions are and why it matters for game developers. </p>
<h2 id="heading-what-we-will-cover">What we will Cover</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-resolution-really-means">What Resolution Really Means</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-evolution-of-resolution-in-gaming">The Evolution of Resolution in Gaming</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-dpi-scaling-and-texture-clarity">DPI, Scaling, and Texture Clarity</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-resolution-vs-performance">Resolution vs. Performance</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-aspect-ratio-and-display-diversity">Aspect Ratio and Display Diversity</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-art-of-testing-in-4k-and-hdr">The Art of Testing in 4K and HDR</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-preparing-for-next-gen-displays">Preparing for Next-Gen Displays</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-resolution-really-means">What Resolution Really Means</h2>
<p>Resolution defines how many pixels a screen can display horizontally and vertically.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763470514266/2ba4689a-6e8d-423d-8da7-694bf7bc6d9e.png" alt="Screen Resolution Sizes" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>A monitor labelled 1920x1080 has 1920 pixels across and 1080 down, which equals over two million pixels in total. More pixels mean more visual detail but also more rendering work for the GPU.</p>
<p>In game development, that tradeoff is constant. Rendering at higher resolutions improves clarity but reduces frame rates unless your code and assets are optimized. </p>
<p>Many developers solve this by offering resolution scaling options in their games, letting players balance visual quality and performance.</p>
<p>It’s also important to distinguish between screen size and resolution. A 27-inch monitor and a 15-inch laptop can both run at 1080p, but the larger display will have bigger, less dense pixels. </p>
<p>This is where pixel density comes in. High-density displays pack more pixels per inch, creating smoother edges and sharper textures even at the same resolution.</p>
<h2 id="heading-the-evolution-of-resolution-in-gaming">The Evolution of Resolution in Gaming</h2>
<p>Games have evolved alongside display technology. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763514379811/7a5bef4e-5441-4b40-99cb-3d925865ac87.jpeg" alt="Gameplay Resolution" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Early consoles ran at 240p, then 480p during the SD era. The jump to HD with 720p and 1080p transformed game visuals. Suddenly, developers had to think about anti-aliasing, texture resolution, and UI scaling in new ways.</p>
<p>Today, 4K and HDR have become the standard for modern consoles and PCs. Developers now design with higher fidelity in mind, baking in lighting systems, shaders, and art pipelines that scale up to Ultra HD. </p>
<p>That’s why testing on different display resolutions isn’t just good practice, it’s critical for consistent player experience.</p>
<p>If you want to see how your game performs on large high-resolution displays, try testing it on a modern TV for PS5. These screens are optimized for 4K and 120Hz refresh rates, giving you a realistic look at how your game will appear in a living-room setup. </p>
<p>They also help you spot UI scaling issues, frame pacing problems, and HDR color mismatches that might go unnoticed on a typical monitor.</p>
<h2 id="heading-dpi-scaling-and-texture-clarity">DPI, Scaling, and Texture Clarity</h2>
<p>For web developers, <a target="_blank" href="https://en.wikipedia.org/wiki/Dots_per_inch">DPI</a> mostly affects how images scale. But for game developers, DPI connects directly to texture resolution and how art assets are perceived at different screen sizes. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763470672635/57795a33-7700-4aee-8dd4-aceb8b71dd49.jpeg" alt="DPI Levels" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>A sprite that looks crisp on a 1080p monitor might appear tiny or blurry on a 4K display if not properly scaled. Engines like <a target="_blank" href="https://www.freecodecamp.org/news/game-development-for-beginners-unity-course/">Unity</a> and Unreal handle this with dynamic scaling options, but understanding the underlying math helps. </p>
<p>When your display density doubles, each asset needs four times as many pixels to appear at the same size and sharpness. If you do not plan for this, your carefully crafted textures might look soft or misaligned on higher-resolution displays.</p>
<p>This is why UI systems in modern engines rely on resolution-independent units. In Unity, Canvas Scaler helps ensure your interface looks the same on every device. In Unreal, DPI scaling rules allow developers to maintain consistent HUD layouts. Getting this right means your game remains legible on everything from handhelds to 8K TVs.</p>
<h2 id="heading-resolution-vs-performance">Resolution vs Performance</h2>
<p>The biggest cost of higher resolution is GPU load. Rendering in 4K means pushing four times as many pixels as 1080p. Without proper optimization, frame rates can drop sharply. </p>
<p>That’s why many <a target="_blank" href="https://en.wikipedia.org/wiki/AAA_%28video_game_industry%29">AAA games</a> use resolution scaling techniques like temporal upsampling or DLSS. These methods render frames at a lower resolution and then use AI or interpolation to upscale them without losing clarity.</p>
<p>As a developer, you should test your game across multiple resolutions and aspect ratios. This helps ensure your render pipeline, shaders, and assets adapt smoothly. Tools like <a target="_blank" href="https://developer.nvidia.com/nsight-systems">NVIDIA Nsight</a> or Unreal’s built-in profiler show how resolution affects frame time and GPU usage.</p>
<p>If your game includes video content or cinematic sequences, also remember that video compression behaves differently at higher resolutions. Encoding 4K video requires significantly more bandwidth and storage, which can affect your build size and performance during playback.</p>
<h2 id="heading-aspect-ratio-and-display-diversity">Aspect Ratio and Display Diversity</h2>
<p>Aspect ratio determines the shape of the display.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763476458560/52decf37-c4f4-4927-96b8-1c6fd9be074c.jpeg" alt="Aspect Ratios" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Most modern games target 16:9, but 21:9 ultrawide and 32:9 super-ultrawide displays are becoming more popular. Developers must ensure their camera framing and UI layouts adapt accordingly.</p>
<p>When a game is locked to one ratio, black bars or stretching can occur. To fix this, adjust your camera’s field of view dynamically or provide safe viewport settings.</p>
<p>Engines like Unreal let you script these adjustments easily, while Unity’s Cinemachine system handles FOV scaling automatically.</p>
<p>Even TVs now vary in aspect ratio capabilities, especially with new mini LED and OLED technologies. Testing across multiple ratios ensures your game looks balanced and cinematic on every screen.</p>
<h2 id="heading-the-art-of-testing-in-4k-and-hdr">The Art of Testing in 4K and HDR</h2>
<p>4K and HDR introduce new layers of visual complexity. HDR displays show a wider range of brightness and color depth, which means lighting and textures can look completely different compared to SDR monitors. To handle this, calibrate your color grading pipeline and use tone mapping tools within your engine.</p>
<p>When working with HDR assets, always test your output on real hardware. Emulators and monitors often fail to reproduce true HDR contrast. A proper HDR-certified TV helps you identify overexposure, color clipping, and banding issues before release.</p>
<h2 id="heading-preparing-for-next-gen-displays">Preparing for Next-Gen Displays</h2>
<p>The display industry continues to evolve fast. 8K and high refresh rate panels are already entering mainstream markets. </p>
<p>For developers, this means thinking ahead. Designing scalable rendering systems, supporting dynamic resolution, and maintaining flexible UI layouts are now essential parts of modern game design.</p>
<p>As displays get sharper, player expectations rise too. Textures, shaders, and post-processing all need to support higher levels of detail without compromising performance. By understanding how resolution interacts with your pipeline, you can future-proof your games for years to come.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Resolution is more than a number on a settings menu. It is a design constraint, a performance factor, and a creative opportunity. As a game developer, mastering resolution helps you build experiences that look sharp, play smoothly, and scale across every device.</p>
<p>The next time you polish your textures or fine-tune your rendering settings, remember that every pixel counts. Understanding how resolution, scaling, and density interact will not only make your games more beautiful but also more accessible to every player, whether they’re gaming on a laptop, a monitor, or the living-room tv that brings your visuals to life in stunning detail.</p>
<p><em>Hope you enjoyed this article. Find me on</em> <a target="_blank" href="https://linkedin.com/in/manishmshiva"><em>Linkedin</em></a> <em>or</em> <a target="_blank" href="https://manishshivanandhan.com/"><em>visit my website</em></a><em>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Reduce Round Trip Time (RTT) with Next.js ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever wondered why some websites load almost immediately and others leave you looking at a blank screen, even when your internet connection is fast? In some cases, your internet speed may not be the issue. It is usually because of Round Trip ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-reduce-round-trip-time-rtt-with-nextjs/</link>
                <guid isPermaLink="false">690c78446959d1f714d81d45</guid>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chukwudi Nweze ]]>
                </dc:creator>
                <pubDate>Thu, 06 Nov 2025 10:28:20 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1762424304223/4d818ff7-0fe2-448d-8acd-3da092bc55a4.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever wondered why some websites load almost immediately and others leave you looking at a blank screen, even when your internet connection is fast? In some cases, your internet speed may not be the issue. It is usually because of Round Trip Time (RTT), which is how long it takes your browser to send a request to a server and get a response.</p>
<p>The internet depends on physical infrastructure: fiber-optic cables, satellites, and data centers often located thousands of kilometers away. Network requests travel at high speed, but they are still limited by the speed of light (around 300,000 km/s). For instance, a network request from Lagos, Nigeria to a server in San Francisco, USA travels more than 12,000 km, and takes about 150–200 milliseconds for a single round trip under ideal conditions. Multiply that by the 20–30 requests a typical web page makes (for HTML, CSS, images, APIs and more), and those milliseconds quickly add up to seconds of delay before a page fully loads.</p>
<p>In this article, we’ll explain in detail what Round Trip Time(RTT) is, why it is one of the most overlooked factors in web performance, and how you can use Next.js to minimize the number of RTTs to make your applications feel fast and responsive. You will learn how features like Server-Side Rendering (SSR), React Server Components (RSC), image optimization, and caching all work together to reduce Round Trip Time in a web page.</p>
<h2 id="heading-what-you-will-learn"><strong>What You will Learn</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-you-will-learn">What You will Learn</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-round-trip-time-rtt">What is Round Trip Time (RTT)?</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-how-distance-increases-round-trip-time">How Distance Increases Round Trip Time</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-round-trip-time-affects-web-performance">How Round Trip Time Affects Web Performance</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-why-client-side-rendering-feels-slower">Why Client-Side Rendering Feels Slower</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-reduce-round-trip-time-with-nextjs">How to Reduce Round Trip Time with Next.js</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-server-side-rendering-ssr">Server-Side Rendering (SSR)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-react-server-components-rsc">React Server Components (RSC)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-image-optimization">Image Optimization</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-caching-and-static-rendering">Caching and Static Rendering</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-trade-offs-across-nextjs-rendering-methods">Trade-offs Across Next.js Rendering Methods</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-when-to-use-each-rendering-method">When to Use Each Rendering Method</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-round-trip-time-rtt">What is Round Trip Time (RTT)?</h2>
<p>When you visit a website, the browser makes a network request to a server. The server processes the request and then sends a response back. The Round Trip Time is the complete duration of this journey in milliseconds, which includes:</p>
<ol>
<li><p><strong>Travel Time</strong>: The amount of time it took the network request to get to the server.</p>
</li>
<li><p><strong>Processing Time</strong>: The amount of time the server took to process the request.</p>
</li>
<li><p><strong>Return Time</strong>: The amount of time it took the response get back to the browser.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761405949671/1ceaadf4-5576-41ae-9f25-e846f41b3e67.png" alt="An illustration showing round-trip time (RTT) communication between a client and a server, where the client request takes about 100 ms to reach the server, and the server response takes about 200 ms to return to the client" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-distance-increases-round-trip-time">How Distance Increases Round Trip Time</h3>
<p>Round Trip Time depends heavily on the physical distance between the client and server. For example:</p>
<ul>
<li><p>A user in Lagos, Nigeria making a network request to a server in London that is about 5,000 km away might see a round trip time of 100–150 ms.</p>
</li>
<li><p>A server in San Francisco that is about 12,000 km could push the roundtrip time to 200–300 ms. The farther the server, the higher the round trip time.</p>
</li>
</ul>
<h2 id="heading-how-round-trip-time-affects-web-performance">How Round Trip Time Affects Web Performance</h2>
<p>Modern web pages make multiple network requests to load completely. Imagine loading an e-commerce product page that requires:</p>
<ul>
<li><p>1 network request for HTML (about 200 ms)</p>
</li>
<li><p>5 network requests for CSS/JavaScript (about 1,000 ms)</p>
</li>
<li><p>10 network requests for images (about 2,000 ms)</p>
</li>
<li><p>4 network requests for product data via API (about 800 ms)</p>
</li>
</ul>
<p>That shows that the product page will take 20 network requests to fully load, which is about 4 seconds of network delay.</p>
<p>The probability of bounce increases 32% as page load time goes from 1 second to 3 seconds (<a target="_blank" href="https://www.thinkwithgoogle.com/marketing-strategies/app-and-mobile/page-load-time-statistics/">Google/SOASTA Research, 2017</a>). That means about one-third of visitors leave before the page even loads.</p>
<h3 id="heading-why-client-side-rendering-feels-slower">Why Client-Side Rendering Feels Slower</h3>
<p>In client side rendering applications, each request adds a round trip time, and traditional client-side rendering (CSR) in React apps increases this:</p>
<ul>
<li><p>The browser downloads a minimal HTML shell and a large JavaScript bundle.</p>
</li>
<li><p>The JavaScript runs to fetch data and render the UI, requiring additional network requests.</p>
</li>
<li><p>Each API call adds another RTT, delaying the First Contentful Paint (FCP).</p>
</li>
</ul>
<p>First Contentful Paint (FCP) measures the time from when the user first navigated to the page to when any part of the page's content such as text, images,<code>&lt;svg&gt;</code> or <code>&lt;canvas&gt;</code> elements is rendered on the screen.</p>
<p>In CSR apps, FCP is delayed because the browser cannot display any meaningful content until JavaScript has finished loading, parsing, and executing the code needed to construct the UI. A regular CSR application may need 5 to 10 network round trips to get all the resources needed for the rendering of the UI, which can easily add several seconds of delay.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// pages/index.js (CSR)</span>
<span class="hljs-keyword">import</span> { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

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

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

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

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

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

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

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

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

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

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

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

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

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Products<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      {products.map((product) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{product.id}</span>&gt;</span>{product.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>In the code above, the page uses Incremental Static Regeneration (ISR). The <code>revalidate = 60</code> option is to regenerate the page every 60 seconds. When a user visits the page, the server serves the pre-rendered HTML instantly. The <code>next: { revalidate: 60 }</code> inside the <code>fetch()</code> means that data is cached for 60 seconds. After 60 seconds, the next request will trigger the server to regenerate a fresh data.</p>
<h2 id="heading-trade-offs-across-nextjs-rendering-methods">Trade-offs Across Next.js Rendering Methods</h2>
<p>With <strong>Server-Side Rendering (SSR)</strong>, the browser gets the complete rendered page in only one round round trip. On the other hand, this can also lead to increased server load and a high TTFB. The TTFB (Time to First Byte) is the duration it takes for a user to see the content displayed on their browser.</p>
<p>With <strong>Incremental Static Regeneration (ISR)</strong>, the page is pre-rendered and cached, thus getting an instantaneous response from the server. The page will be re-generated depending on a fixed period (such as every 60 seconds). The downside of this method is that users might see old content before it gets updated.</p>
<p>In <strong>Server Components</strong>, rendering takes place on the server, and only interactive parts are managed on the client. With this, server-side rendering are still maintained while still allowing client interactions. The only drawback is that developers need to be very particular while deciding what to run on the server and what to run on the client.</p>
<h2 id="heading-when-to-use-each-rendering-method">When to Use Each Rendering Method</h2>
<p><strong>Server-Side Rendering (SSR)</strong> should be applied to pages that updates frequently, such as dashboards, user profiles, and so on. SSR guarantee users to always see the latest data.  </p>
<p>As for <strong>Incremental Static Regeneration (ISR)</strong>, it should be applied to pages with infrequent changes, for instance, product listings, marketing pages, or blogs.  </p>
<p>Use <strong>Server Components</strong> when you want part of the page to render on the server while some sections run on the client. For instance, pages that need user interaction like search inputs or filters, while data fetching and rendering takes place on the server.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Round Trip Time (RTT) is one of the hidden factors behind slow page loads. Each network request adds a round trip, and these network delays build up as the browser fetches several resources like scripts, images, and data files. Next.js deals with this issue by minimizing the number of network requests that need to be done before the first content paint.</p>
<ul>
<li><p><strong>Server-Side Rendering (SSR)</strong> and <strong>React Server Components (RSC)</strong> shift data fetching and rendering to the server, which reduces client-side requests.</p>
</li>
<li><p><strong>Image optimization</strong> reduces image size and uses CDNs to deliver content faster from nearby servers.</p>
</li>
<li><p><strong>Caching and static rendering</strong> serve pre-generated pages instantly without further processing from the server.</p>
</li>
</ul>
<p>With these techniques, you can build web applications that load faster and feel more responsive, even for users who are far from your origin server or are on slower networks.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Do Global Execution Context and Temporal Dead Zone Work in JavaScript? ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever wondered how JavaScript runs your code behind the scenes, and how the Global Execution Context actually works? How does hoisting work for var, let, and const? Consider the code bellow: console.log('My age is', age) console.log('My name ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/global-execution-context-and-temporal-dead-zone-explained/</link>
                <guid isPermaLink="false">690b5691972e7bfdc1ed09c1</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Shejan Mahamud ]]>
                </dc:creator>
                <pubDate>Wed, 05 Nov 2025 13:52:17 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1762347165225/c7bd75a9-a819-41b6-8a35-4feecfb7cf58.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever wondered how JavaScript runs your code behind the scenes, and how the Global Execution Context actually works? How does hoisting work for <code>var</code>, <code>let</code>, and <code>const</code>?</p>
<p>Consider the code bellow:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'My age is'</span>, age)
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'My name is'</span>, name)
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'My country is'</span>, country)

<span class="hljs-keyword">var</span> age = <span class="hljs-number">24</span>
<span class="hljs-keyword">let</span> name = <span class="hljs-string">'Shejan'</span>
<span class="hljs-keyword">const</span> country = <span class="hljs-string">'Bangladesh'</span>
sayHi()
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sayHi</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hi!'</span>)
}
</code></pre>
<p>What do you think the output of this code will be?</p>
<p>The first line will probably print <code>undefined</code>, right? But what about the second line with <code>name</code>? This will throw a “<code>ReferenceError</code>: Cannot access <code>name</code> before initialization.” Why? Because <code>let</code> variables are hoisted but remain uninitialized in the temporal dead zone (TDZ) until their declaration line is reached.</p>
<p>The third line with <code>country</code> will never execute because the code stops at line 2 due to the <code>ReferenceError</code>. But if line 2 wasn’t there, line 3 would throw the same error for the same reason – <code>const</code> also stays in the TDZ.</p>
<p>And what about the <code>sayHi()</code> function call? If we could reach it, it would work perfectly and print "Hi!" because function declarations are fully hoisted with their complete body.</p>
<p>The main question: why and how is all this happening? Let's dive in and find answers to these questions.</p>
<h2 id="heading-heres-what-well-cover">Here’s What We’ll Cover:</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-does-the-global-execution-context-work">How Does the Global Execution Context Work?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-memory-creation-phase">Memory Creation Phase</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-flowchart">Understanding the Flowchart</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-exactly-is-hoisting">What Exactly is Hoisting?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-does-only-var-get-hoisted">Does Only var Get Hoisted?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-temporal-dead-zone-tdz-what-is-it-really">Temporal Dead Zone (TDZ) – What is it Really?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-function-hoisting-the-most-interesting-part">Function Hoisting – The Most Interesting Part!</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-happens-in-the-memory-phase">What Happens in the Memory Phase:</a></p>
</li>
</ul>
<h2 id="heading-how-does-the-global-execution-context-work">How Does the Global Execution Context Work?</h2>
<p>When we run any JavaScript code, the very first thing that happens is the creation of a <strong>Global Execution Context (GEC)</strong>. This is the fundamental concept behind JavaScript execution! This global execution context has two important phases:</p>
<ol>
<li><p><strong>Memory creation phase</strong> (memory phase)</p>
</li>
<li><p><strong>Code execution phase</strong> (thread phase)</p>
</li>
</ol>
<p>Let's look at what happens in each phase, one by one.</p>
<h2 id="heading-memory-creation-phase">Memory Creation Phase</h2>
<p>This is the preparation time. During this phase, the JavaScript engine scans through the entire code once (without executing it) and allocates memory for all variables and functions.</p>
<p>But here's where it gets interesting:</p>
<ul>
<li><p><strong>Variables</strong> (var, let, const) are given space in memory.</p>
<ul>
<li><p><code>var</code> is assigned the value <code>undefined</code>.</p>
</li>
<li><p><code>let</code> and <code>const</code> are placed in memory but remain uninitialized.</p>
</li>
<li><p>Functions (function declarations) are stored in memory with their complete code body.</p>
</li>
</ul>
</li>
</ul>
<p>So what happens in the memory phase for our example code?</p>
<pre><code class="lang-bash">age: undefined
name: &lt;uninitialized&gt;
country: &lt;uninitialized&gt;
sayHi: <span class="hljs-function"><span class="hljs-title">function</span></span>() { console.log(<span class="hljs-string">"Hi!"</span>); }
</code></pre>
<p>As you can see, even before a single line of code is executed, everything is already in memory! This entire process of lifting variables and functions into memory during the memory creation phase is called <strong>Hoisting</strong> – and this is what makes JavaScript execution seem "magical."</p>
<h3 id="heading-code-execution-phase">Code Execution Phase</h3>
<p>Now the real action begins! The JavaScript engine starts executing the code line by line.</p>
<p><strong>Line 1:</strong> <code>console.log("My age is", age);</code></p>
<ul>
<li><p>Looks for <code>age</code> in memory</p>
</li>
<li><p>Finds <code>undefined</code></p>
</li>
<li><p><strong>Output:</strong> <code>My age is undefined</code></p>
</li>
</ul>
<p>Line 2: <code>console.log("My name is", name);</code></p>
<ul>
<li><p>Looks for name in memory Finds that it exists in memory but hasn't been initialized yet (it's in the temporal dead zone, or TDZ – we'll explore this concept in detail later).</p>
</li>
<li><p>Output: <code>ReferenceError</code>: Cannot access <code>name</code> before initialization.</p>
</li>
</ul>
<p>The code execution stops right here! The remaining lines won't be executed.</p>
<p>But what would happen if Lines 2 and 3 weren't there?</p>
<p><strong>Line 4:</strong> <code>var age = 24;</code></p>
<ul>
<li>The value of <code>age</code> in memory gets updated from <code>undefined</code> to <code>24</code></li>
</ul>
<p><strong>Line 5:</strong> <code>let name = "Shejan";</code></p>
<ul>
<li><p><code>name</code> is now initialized with the value <code>"Shejan"</code></p>
</li>
<li><p>From this point forward, <code>name</code> can be accessed</p>
</li>
</ul>
<p><strong>Line 6:</strong> <code>const country = "Bangladesh";</code></p>
<ul>
<li><code>country</code> is initialized with the value <code>"Bangladesh"</code></li>
</ul>
<p><strong>Lines 7-9:</strong> Function call</p>
<ul>
<li><p>The <code>sayHi()</code> function was already loaded with its complete body during the memory phase.</p>
</li>
<li><p>When <code>sayHi()</code> is called, the JavaScript engine creates a new execution context specifically for this function.</p>
</li>
<li><p>This new context is known as a <strong>Function Execution Context (FEC)</strong> – it works as a child of the global execution context.</p>
</li>
</ul>
<p>This function execution context also has <strong>two phases</strong>, just like the global execution context:</p>
<ol>
<li><p><strong>Memory Creation Phase:</strong></p>
<ul>
<li><p>All variables, parameters, and nested functions inside the function are allocated in memory.</p>
</li>
<li><p>Function arguments are assigned.</p>
</li>
<li><p>A function scope is created and a reference link is established with the outer lexical environment (where the function was defined) – this link is called the <strong>scope chain</strong>. The scope chain is JavaScript's way of resolving variable names. It's like a chain of connected scopes. When JavaScript looks for a variable inside a function, it first checks the function's own scope. If it doesn't find the variable there, it moves up the chain to check the parent scope (where the function was defined), then the grandparent scope, and so on, until it reaches the global scope. This chain ensures that functions can access variables from their outer environments.</p>
</li>
</ul>
</li>
<li><p><strong>Code Execution (Thread) Phase:</strong></p>
<ul>
<li><p>Now the function body is executed line by line.</p>
</li>
<li><p><code>console.log("Hi!");</code> executes and prints <strong>"Hi!"</strong></p>
</li>
</ul>
</li>
</ol>
<p>Once the function execution is complete:</p>
<ul>
<li><p>That function execution context is popped off the call stack.</p>
</li>
<li><p>And control returns to the global execution context.</p>
</li>
</ul>
<p><strong>Note</strong>: When all code execution is complete, the global execution context is also popped off the call stack.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761988425883/33792916-eee7-4f87-b365-51a04290aa96.png" alt="Flowchart diagram illustrating JavaScript Global Execution Context workflow, showing the two phases - Memory Creation Phase where variables and functions are allocated, and Code Execution Phase where code runs line by line, including how Function Execution Context is created when functions are called" class="image--center mx-auto" width="2724" height="2715" loading="lazy"></p>
<p>The flowchart diagram above illustrates the JavaScript global execution context workflow, showing the two phases. In the memory creation phase, variables and functions are allocated, and in the code execution phase, the code runs line by line. It also shows how the function execution context is created when functions are called.</p>
<h2 id="heading-understanding-the-flowchart">Understanding the Flowchart</h2>
<p>The diagram above visualizes the complete journey of JavaScript code execution from start to finish.</p>
<p><strong>The flow begins</strong> when JavaScript execution starts and immediately creates a global execution context (GEC). This context then splits into two distinct phases, shown as a diamond in the diagram.</p>
<p><strong>On the left side - Memory Creation Phase:</strong> You can see three parallel branches showing how different types of declarations are handled:</p>
<ul>
<li><p><code>var</code> variables are allocated with the value <code>undefined</code></p>
</li>
<li><p><code>let</code> and <code>const</code> variables are allocated but remain uninitialized (in the temporal dead zone)</p>
</li>
<li><p>Function declarations are fully hoisted with their complete body</p>
</li>
</ul>
<p><strong>On the right side - Code Execution Phase:</strong> JavaScript now executes the code line by line. During execution:</p>
<ul>
<li><p>It accesses variable values from memory</p>
</li>
<li><p>If you try to access <code>let</code> or <code>const</code> before initialization, you get a ReferenceError (temporal dead zone)</p>
</li>
<li><p>If you access <code>var</code> before assignment, you get <code>undefined</code></p>
</li>
<li><p>When a function is called, a new Function Execution Context (FEC) is created</p>
</li>
</ul>
<p><strong>The Function Execution Context (FEC)</strong> (shown in the right branch) works as a child of the GEC and has its own Memory and Execution phases. After the function executes completely, the FEC is popped off the call stack and control returns to the GEC.</p>
<p><strong>Finally</strong>, when all code execution is complete, the GEC itself is popped from the call stack, and the program ends.</p>
<p>This visual representation helps you understand that JavaScript doesn't just read and run your code - it prepares everything first (Memory Phase) and then executes it systematically (Execution Phase).</p>
<h2 id="heading-what-exactly-is-hoisting">What Exactly is Hoisting?</h2>
<p>Hoisting is JavaScript's default behavior of moving variable and function declarations to memory before code execution begins.</p>
<p>Think of it this way – it appears as if all declarations automatically move to the very top of the code. Although the code doesn't physically move, the memory allocation happens first.</p>
<h2 id="heading-does-only-var-get-hoisted">Does Only <code>var</code> Get Hoisted?</h2>
<p>This surprises many people, but the answer is no. It's not just <code>var</code> that gets hoisted! This is a huge misconception among many developers.</p>
<p>The truth is that—<code>let</code>, <code>const</code>, and functions—everything gets hoisted! But their behavior is completely different. Let's dive into the details.</p>
<h3 id="heading-what-happens-with-var">What Happens with <code>var</code>?</h3>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(name) <span class="hljs-comment">// undefined</span>
<span class="hljs-keyword">var</span> name = <span class="hljs-string">'Rahim'</span>
<span class="hljs-built_in">console</span>.log(name) <span class="hljs-comment">// "Rahim"</span>
</code></pre>
<p>Variables declared with <code>var</code>:</p>
<ul>
<li><p>Get hoisted</p>
</li>
<li><p>Are initialized with <code>undefined</code></p>
</li>
<li><p>Exist in global scope or function scope</p>
</li>
<li><p>Can be accessed before declaration (doesn't throw an error)</p>
</li>
</ul>
<h3 id="heading-what-happens-with-let">What Happens with <code>let</code>?</h3>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(name) <span class="hljs-comment">// ReferenceError: Cannot access 'name' before initialization</span>
<span class="hljs-keyword">let</span> name = <span class="hljs-string">'Rahim'</span>
<span class="hljs-built_in">console</span>.log(name) <span class="hljs-comment">// "Rahim"</span>
</code></pre>
<p>Is this magic? No! Actually, <code>let</code> does get hoisted, but it's stuck in a special state called the temporal dead zone!</p>
<p>Space is allocated in memory, but it's not initialized. So if you try to access it before declaration, JavaScript says – "Hey, the variable exists, but you can't use it yet!"</p>
<h3 id="heading-what-happens-with-const">What Happens with <code>const</code>?</h3>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(age) <span class="hljs-comment">// ReferenceError: Cannot access 'age' before initialization</span>
<span class="hljs-keyword">const</span> age = <span class="hljs-number">24</span>
<span class="hljs-built_in">console</span>.log(age) <span class="hljs-comment">// 24</span>
</code></pre>
<p>The behavior of <code>const</code> is exactly the same as <code>let</code>:</p>
<ul>
<li><p>Gets hoisted</p>
</li>
<li><p>Stays in the TDZ until declaration</p>
</li>
<li><p>Exists in block scope</p>
</li>
<li><p>Plus, once assigned, it cannot be reassigned</p>
</li>
</ul>
<h2 id="heading-temporal-dead-zone-tdz-what-is-it-really">Temporal Dead Zone (TDZ) – What is it Really?</h2>
<p>The Temporal Dead Zone is the time period or zone when a variable exists in memory (due to hoisting) but hasn't been initialized yet. During this time, the variable is essentially "dead" – meaning that you cannot access it.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ← TDZ starts for x and y</span>
<span class="hljs-built_in">console</span>.log(x) <span class="hljs-comment">// ReferenceError - still in TDZ</span>
<span class="hljs-built_in">console</span>.log(y) <span class="hljs-comment">// ReferenceError - still in TDZ</span>

<span class="hljs-comment">// TDZ continues...</span>
<span class="hljs-keyword">let</span> x = <span class="hljs-number">10</span> <span class="hljs-comment">// ← x's TDZ ends at this line</span>
<span class="hljs-keyword">const</span> y = <span class="hljs-number">20</span> <span class="hljs-comment">// ← y's TDZ ends at this line</span>

<span class="hljs-built_in">console</span>.log(x) <span class="hljs-comment">// 10 - can access now</span>
<span class="hljs-built_in">console</span>.log(y) <span class="hljs-comment">// 20 - can access now</span>
</code></pre>
<p>The entire concept of TDZ is to force us to write better code. Using variables before declaring them is a bad practice, and TDZ prevents us from doing that.</p>
<h2 id="heading-function-hoisting-the-most-interesting-part">Function Hoisting – The Most Interesting Part!</h2>
<p>Hoisting with functions is even more interesting and powerful:</p>
<pre><code class="lang-javascript">greet() <span class="hljs-comment">// "Hello World!" - Perfect! It works!</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello World!'</span>)
}
</code></pre>
<p>How is this possible? Because function declarations are completely hoisted! This means not just the name, but the entire function body is lifted into memory. That's why it can be called even before the declaration.</p>
<p>But wait! Not all functions work this way.</p>
<h3 id="heading-with-function-expressions">With Function Expressions:</h3>
<pre><code class="lang-javascript">greet() <span class="hljs-comment">// TypeError: greet is not a function</span>

<span class="hljs-keyword">var</span> greet = <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>)
}
</code></pre>
<p>What happened here? <code>greet</code> was hoisted as a variable and received the value <code>undefined</code>. It wasn't hoisted as a function! So when you try to call it, you get an error. In other words, it's hoisted as a variable (assigned <code>undefined</code>), but the function body isn't loaded into memory.</p>
<h3 id="heading-with-arrow-functions">With Arrow Functions:</h3>
<pre><code class="lang-javascript">sayHello() <span class="hljs-comment">// ReferenceError (if let/const is used)</span>

<span class="hljs-keyword">const</span> sayHello = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello!'</span>)
}
</code></pre>
<p>Arrow functions behave just like function expressions. They follow variable rules.</p>
<p>Let's clear everything up with a complete example:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(a) <span class="hljs-comment">// undefined (var hoisting)</span>
<span class="hljs-built_in">console</span>.log(b) <span class="hljs-comment">// ReferenceError (TDZ)</span>
<span class="hljs-built_in">console</span>.log(c) <span class="hljs-comment">// ReferenceError (TDZ)</span>
multiply(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>) <span class="hljs-comment">// 6 (function hoisting)</span>
add(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>) <span class="hljs-comment">// TypeError (function expression)</span>

<span class="hljs-keyword">var</span> a = <span class="hljs-number">10</span>
<span class="hljs-keyword">let</span> b = <span class="hljs-number">20</span>
<span class="hljs-keyword">const</span> c = <span class="hljs-number">30</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">multiply</span>(<span class="hljs-params">x, y</span>) </span>{
  <span class="hljs-keyword">return</span> x * y
}

<span class="hljs-keyword">var</span> add = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">x, y</span>) </span>{
  <span class="hljs-keyword">return</span> x + y
}
</code></pre>
<h2 id="heading-what-happens-in-the-memory-phase">What Happens in the Memory Phase:</h2>
<pre><code class="lang-javascript">a: <span class="hljs-literal">undefined</span>
<span class="hljs-attr">b</span>: &lt;uninitialized&gt;
c: &lt;uninitialized&gt;
multiply: function(x, y) { return x * y; }
add: undefined
</code></pre>
<p>This snapshot represents the state of memory before any code is executed. Here's what each line means:</p>
<p><code>a: undefined</code> - Since <code>a</code> is declared with <code>var</code>, it gets hoisted and immediately assigned the value <code>undefined</code>. This is why you get <code>undefined</code> instead of an error when you try to access <code>a</code> before its declaration line.</p>
<p><code>b: &lt;uninitialized&gt;</code> - The variable <code>b</code> is declared with <code>let</code>, so it's hoisted and memory is allocated for it, but it remains uninitialized. It's in the Temporal Dead Zone (TDZ). Attempting to access it before the declaration line will throw a <code>ReferenceError</code>.</p>
<p><code>c: &lt;uninitialized&gt;</code> - Similarly, <code>c</code> is declared with <code>const</code> and follows the same behavior as <code>let</code>. It's hoisted but stays uninitialized in the TDZ until the declaration line is reached.</p>
<p><code>multiply: function(x, y) { return x * y; }</code> - This is a function declaration, so it's fully hoisted with its complete body. The entire function is stored in memory and ready to be called even before the JavaScript engine reaches its declaration in the code. This is why <code>multiply(2, 3)</code> works perfectly and returns <code>6</code>.</p>
<p><code>add: undefined</code> - Here's the crucial difference! Even though <code>add</code> will eventually store a function, it's declared using <code>var add = function() {...}</code> (a function expression). During the memory phase, only the variable <code>add</code> is hoisted and initialized with <code>undefined</code>. The actual function body isn't assigned until the execution phase reaches line 11. This is why calling <code>add(2, 3)</code> before the assignment throws a <code>TypeError: add is not a function</code> - you're essentially trying to execute <code>undefined()</code>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Understanding JavaScript's execution mechanism is fundamental to becoming a proficient developer. Let's recap the essential concepts we've explored:</p>
<p><strong>The Global Execution Context (GEC)</strong> is the foundation of JavaScript execution. Every time you run JavaScript code, the GEC is created first. It works in two critical phases:</p>
<ul>
<li><p><strong>Memory Creation Phase</strong>: JavaScript prepares by scanning the code and allocating memory for variables and functions.</p>
</li>
<li><p><strong>Code Execution Phase</strong>: JavaScript runs your code line by line.</p>
</li>
</ul>
<p><strong>Hoisting is universal</strong> - not just limited to <code>var</code>. Here's how different declarations are hoisted:</p>
<ul>
<li><p><code>var</code> variables are hoisted and initialized with <code>undefined</code>.</p>
</li>
<li><p><code>let</code> and <code>const</code> are hoisted but remain uninitialized in the TDZ.</p>
</li>
<li><p>Function declarations are fully hoisted with their entire body.</p>
</li>
<li><p>Function expressions and arrow functions follow variable hoisting rules</p>
</li>
</ul>
<p><strong>The Temporal Dead Zone (TDZ)</strong> is JavaScript's built-in safety mechanism. It exists from the start of the scope until the variable declaration line is reached. The TDZ prevents us from accessing <code>let</code> and <code>const</code> variables before they're declared, encouraging better coding practices and helping us avoid bugs.</p>
<p><strong>Function hoisting behavior varies</strong>:</p>
<ul>
<li><p>Function declarations can be called before they appear in code.</p>
</li>
<li><p>Function expressions behave like variables and cannot be called before assignment.</p>
</li>
<li><p>Arrow functions follow the same rules as function expressions.</p>
</li>
</ul>
<p><strong>Why does this matter?</strong> Understanding these concepts helps you:</p>
<ul>
<li><p>Predict how your code will behave before running it.</p>
</li>
<li><p>Avoid common errors like <code>ReferenceError</code> and <code>TypeError</code>.</p>
</li>
<li><p>Write cleaner, more maintainable code.</p>
</li>
<li><p>Debug issues faster when they arise.</p>
</li>
<li><p>Make informed decisions about when to use <code>var</code>, <code>let</code>, or <code>const</code>.</p>
</li>
</ul>
<p><strong>The key takeaway</strong>: <strong>JavaScript doesn't just execute your code - it prepares first, then executes.</strong> The memory phase sets up the stage, and the execution phase performs the show. Master this two-phase process, and you'll have a solid understanding of how JavaScript works under the hood.</p>
<p>Now you're equipped with the knowledge to write better JavaScript code and understand exactly what's happening behind the scenes. Keep practicing these concepts, and they'll become second nature!</p>
<p>Happy Coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Optimize a Graphical React Codebase — Optimize d3-zoom and dnd-kit Code ]]>
                </title>
                <description>
                    <![CDATA[ Miro and Figma are online collaborative canvas tools that became very popular during the pandemic. Instead of using sticky notes on a physical wall, you can add a virtual post—and an array of other things—to a virtual canvas. This lets teams collabor... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-optimize-a-graphical-react-codebase/</link>
                <guid isPermaLink="false">68f0e6e94d664bb368c83f39</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Cedd Burge ]]>
                </dc:creator>
                <pubDate>Thu, 16 Oct 2025 12:36:57 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1760617553059/99fd830f-39a8-4067-9727-e9b35850168d.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Miro and Figma are online collaborative canvas tools that became very popular during the pandemic. Instead of using sticky notes on a physical wall, you can add a virtual post—and an array of other things—to a virtual canvas. This lets teams collaborate virtually in ways that feel familiar from the physical world.</p>
<p>I previously wrote an article showing <a target="_blank" href="https://www.freecodecamp.org/news/how-to-create-a-figma-miro-style-canvas-with-react-and-typescript/">how to create a Figma/Miro Clone in React and TypeScript</a>. The <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-part-3">code in the article</a> was designed to be as easy to understand, and in this article, we’re going to optimize it. The code used <a target="_blank" href="https://dndkit.com/">DndKit</a> for dragging and dropping, and <a target="_blank" href="https://github.com/d3/d3-zoom">D3 Zoom</a> for panning and zooming. There were four components (<code>App</code>, <code>Canvas</code>, <code>Draggable</code> and <code>Addable</code>), and about 250 lines of code. You do not need to read the original article to understand this one.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759863968693/38c8784c-47c8-46e0-9f06-0567c0ebf668.gif" alt="38c8784c-47c8-46e0-9f06-0567c0ebf668" class="image--center mx-auto" width="1026" height="730" loading="lazy"></p>
<p>Standard optimizations such as <code>useCallback</code>, <code>memo</code>, and similar made it about twice as fast when dragging, but made no difference for panning and zooming. More creative/intensive optimizations made it about ten times as fast in most cases.</p>
<p>You can see the optimized code on <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised">GitHub</a> and there is a <a target="_blank" href="https://ceddlyburge.github.io/react-figma-miro-canvas-optimised/">live demo on GitHub pages</a> to test out the speed with 100,000 cards.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-measure-performance-in-react-apps">How to Measure Performance in React Apps</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-investigate-the-performance">How to Investigate the performance</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-optimize-panning-and-zooming-the-canvas">How to Optimize Panning and Zooming the Canvas</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-optimize-dragging-cards-around-the-canvas">How to Optimize Dragging Cards Around the Canvas</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-results">Results</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary">Summary</a></p>
</li>
</ul>
<h2 id="heading-how-to-measure-performance-in-react-apps">How to Measure Performance in React Apps</h2>
<p>There are three common ways to measure performance in React Apps</p>
<ul>
<li><p><a target="_blank" href="https://chromewebstore.google.com/detail/react-developer-tools">React Dev Tools profiler</a></p>
</li>
<li><p><a target="_blank" href="https://developer.chrome.com/docs/devtools/performance/overview">Chrome Dev Tools profiler</a>, especially using <a target="_blank" href="https://www.debugbear.com/blog/favourite-devtools-features-in-2025#add-custom-tracks-to-performance-recordings">custom tracks</a></p>
</li>
<li><p><a target="_blank" href="https://react.dev/reference/react/Profiler">Profiler component</a></p>
</li>
</ul>
<p>These tools are all great, but none of them are quite the right fit in this case. In most codebases, the time spent executing JavaScript code (both our code and that of the React framework) is the primary issue. However, after all your code has run and React has updated the Dom, the browser still has a lot of work to do:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760025146277/7ae9ef2a-e248-491b-a07d-c674694d3fa9.png" alt="7ae9ef2a-e248-491b-a07d-c674694d3fa9" class="image--center mx-auto" width="898" height="219" loading="lazy"></p>
<p>In this case, this browser layout and rendering time was significant, and is not accounted for by the React profiling.</p>
<p>You can use custom tracks in the Chrome dev tools profiler, but it is very cumbersome to use.</p>
<p>For us, the JavaScript <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Performance">performance API</a> is the best option, which gives results that are closer to those experienced by the user, and is relatively easy to use.</p>
<p>First, we make a call to <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Performance/mark"><code>performance.mark</code></a> in the event handler that starts the action, with a string to describe the time point. For example, when starting a zoom or pan operation:</p>
<pre><code class="lang-javascript">zoomBehavior.on(<span class="hljs-string">"start"</span>, <span class="hljs-function">() =&gt;</span> {
    performance.mark(<span class="hljs-string">'zoomingOrPanningStart'</span>);
}
</code></pre>
<p>Then, in a <code>useEffect</code> hook, we call <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Performance/mark"><code>performance.mark</code></a> again, and call <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Performance/measure"><code>performance.measure</code></a> to calculate the time between the two points:</p>
<pre><code class="lang-javascript">useEffect(<span class="hljs-function">() =&gt;</span> {
    performance.mark(<span class="hljs-string">'zoomingOrPanningEnd'</span>);
    performance.measure(<span class="hljs-string">'zoomingOrPanning'</span>, <span class="hljs-string">'zoomingOrPanningStart'</span>, <span class="hljs-string">'zoomingOrPanningEnd'</span>);
});
</code></pre>
<p>The <a target="_blank" href="https://react.dev/reference/react/useEffect">React docs</a> states that <code>useEffect</code> usually fires after the browser has painted the updated screen, which is what we want.</p>
<p>This isn't perfect, and will vary depending on the machine specifications, and what else the machine is doing at the time, but it was good enough to verify which optimizations worked best. It is possible to go further if you need to. For example, using <a target="_blank" href="https://filiphric.com/testing-frontend-performance-with-cypress">Cypress to automate and profile scenarios</a>, potentially running many times to get a good mean, or using <a target="_blank" href="https://www.browserstack.com/guide/performance-testing-with-cypress">Browserstack to test on a variety of devices</a>.</p>
<h2 id="heading-how-to-investigate-the-performance">How to Investigate the Performance</h2>
<p>Most of the investigation involved using the <a target="_blank" href="https://chromewebstore.google.com/detail/react-developer-tools">React Dev Tools profiler</a> to record profiles of user interactions.</p>
<p>The performance data shows how many commits there were in the profile, and how long each one took, which is a great way to see if there are too many commits.</p>
<p>Each commit displays a flame chart showing which components rendered and why they re-rendered. This makes it much easier to find ways to avoid the re-rendering, and to check that memoization strategies are working as expected. This does have some caveats though. It often says <a target="_blank" href="https://github.com/facebook/react/issues/19732">'The parent component rendered'</a>, which is misleading default text for when it doesn’t understand what happened (and is often due to a change in a parent context). It also says things like 'hook 9 changed', which makes it time consuming to work out exactly which hook changed.</p>
<p>The flame chart also shows how long each component took to render. This helps target problem components that we need to focus on.</p>
<h2 id="heading-how-to-optimize-panning-and-zooming-the-canvas">How to Optimize Panning and Zooming the Canvas</h2>
<p>The original <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-part-3/blob/main/src/Canvas.tsx">Canvas</a> element used the CSS transform <code>translate3d(x, y, k)</code> to pan and zoom the canvas. This works, but it doesn't scale child elements, so when the zoom changes, all the cards on the canvas have to be re-rendered with a new CSS transform for the new zoom level (<a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-part-3/blob/97935f5b03ecff2f0732f6138e173a0c5e71a1ed/src/Draggable.tsx#L31"><code>scale(${canvasTransform.k})</code></a>).</p>
<pre><code class="lang-javascript"> &lt;div
    ...
    className=<span class="hljs-string">"canvas"</span>
    style={{
        <span class="hljs-attr">transform</span>: <span class="hljs-string">`translate3d(<span class="hljs-subst">${transform.x}</span>px, <span class="hljs-subst">${transform.y}</span>px, <span class="hljs-subst">${transform.k}</span>px)`</span>,
        ...
    }}&gt;
    ...
&lt;/div&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
    <span class="hljs-attr">className</span>=<span class="hljs-string">"card"</span>
    <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">...</span>
        <span class="hljs-attr">transform:</span> `<span class="hljs-attr">scale</span>(${<span class="hljs-attr">canvasTransform.k</span>})`,
    }}&gt;</span>
    ...
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>I changed this to use <code>translateX(x) translateY(y) scale(k)</code>, which has the same effect, but does scale child elements. This way, when the zoom changes, none of the cards will be re-rendered (the <code>style</code> of the <code>card</code> component no longer uses the <code>canvasTransform.k</code>).</p>
<pre><code class="lang-javascript"> &lt;div
    ...
    className=<span class="hljs-string">"canvas"</span>
    style={{
        <span class="hljs-attr">transform</span>: <span class="hljs-string">`translateX(<span class="hljs-subst">${transform.x}</span>px) translateY(<span class="hljs-subst">${transform.y}</span>px) scale(<span class="hljs-subst">${transform.k}</span>)`</span>,
        ...
    }}&gt;
    ...
&lt;/div&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
    <span class="hljs-attr">className</span>=<span class="hljs-string">"card"</span>
    <span class="hljs-attr">...</span>
&lt;/<span class="hljs-attr">div</span>&gt;</span></span>
</code></pre>
<p>The <code>Canvas</code> still needed to re-render whenever the pan or zoom changed, and it is possible to prevent this with <code>useRef</code>, and updating the CSS transform with direct JavaScript Dom manipulation in the <a target="_blank" href="https://d3js.org/d3-zoom">d3-zoom</a> event handler. This doesn’t make a significant improvement to the performance though, and is a definite hack, so the trade off is not worthwhile.</p>
<p>Both zooming and panning get a bit slower when the canvas is zoomed very far out and there are (a lot) more cards visible on the screen, just due to the browser having to render them all. It's still workable at 100,000 cards though. There are things you can do about this. An easy option is limiting the maximum zoom extent. This is a functional change, so potentially something that doesn’t meet requirements, but it is easy to do in d3-zoom using <a target="_blank" href="https://d3js.org/d3-zoom#zoom_scaleExtent"><code>scaleExtent</code></a>:</p>
<pre><code class="lang-javascript">zoom&lt;HTMLDivElement&gt;().scaleExtent([<span class="hljs-number">0.1</span>, <span class="hljs-number">100</span>])
</code></pre>
<p>Another option is to create a bitmap for very low zoom levels and render that as a single element. This may be difficult, but it means that there will be no change to the functionality.</p>
<h2 id="heading-how-to-optimize-dragging-cards-around-the-canvas">How to Optimize Dragging Cards Around the Canvas</h2>
<h3 id="heading-starting-a-drag"><strong>Starting a drag</strong></h3>
<p>The <code>useDraggable</code> hook from <code>DndContext</code> causes some re-renders when starting a drag operation.</p>
<p>It is possible to improve this by changing the <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/Draggable.tsx"><code>Draggable</code></a> component to just have this hook (and the things that use it) and having a <code>DraggableInner</code> component for everything else (inside a <code>memo</code>). This works well for reducing the re-renders, in that the <code>DraggableInner</code> almost never get re-rendered, and improves the speed of starting a drag operation. However, it was still fairly slow, and the time was all under the <code>DndContext</code>.</p>
<p>A better option is to create a new <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/NonDraggable.tsx"><code>NonDraggable</code></a> component, that looks exactly like the <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/Draggable.tsx"><code>Draggable</code></a> component, but does not hook up with <code>DndContext</code>. These cards are shown on the Canvas, and have an <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/56d0c8256350ef3a0d8f50cc442305bd6c9d03c1/src/NonDraggable.tsx#L10"><code>onMouseEnter</code></a> event, to swap in the <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/Draggable.tsx"><code>Draggable</code></a> component for the active card, so that dragging continued to work.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> onMouseEnter = useCallback(<span class="hljs-function">() =&gt;</span> {
    setHoverCard(card);
}, []);
</code></pre>
<p>This works well, and significantly improves the speed when starting a drag operation, but it was still quite slow with large numbers of cards. Nearly nothing was getting re-rendered, but there is still a time cost to when using <code>memo</code>, as it needs to check whether components have changed.</p>
<p>To fix this, we create an <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/AllCards.tsx"><code>AllCards</code></a> component, that contains all the cards on the canvas as <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/NonDraggable.tsx"><code>NonDraggable</code></a> components. Because it always renders all the cards, it nearly never needs to be re-rendered, and it is used with <code>memo</code>. So instead of each individual card using a <code>memo</code> (with the associated time cost), there is now just one component using a <code>memo</code>. To make it so that the dragging still works, the active <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/Draggable.tsx"><code>Draggable</code></a> component is rendered on top, obscuring the <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/NonDraggable.tsx"><code>NonDraggable</code></a> component beneath it. There is also a <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/Cover.tsx"><code>Cover</code></a> component beneath that, so that when the <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/Draggable.tsx"><code>Draggable</code></a> component is dragged away, the <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/NonDraggable.tsx"><code>NonDraggable</code></a> component underneath remains hidden.</p>
<p>Original code, where each card is a <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/Draggable.tsx"><code>Draggable</code></a> component:</p>
<pre><code class="lang-javascript">&lt;DndContext ...&gt;
    {cards.map(<span class="hljs-function">(<span class="hljs-params">card</span>) =&gt;</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Draggable</span> <span class="hljs-attr">card</span>=<span class="hljs-string">{card}</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{card.id}</span> <span class="hljs-attr">canvasTransform</span>=<span class="hljs-string">{transform}</span> /&gt;</span></span>
    ))}
&lt;/DndContext&gt;
</code></pre>
<p>Optimized code, where the <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/AllCards.tsx"><code>AllCards</code></a> component renders all the cards as <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/NonDraggable.tsx"><code>NonDraggable</code></a> components, and then a <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/Cover.tsx"><code>Cover</code></a> and a <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/Draggable.tsx"><code>Draggable</code></a> component for the active card.</p>
<pre><code class="lang-javascript">&lt;AllCards cards={cards} setHoverCard={setHoverCard} /&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DndContext</span> <span class="hljs-attr">...</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Cover</span> <span class="hljs-attr">card</span>=<span class="hljs-string">{hoverCard}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Draggable</span> <span class="hljs-attr">card</span>=<span class="hljs-string">{hoverCard}</span> <span class="hljs-attr">canvasTransform</span>=<span class="hljs-string">{transform}</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">DndContext</span>&gt;</span></span>
</code></pre>
<p>This works very well. With a low number of cards, the speed is about the same, but with a high numbers of cards, it’s about twenty times faster.</p>
<p>There is now a new potential performance issue with the <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/56d0c8256350ef3a0d8f50cc442305bd6c9d03c1/src/NonDraggable.tsx#L10"><code>onMouseEnter</code></a> event that swaps in the <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/Draggable.tsx"><code>Draggable</code></a> component for the active card, but this just adds two components to the Dom, and is very quick even with large numbers of cards.</p>
<h3 id="heading-finishing-a-drag"><strong>Finishing a drag</strong></h3>
<p>Finishing a drag operation is hard to optimize, as the position of a card changes, and that does need to re-render, which means that the <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/AllCards.tsx"><code>AllCards</code></a> component has to re-render as well.</p>
<p>You can see original code below. Even when using <code>memo</code> with the Draggable component, the end drag operation still takes 2500ms with 100,000 cards, mostly due to the complexity of the <code>Draggable</code> component and its integration with DndKit.</p>
<pre><code class="lang-javascript">&lt;DndContext ...&gt;
    {cards.map(<span class="hljs-function">(<span class="hljs-params">card</span>) =&gt;</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Draggable</span> <span class="hljs-attr">card</span>=<span class="hljs-string">{card}</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{card.id}</span> <span class="hljs-attr">canvasTransform</span>=<span class="hljs-string">{transform}</span> /&gt;</span></span>
    ))}
&lt;/DndContext&gt;
</code></pre>
<p>However, we now use the <a target="_blank" href="https://github.com/ceddlyburge/react-figma-miro-canvas-optimised/blob/main/src/NonDraggable.tsx"><code>NonDraggable</code></a> components, which all <code>memo</code> successfully, and only the dragged card is re-rendered. There is still a time cost using the <code>memo</code>, and this is the slowest part of the solution, but it leads to an increase in speed to 500ms with 100,000 cards.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> NonDraggable = memo(...)

<span class="hljs-keyword">const</span> AllCards = memo(<span class="hljs-function">(<span class="hljs-params">cards, setHoverCard</span>) =&gt;</span> {
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
        {cards.map((card) =&gt; {
            <span class="hljs-tag">&lt;<span class="hljs-name">NonDraggable</span> <span class="hljs-attr">card</span>=<span class="hljs-string">{card}</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{card.id}</span> <span class="hljs-attr">setHoverCard</span>=<span class="hljs-string">{setHoverCard}</span> /&gt;</span>);
        })}
    <span class="hljs-tag">&lt;/&gt;</span></span>;
});
</code></pre>
<h2 id="heading-results"><strong>Results</strong></h2>
<p>The base unoptimized version started to get slow between 1000 and 5000 cards. Standard optimizations improved this to around 10,000 cards, and the more optimization took it to about 100,000 cards. The trade off is that the code becomes significantly more complicated, which makes it harder to understand and modify, especially for people new to the codebase.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td></td><td></td><td><strong>Pan (ms)</strong></td><td><strong>Zoom (ms)</strong></td><td><strong>Start drag (ms)</strong></td><td><strong>End drag (ms)</strong></td><td><strong>Card hover (ms)</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1000 cards</td><td>Base</td><td>3</td><td>4</td><td>200</td><td>50</td><td>-</td></tr>
<tr>
<td></td><td>Basic optimization</td><td>2</td><td>3</td><td>200</td><td>30</td><td>-</td></tr>
<tr>
<td></td><td>Intensive optimization</td><td>10</td><td>10</td><td>7</td><td>15</td><td>2</td></tr>
<tr>
<td>5000 cards</td><td>Base</td><td>20</td><td>150</td><td>450</td><td>200</td><td>-</td></tr>
<tr>
<td></td><td>Basic optimization</td><td>20</td><td>150</td><td>200</td><td>80</td><td>-</td></tr>
<tr>
<td></td><td>Intensive optimization</td><td>10</td><td>10</td><td>25</td><td>40</td><td>2</td></tr>
<tr>
<td>10,000 cards</td><td>Base</td><td>50</td><td>300</td><td>900</td><td>400</td><td>-</td></tr>
<tr>
<td></td><td>Basic optimization</td><td>50</td><td>300</td><td>400</td><td>180</td><td>-</td></tr>
<tr>
<td></td><td>Intensive optimization</td><td>25</td><td>25</td><td>50</td><td>50</td><td>2</td></tr>
<tr>
<td>50,000 cards</td><td>Base</td><td>1000</td><td>1500</td><td>4000</td><td>1800</td><td>-</td></tr>
<tr>
<td></td><td>Basic optimization</td><td>1000</td><td>1500</td><td>1900</td><td>900</td><td>-</td></tr>
<tr>
<td></td><td>Intensive optimization</td><td>150</td><td>150</td><td>150</td><td>250</td><td>5</td></tr>
<tr>
<td>100,000 cards</td><td>Base</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
<tr>
<td></td><td>Basic optimization</td><td>3000</td><td>4500</td><td>5000</td><td>2500</td><td>-</td></tr>
<tr>
<td></td><td>Intensive optimization</td><td>150</td><td>250</td><td>300</td><td>500</td><td>15</td></tr>
</tbody>
</table>
</div><h2 id="heading-summary">Summary</h2>
<p>It is unusual to display 100,000 or more items on screen in a standard React App, but in a highly graphical codebase, it becomes much more likely.</p>
<p>With these numbers, the browser rendering engine is likely to take a significant amount of time, so it is best to use the performance API to measure performance, instead of the usual React tools.</p>
<p>Standard React optimization strategies do work and improve the situation, but there is a need to go further, by finding ways to avoid renders, and even to avoid too many <code>memo</code> comparisons.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Fix Memory Leaks in React Applications ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever noticed your React application getting slower the longer you use it? This could be a result of memory leaks. Memory leaks are a common performance issue in React applications. They can slow down your application, crash your browser, and... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/fix-memory-leaks-in-react-apps/</link>
                <guid isPermaLink="false">68d443c623251efd1f372d02</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Olaleye Blessing ]]>
                </dc:creator>
                <pubDate>Wed, 24 Sep 2025 19:17:26 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758741256644/817dba0f-bf49-424c-9b13-86bf81dc327f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever noticed your React application getting slower the longer you use it? This could be a result of memory leaks. Memory leaks are a common performance issue in React applications. They can slow down your application, crash your browser, and frustrate users.</p>
<p>In this tutorial, you’ll learn what causes memory leaks and how to fix them.</p>
<h2 id="heading-table-of-contents">Table Of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-are-memory-leaks-in-react">What Are Memory Leaks in React?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-when-does-a-component-unmount">When Does A Component Unmount?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-common-causes-of-memory-leaks-and-how-to-fix-them">Common Causes Of Memory Leaks And How To Fix Them</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-event-listeners">Event Listeners</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-timers">Timers</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-subscriptions">Subscriptions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-async-operations">Async Operations</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you move on, make sure you have:</p>
<ul>
<li><p>Basic knowledge of JavaScript, React, and React hooks</p>
</li>
<li><p>Understanding of event handling, timers, and asynchronous calls</p>
</li>
<li><p>A React development setup.</p>
</li>
</ul>
<p>If you don’t have a React development setup, you can head over to the <a target="_blank" href="https://github.com/Olaleye-Blessing/freecodecamp-fix-memory-leak">memory-leak repo</a>. Run the commands below to set it up:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># clone the repo</span>
git <span class="hljs-built_in">clone</span> &lt;https://github.com/Olaleye-Blessing/freecodecamp-fix-memory-leak.git&gt;

<span class="hljs-comment"># navigate to the folder</span>
<span class="hljs-built_in">cd</span> freecodecamp-fix-memory-leak.git

<span class="hljs-comment"># install the packages</span>
pnpm install

<span class="hljs-comment"># start development</span>
pnpm dev
</code></pre>
<h2 id="heading-what-are-memory-leaks-in-react">What Are Memory Leaks in React?</h2>
<p>In JavaScript, memory leaks happen when an application allocates memory but fails to release it. This occurs even after the memory is no longer needed.</p>
<p>In React, memory leaks happen when a component creates resources but does not remove them when it unmounts. These resources can be event listeners, timers, or subscriptions.</p>
<p>As a user stays longer in the application, these unreleased resources accumulate. This accumulation causes the application to consume more RAM. This will eventually lead to several problems:</p>
<ul>
<li><p>A slow application</p>
</li>
<li><p>The browser crashing</p>
</li>
<li><p>A poor user experience</p>
</li>
</ul>
<p>For example, a component might create a “resize” event listener when it mounts, but forgets to remove it when it unmounts. This builds up memory as the user stays longer in the application and resizes the screen.</p>
<h2 id="heading-when-does-a-component-unmount">When Does A Component Unmount?</h2>
<p>A component unmounts when it no longer exists in the DOM. This can happen if:</p>
<ol>
<li><p>A user navigates away from the page.</p>
<pre><code class="lang-typescript"> &lt;Routes&gt;
   &lt;Route path=<span class="hljs-string">"/posts"</span> element={&lt;Posts /&gt;} /&gt;
   &lt;Route path=<span class="hljs-string">"/dashboard"</span> element={&lt;Dashboard /&gt;} /&gt;
 &lt;/Routes&gt;
</code></pre>
<p> The dashboard component will unmount immediately when a user navigates from <code>/dashboard</code> to any other route in the application.</p>
</li>
<li><p>A component is conditionally rendered.</p>
<pre><code class="lang-typescript"> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
   <span class="hljs-keyword">const</span> [show, setShow] = useState(<span class="hljs-literal">true</span>);

   <span class="hljs-keyword">return</span> &lt;div&gt;{show &amp;&amp; &lt;Component /&gt;}&lt;/div&gt;;
 }
</code></pre>
<p> <code>&lt;Component /&gt;</code> will unmount when <code>show</code> becomes false.</p>
</li>
<li><p>A component key changes.</p>
<pre><code class="lang-typescript"> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
   <span class="hljs-keyword">const</span> [key, setKey] = useState(<span class="hljs-built_in">Date</span>.now());

   <span class="hljs-keyword">return</span> (
     &lt;&gt;
       &lt;button onClick={<span class="hljs-function">() =&gt;</span> setKey(<span class="hljs-built_in">Date</span>.now())}&gt;Change Key&lt;/button&gt;
       &lt;Form key={key} /&gt;
     &lt;/&gt;
   );
 }
</code></pre>
<p> The <code>&lt;Form /&gt;</code> component will unmount every time the key changes. Also note that a new <code>&lt;Form /&gt;</code> component will mount each time the key changes.</p>
</li>
</ol>
<h2 id="heading-common-causes-of-memory-leaks-and-how-to-fix-them">Common Causes Of Memory Leaks And How To Fix Them</h2>
<p>As said earlier, there will be a memory leak when resources are not removed after a component unmounts. React <code>useEffect</code> allows you to return a function that will be called when a component unmounts.</p>
<pre><code class="lang-typescript">useEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// code to remove resources</span>
  };
}, []);
</code></pre>
<p>You can clean any created resources in this returned function. We will go through how to clean up some of these resources.</p>
<h3 id="heading-event-listeners">Event Listeners</h3>
<p>Event listeners persist if they are not removed after a component unmounts. Look at the code below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

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

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleResize</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">const</span> width = <span class="hljs-built_in">window</span>.innerWidth;
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"__ Resizing Event Listerner __"</span>, width);
      setWindowWidth(width);
    }

    <span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">"resize"</span>, handleResize);
  }, []);

  <span class="hljs-keyword">return</span> &lt;div&gt;Width is: {windowWidth}&lt;/div&gt;;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> EventListener;
</code></pre>
<p>We do not remove the resize event listener on unmount, so every mount adds a new listener. This failure to clean up leads to a memory leak.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758149182882/58ddc026-d6b8-4120-9144-53b6d87fb63e.gif" alt="GIF shows multiple 'resize' event listeners being created each time a component mounts." class="image--center mx-auto" width="800" height="495" loading="lazy"></p>
<p>As shown in the GIF above, we log the width in the console every time we resize the window’s width. We still log the same information after component unmounts. Also, when we check the “Event Listeners” tab, the number of listeners keeps increasing by 2 instead of being just 1 each time we remount the component.</p>
<p>We see two listeners when the component mounts because React uses StrictMode in development. This helps to see side effects in the development mode. The same reason the listeners increase by 2 any time we mount the component.</p>
<p>To fix this memory leak, we need to remove the event listener in our cleanup function.</p>
<pre><code class="lang-typescript">useEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// previous code</span>

  <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">window</span>.removeEventListener(<span class="hljs-string">"resize"</span>, handleResize);
  };
}, []);
</code></pre>
<p>The cleanup function runs when the component unmounts. This, in turn, removes our event listener and prevents a memory leak.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758149497654/f95d75b4-f41f-4bb0-806b-546555be813a.gif" alt="GIF shows a 'resize' event listener that is removed when the component unmounts." class="image--center mx-auto" width="800" height="495" loading="lazy"></p>
<p>Notice this time, nothing is shown in the console when we hide the component. Also, the resize event listener was reduced to 0 when we hid (unmounted) the component, and increased to 1 when we showed (mounted) it.</p>
<h3 id="heading-timers">Timers</h3>
<p>Timers like <code>setInterval</code> and <code>setTimeout</code> can also cause memory leaks if they are not cleared after the component unmounts. Look at this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> Timers = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [countDown, setCountDown] = useState(<span class="hljs-number">0</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"__ Set Interval __"</span>);
      setCountDown(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> prev + <span class="hljs-number">1</span>);
    }, <span class="hljs-number">1000</span>);
  }, []);

  <span class="hljs-built_in">console</span>.log({ countDown });

  <span class="hljs-keyword">return</span> &lt;div&gt;Countdown: {countDown}&lt;/div&gt;;
};
</code></pre>
<p>The interval will continue to run even after React hides or unmounts the component.</p>
<p>Note that, in React 18+, React ignores a state update when a component already unmounts.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758149517577/34868e3e-e8f6-495a-a2f8-ef0e1e745051.gif" alt="GIF shows a countdown timer component that continues to run and update state after it has been unmounted from the DOM." class="image--center mx-auto" width="800" height="495" loading="lazy"></p>
<p>In the GIF, we notice that the console stops showing "__ Outside effect ” anytime we hide/unmount the component. But the string, " Interval __”, shows every time.</p>
<p>We can fix this by using the cleanup function. All timers (<code>setInterval</code>, <code>setTimeout</code>) return a unique timer ID that we can use to clear the timer after the component unmounts.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> [countDown, setCountDown] = useState(<span class="hljs-number">0</span>);
useEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> timer = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.count(<span class="hljs-string">"__ Interval __"</span>);
    setCountDown(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> prev + <span class="hljs-number">1</span>);
  }, <span class="hljs-number">1000</span>);

  <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">clearInterval</span>(timer);
  };
}, []);
</code></pre>
<p>We now save the ID of the timer and use this ID to clear the interval when the component unmounts. The same method applies to <code>setTimeout</code>; save the ID and clear it with <code>clearTimeout</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758149580900/7c37c824-93db-4b73-8ff4-c45c6404bb65.gif" alt="GIF shows a countdown timer component that stops running and updating state after it unmounts." class="image--center mx-auto" width="800" height="495" loading="lazy"></p>
<h3 id="heading-subscriptions">Subscriptions</h3>
<p>When a component subscribes to external data, it’s always appropriate to unsubscribe after the component unmounts. Most data source returns a callback function to unsubscribe from such data. Take Firebase for an example:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { collection, onSnapshot } <span class="hljs-keyword">from</span> <span class="hljs-string">"firebase/firestore"</span>;
<span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> Subscriptions = <span class="hljs-function">() =&gt;</span> {
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> unsubscribe = onSnapshot(collection(db, <span class="hljs-string">"cities"</span>), <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-comment">// Respond to data</span>
        <span class="hljs-comment">// ...</span>
    });
  }, [])

    <span class="hljs-keyword">return</span> &lt;div&gt;Subscriptions&lt;/div&gt;;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Subscriptions;
</code></pre>
<p>The <code>onSnapshot</code> function from <code>firebase/firestore</code> gets real-time updates from our database. It returns a callback function that stops listening to the DB updates. If you fail to call this function, our app continues to listen to these updates even when it no longer needs them.</p>
<pre><code class="lang-typescript">useEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> unsubscribe = onSnapshot(collection(db, <span class="hljs-string">"cities"</span>), <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Respond to data</span>
    <span class="hljs-comment">// ...</span>
  });

  <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
    unsubscribe();
  };
}, []);
</code></pre>
<p>Calling <code>unsubscribe()</code> in the returned function means we are no longer interested in listening to the data updates.</p>
<h3 id="heading-async-operations">Async Operations</h3>
<p>One common mistake is not cancelling an API call when it’s no longer needed. It's a waste of resources to allow an API call to keep running when the component unmounts. This is because the browser continues to hold references in memory until the promise resolves. Look at this example:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">interface</span> Post {
  id: <span class="hljs-built_in">string</span>;
  title: <span class="hljs-built_in">string</span>;
  views: <span class="hljs-built_in">number</span>;
}

<span class="hljs-keyword">const</span> ApiCall = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [data, setData] = useState&lt;Post[] | <span class="hljs-literal">null</span>&gt;(<span class="hljs-literal">null</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> getTodos = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        setLoading(<span class="hljs-literal">true</span>);

        <span class="hljs-built_in">console</span>.time(<span class="hljs-string">"POSTS"</span>);
        <span class="hljs-keyword">const</span> req = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"&lt;http://localhost:3001/posts&gt;"</span>);
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> req.json();
        <span class="hljs-built_in">console</span>.timeLog(<span class="hljs-string">"POSTS"</span>);
        setData(res.posts);
      } <span class="hljs-keyword">catch</span> (error) {
        setError(<span class="hljs-string">"Try again"</span>);
      } <span class="hljs-keyword">finally</span> {
        setLoading(<span class="hljs-literal">false</span>);
      }
    };

    getTodos();
  }, []);

  <span class="hljs-keyword">return</span> (
    &lt;div style={{ marginTop: <span class="hljs-string">"2rem"</span> }}&gt;
      &lt;p&gt;ApiCall Component&lt;/p&gt;
      {loading ? (
        &lt;p&gt;Loading...&lt;/p&gt;
      ) : error ? (
        &lt;p&gt;{error}&lt;/p&gt;
      ) : data ? (
        &lt;p&gt;Views: {data[<span class="hljs-number">0</span>].views}&lt;/p&gt;
      ) : <span class="hljs-literal">null</span>}
    &lt;/div&gt;
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ApiCall;
</code></pre>
<p>This component fetches a list of posts from our server immediately it mounts. It changes the UI based on the state of the API call:</p>
<ul>
<li><p>It displays a loading text when you click the button.</p>
</li>
<li><p>It shows an error if the API fails.</p>
</li>
<li><p>It shows the data if the API succeeds.</p>
</li>
</ul>
<p>We have a simple server that returns the list of posts. The problem with the server is that it takes three seconds for it to return the list of posts.</p>
<p>What happens when a user comes to this page but decides to leave before three seconds? (We simulate leaving the page by clicking the Hide Component button.)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758149803784/bf5cf55f-75fe-472f-9a08-653c53bdafaa.gif" alt="GIF shows a component that continues with an API call after it unmounts." class="image--center mx-auto" width="800" height="495" loading="lazy"></p>
<p>As you can see, the browser still holds a reference to the request even though it’s no longer needed.</p>
<p>A proper way to fix this is to cancel the request when the component unmounts. We can do this by using the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/AbortController">AbortController</a>. We can use the <code>abort</code> method to cancel the request before it gets completed, thereby releasing memory.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">interface</span> Post {
  id: <span class="hljs-built_in">string</span>;
  title: <span class="hljs-built_in">string</span>;
  views: <span class="hljs-built_in">number</span>;
}

<span class="hljs-keyword">const</span> ApiCall = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// previous code</span>

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> controller = <span class="hljs-keyword">new</span> AbortController();

    <span class="hljs-keyword">const</span> getTodos = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">// previous code</span>

        <span class="hljs-keyword">const</span> req = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"&lt;http://localhost:3001/posts&gt;"</span>, {
          signal: controller.signal,
        });

        <span class="hljs-comment">// previous code</span>
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-keyword">if</span> (error <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Error</span> &amp;&amp; error.name === <span class="hljs-string">"AbortError"</span>) {
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Request was cancelled"</span>);
          <span class="hljs-keyword">return</span>;
        }

        setError(<span class="hljs-string">"Try again"</span>);
      } <span class="hljs-keyword">finally</span> {
        setLoading(<span class="hljs-literal">false</span>);
      }
    };

    getTodos();

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      controller.abort();
    };
  }, []);

  <span class="hljs-keyword">return</span> (
    &lt;div style={{ marginTop: <span class="hljs-string">"2rem"</span> }}&gt;
      &lt;p&gt;ApiCall Component&lt;/p&gt;
      {<span class="hljs-comment">/* previous code */</span>}
    &lt;/div&gt;
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ApiCall;
</code></pre>
<p>We created a controller to track our API request when the component mounts. We then attach the controller to our API request. Our cleanup function cancels the request if the users leave the page within three seconds.</p>
<p>We can see the result of this in the GIF below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758149811531/5497edbd-050c-4059-b088-239e8c5b65ef.gif" alt="GIF shows an API call being cancelled after its component unmounts." class="image--center mx-auto" width="800" height="495" loading="lazy"></p>
<p>Most production React applications use external libraries to fetch APIs. For example, <a target="_blank" href="https://tanstack.com/query/latest/docs/framework/react/guides/query-cancellation#using-fetch">react query</a> allows us to cancel a processing promise:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> query = useQuery({
  queryKey: [<span class="hljs-string">"todos"</span>],
  queryFn: <span class="hljs-keyword">async</span> ({ signal }) =&gt; {
    <span class="hljs-keyword">const</span> todosResponse = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"/todos"</span>, { signal });
    <span class="hljs-keyword">const</span> todos = <span class="hljs-keyword">await</span> todosResponse.json();

    <span class="hljs-keyword">return</span> todos;
  },
});
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Memory leaks can significantly impact your React application's performance and user experience. You can prevent these issues by properly cleaning up resources when a component unmounts. In summary, always remember to:</p>
<ul>
<li><p>Remove event listeners with <code>removeEventListener</code>.</p>
</li>
<li><p>Clear timers with <code>clearInterval</code> and <code>clearTimeout</code>.</p>
</li>
<li><p>Unsubscribe from external data sources.</p>
</li>
<li><p>Cancel API requests using <code>AbortController</code>.</p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Optimize Search in JavaScript with Debouncing ]]>
                </title>
                <description>
                    <![CDATA[ A few months ago, my manager assigned me a task: implement a search functionality across an entire page. The tricky part was that the displayed text was shown in the form of prompts, and each prompt could be truncated after two lines. If the text exc... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/optimize-search-in-javascript-with-debouncing/</link>
                <guid isPermaLink="false">68d2d63ab7bb607e13c45cf4</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ajay Yadav ]]>
                </dc:creator>
                <pubDate>Tue, 23 Sep 2025 17:17:46 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758647563748/4f1c792d-5912-4bbb-9144-fcdda83d78ec.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A few months ago, my manager assigned me a task: implement a search functionality across an entire page. The tricky part was that the displayed text was shown in the form of prompts, and each prompt could be truncated after two lines.</p>
<p>If the text exceeded the limit, a split button appeared, allowing users to open the full prompt in a separate split-view section (see the illustration below for better understanding).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757771259264/66158a97-07d1-4b4f-ad24-c57c62a498ae.png" alt="A black interface with a search bar at the top left, a rating of 5/10, and navigation arrows. Below are four text boxes with dummy text snippets. On the right is a detailed explanation of &quot;Lorem Ipsum,&quot; discussing its history in the printing and typesetting industry. The page number is 1 of 7 out of 12." class="image--center mx-auto" width="1076" height="705" loading="lazy"></p>
<p>Now, if the requirement had been just plain text, I could have solved it with a simple regex-based search. In fact, inside the split view itself, I initially used a regex approach for searching along with navigation to the matches. That worked fine.</p>
<p>Since I already had a working search helper function, I thought, “Why not reuse it for the global search as well?”</p>
<p>Well, I tried that. But this time, the UI started lagging whenever I clicked the next/previous buttons in the search bar. Even the pagination controls on the top-right slowed down during navigation. To figure out a better approach, I turned to AI tools for brainstorming and came across multiple ideas and concepts.</p>
<p>As developers, we use Google daily, and naturally, I became curious about how Google’s search works under the hood. I opened up Chrome DevTools, started typing in Google’s search bar, and noticed something interesting.</p>
<p>While Google Search updates results in real-time with each keystroke, we don’t have Google’s server power. In our apps, debouncing is a practical way to avoid unnecessary API calls and improve performance. That idea matched exactly what ChatGPT had suggested to me earlier.</p>
<p>So, I applied a similar approach to my project and finally delivered the feature using debouncing, along with React hooks like <code>useTransition</code> and <code>useDeferredValue</code>. That’s how the idea for this article came out.</p>
<p>In this article, I’ll show you how to optimize your application’s performance by implementing the debounce technique.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-problem-without-debouncing">Problem Without Debouncing</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-debouncing">What is Debouncing</a>?</p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-debouncing-in-javascript">How to Implement Debouncing in JavaScript</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-benefits-of-using-debouncing-in-search">Benefits of Using Debouncing in Search</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-common-mistakes-to-avoid">Common Mistakes to Avoid</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-before-we-end">Before We End</a></p>
</li>
</ul>
<p>Let’s dig in.</p>
<h2 id="heading-problem-without-debouncing">Problem Without Debouncing</h2>
<p>Imagine you’re building a search bar that fetches results from an API. Every time the user types a letter, the search bar immediately makes a new request.</p>
<p>If someone types the word “JavaScript”, that means 10 separate API calls will be fired — one for each character.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758013146153/204187ef-1757-490b-8b29-7d11951c88b3.png" alt="the Google search page with &quot;javascript&quot; in the input box" class="image--center mx-auto" width="2047" height="1506" loading="lazy"></p>
<p>Now, in Google Search, results update in real-time with every keystroke. But unlike Google, we don’t have massive infrastructure to handle that load. In most applications, firing a request for every single character quickly becomes inefficient.</p>
<p>At first, this might not seem like a big deal, but in practice it leads to serious problems. The browser has to manage a flood of unnecessary requests, the server gets overloaded with repeated calls, and the user ends up with a laggy or inconsistent experience. The whole interface feels heavy and unresponsive.</p>
<p>This is exactly the situation I ran into when I reused my simple regex-based search function for the global search. It worked fine for a small prompt inside the split view, but when applied at a larger scale with navigation buttons and pagination, the UI started freezing and slowing down.</p>
<h2 id="heading-what-is-debouncing">What is Debouncing?</h2>
<p>Debouncing is a technique, not a programming language feature. It’s simply a way to control how often a function gets called. Instead of running the function every single time an event happens, you delay its execution.</p>
<p>If the event keeps firing during that delay, the timer resets. The function only runs when the user finally pauses.</p>
<p>Think about typing into a search bar. Without debouncing, the app would make a request for every keystroke. With debouncing, the app waits until the user stops typing for a short time—say 300 milliseconds and then makes just one request with the final input.</p>
<p>Behind the scenes, this is usually implemented with <code>setTimeout</code> and <code>clearTimeout</code>. A timer starts when the event occurs, and if another event happens before the timer ends, the timer is cleared and restarted. Only when the user stops typing for the specified delay does the function execute.</p>
<h2 id="heading-how-to-implement-debouncing-in-javascript">How to Implement Debouncing in JavaScript</h2>
<p>As I mentioned earlier, debouncing is not tied to any specific programming language. It’s simply a concept that can be implemented using timers. In JavaScript, we typically use <code>setTimeout</code> and <code>clearTimeout</code> to achieve this.</p>
<p>Here’s a simple example of a debounce function in JavaScript:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">debounce</span>(<span class="hljs-params">fn, delay</span>) </span>{
  <span class="hljs-keyword">let</span> timer;
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">...args</span>) </span>{
    <span class="hljs-built_in">clearTimeout</span>(timer);
    timer = <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      fn.apply(<span class="hljs-built_in">this</span>, args);
    }, delay);
  };
}
</code></pre>
<p>We start with a function <code>debounce</code> that takes two arguments:</p>
<ul>
<li><p><code>fn</code> is the function we want to control, such as the API call.</p>
</li>
<li><p><code>delay</code> is how long we want to wait before actually running <code>fn</code>.</p>
</li>
</ul>
<p>Inside, we declare a variable <code>timer</code>. This will hold the reference to the <code>setTimeout</code>.</p>
<p>The <code>debounce</code> function then returns another function. This returned function is the one that will actually run whenever an event (like typing in the input or API call) happens.</p>
<p>Every time the user types, the first thing you do is <code>clearTimeout(timer)</code>. This cancels any previously scheduled function call. Then you create a new timeout with <code>setTimeout</code>.</p>
<p>If the user keeps typing before the delay finishes, the old timer is cleared and restarted. Only when they pause long enough does the timeout finish and <code>fn</code> gets executed.</p>
<p>Did you notice how I used <code>fn.apply(this, args)</code>? That’s just a safe way of calling the original function with the correct <code>this</code> context and passing along all arguments.</p>
<p>Now here’s how you use it in practice:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchResults</span>(<span class="hljs-params">query</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Fetching results for:"</span>, query);
  <span class="hljs-comment">// Here you could call your API</span>
}

<span class="hljs-comment">// Wrap it with debounce</span>
<span class="hljs-keyword">const</span> debouncedSearch = debounce(fetchResults, <span class="hljs-number">300</span>);

<span class="hljs-comment">// Attach to input event</span>
<span class="hljs-keyword">const</span> input = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"search"</span>);
input.addEventListener(<span class="hljs-string">"input"</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
  debouncedSearch(e.target.value);
});
</code></pre>
<ol>
<li><p><code>fetchResults</code> is our actual search function. Normally, it would run for every keystroke.</p>
</li>
<li><p>We wrap it with <code>debounce</code> and set a delay of 300ms. That means it won’t run until the user stops typing for 300ms.</p>
</li>
<li><p>On every <code>input</code> event, instead of calling <code>fetchResults</code> directly, we call <code>debouncedSearch</code>. This ensures only the debounced version of the function executes.</p>
</li>
</ol>
<p>So if a user types “hello,” instead of five API calls, only one or two will fire once they pause.</p>
<h2 id="heading-benefits-of-using-debouncing-in-search">Benefits of Using Debouncing in Search</h2>
<p>Using debouncing in a search feature may feel like a small optimization, but it has a big impact. The most obvious benefit is performance.</p>
<p>Instead of making a request for every single keystroke, your app waits until the user pauses, which saves both browser and server resources. The UI feels much smoother because it isn’t constantly being interrupted by unnecessary calls.</p>
<p>Debouncing also improves scalability. If hundreds or thousands of users are typing at once, you’re cutting down a huge number of wasted API calls. That means your backend can handle more users without getting overloaded.</p>
<p>There’s also an indirect benefit for SEO and analytics. When your app performs efficiently and feels snappy, users stay longer, interact more, and bounce less. This kind of responsiveness can make a big difference in how people perceive the quality of your product.</p>
<h2 id="heading-common-mistakes-to-avoid">Common Mistakes to Avoid</h2>
<p>While debouncing is powerful, there are a few mistakes developers often make. One common issue is setting the delay too high. If you make users wait one or two seconds before seeing results, the search will feel unresponsive.</p>
<p>On the other hand, a delay that’s too short may not reduce calls enough to be useful. A sweet spot is usually between 300–500 milliseconds, but it depends on your use case.</p>
<p>Another mistake is forgetting to clear old timers. Without clearing, your app may still execute older, outdated calls, which can lead to glitches or memory leaks. That’s why <code>clearTimeout</code> is just as important as <code>setTimeout</code> in any debounce function.</p>
<p>It’s also important to think about edge cases. What happens if the input is cleared quickly? Or if someone pastes a long string instead of typing? Testing these cases ensures your debounce function works smoothly in real-world scenarios.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>When I first encountered the challenge of building a global search, I thought I could simply reuse my basic regex-based solution. However, the UI soon began to lag, and the user experience declined. It's surprising how such a small concept can significantly impact performance.</p>
<p>Debouncing ensures that your functions run at the right time, not every time. Whether you’re building a simple JavaScript app or working with React and Next.js, this technique helps reduce unnecessary calls, improves performance, and keeps your app scalable.</p>
<p>So the next time you build a search bar, remember: don’t just make it work, make it efficient.</p>
<h2 id="heading-before-we-end">Before We End</h2>
<p>I hope you found this article insightful. I’m Ajay Yadav, a software developer and content creator.</p>
<p>You can connect with me on:</p>
<ul>
<li><p><a target="_blank" href="https://x.com/atechajay">Twitter/X</a> and <a target="_blank" href="https://www.linkedin.com/in/atechajay/">LinkedIn</a>, where I share insights to help you improve 0.01% each day.</p>
</li>
<li><p>Check out my <a target="_blank" href="https://github.com/ATechAjay">GitHub</a> for more projects.</p>
</li>
<li><p>I also run a Hindi <a target="_blank" href="http://youtube.com/@atechajay">YouTube Channel</a> where I share content about careers, software engineering, and technical writing.</p>
</li>
</ul>
<p>See you in the next article — until then, keep learning!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Optimize Next.js Web Apps for Better Performance ]]>
                </title>
                <description>
                    <![CDATA[ As engineers, we often get so carried away with other aspects of development that we overlook how users perceive and interact with our applications. This oversight can result in users leaving the app almost as soon as they arrive, leading to higher b... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/optimize-nextjs-web-apps-for-better-performance/</link>
                <guid isPermaLink="false">6776a323218b455d646035b2</guid>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Performance Optimization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ayantunji Timilehin ]]>
                </dc:creator>
                <pubDate>Thu, 02 Jan 2025 14:30:59 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735828217839/b65374be-d891-4f19-a359-f84f2ac8f3b9.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As engineers, we often get so carried away with other aspects of development that we overlook how users perceive and interact with our applications. This oversight can result in users leaving the app almost as soon as they arrive, leading to higher bounce rates and minimal engagement.</p>
<p>At its core, every business thrives on delivering value to its users. When users are unable to access this value due to poor performance, it ultimately impacts the business's success. Slow load times, among other factors, frustrate users and drive them away before they even get a chance to engage.</p>
<p>Optimizing performance is more than just a technical detail – it’s also a critical part of creating a successful application. Without it, even the best features can go unnoticed if users don’t stick around long enough to see them.</p>
<p>In this article, we’ll explore key approaches to optimize your Next.js application, making it faster and more efficient.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-building-a-performant-app">Building a Performant Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-optimize-your-applications">How to Optimize Your Applications</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-key-techniques-to-optimize-performance">Key Techniques To Optimize Performance</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-using-the-nextjs-image-component">Using The Next.js Image Component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-optimizing-third-party-scripts-with-the-nextjs-script-component">Optimizing Third-Party Scripts with the Next.js Script Component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-remove-unused-packagesdependencies">Remove Unused Packages/Dependencies</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-caching-and-incremental-static-regeneration-isr">Caching and Incremental Static Regeneration (ISR)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-caching-frequently-used-content">Caching Frequently Used Content</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-5-font-optimization-with-nextfont">Font Optimization With next/font</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-6-lazy-loading-and-code-splitting">Lazy Loading And Code Splitting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-lazy-loading-in-nextjs">Lazy Loading in Next.js</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-code-splitting">Code Splitting</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-building-a-performant-application">Building a Performant Application</h2>
<p>Making your apps more performant means striking the right balance between speed, responsiveness, and efficient use of resources. You should strive to create an application that delivers value and keeps users satisfied.</p>
<p>Building a performant app is about making sure the app feels smooth and intuitive so that there are no frustrating lags when a user clicks buttons, scrolls, or navigates around. You’ll also want to make sure that data loads or updates without unnecessary delays.</p>
<h2 id="heading-how-to-optimize-your-applications">How to Optimize Your Applications</h2>
<p>The first step in optimizing your application is identifying problem areas. A number of tools and packages can help you analyze your application's performance effectively. Here's how you can use them:</p>
<h3 id="heading-using-npm-run-build">Using <code>npm run build</code></h3>
<p>When you run <code>npm run build</code>, Next.js creates a production-ready version of your application and gives a detailed breakdown of your pages. This includes:</p>
<ul>
<li><p><strong>Size</strong>: The size of the JavaScript files for each route. Highlighting any routes that are too large and could slow things down. Smaller page sizes generally result in faster load times while large pages might take longer to download, especially for users with slower network connections.</p>
</li>
<li><p><strong>First Load Js</strong>: This column provides information about the total amount of JavaScript the browser needs to download and execute to fully render the page for the first time. Large <strong>First Load JS</strong> values</p>
<p>  cause Slower Time-to-Interactive (TTI).</p>
</li>
</ul>
<p>Running this command produces an analysis like below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734639730677/cfd1f858-a9df-4e6c-af28-454857309156.png" alt="Example result of running npm run build" class="image--center mx-auto" width="984" height="300" loading="lazy"></p>
<h3 id="heading-using-nextbundle-analyzer">Using <code>@next/bundle-analyzer</code></h3>
<p>The <a target="_blank" href="https://www.npmjs.com/package/@next/bundle-analyzer">bundle analyzer</a> is a package provided by Next.js to analyze the size of JavaScript bundles by providing a visual representation of the application’s module and dependencies. Here’s how to use the package:</p>
<p>First, install the package by running this command:</p>
<pre><code class="lang-bash">npm install @next/bundle-analyzer
</code></pre>
<p>Or you can use yarn:</p>
<pre><code class="lang-bash">yarn add @next/bundle-analyzer
</code></pre>
<p>Then add the <code>@next/bundle-analyzer</code> configuration to your <code>next.config.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> withBundleAnalyzer = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@next/bundle-analyzer'</span>)({
  <span class="hljs-attr">enabled</span>: process.env.ANALYZE === <span class="hljs-string">'true'</span>,
});

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

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

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

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

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

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

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

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

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

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

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Welcome Home!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">HeavyComponent</span> /&gt;</span> {/* This loads only when rendered */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
</code></pre>
<p>In the above code, <code>dynamic</code> dynamically imports the component only when needed. <code>ssr: false</code> disables server-side rendering for the component, which can save resources if the component doesn’t need to be pre-rendered.</p>
<p>Next.js automatically splits code by page, meaning each page only loads the necessary JavaScript when accessed, improving load times. For more granular control, <code>next/dynamic</code> allows you to dynamically import specific components, ensuring they are loaded lazily only when needed. While Next.js handles page-level code splitting by default, using <code>next/dynamic</code> gives you the flexibility to apply component-level splitting, optimizing resource loading and enhancing performance.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Creating a high-performance application is a very important aspect of any business. A faster and more efficient application enhances user engagement, lowers bounce rates, and boosts SEO rankings, which all contribute to business growth and customer satisfaction.</p>
<p>By utilizing these techniques we discussed in this guide, you can provide a smooth user experience while maintaining optimal efficiency behind the scenes.</p>
<p>Remember, every second saved in load time translates to happier users and, ultimately, better business outcomes.</p>
<p>Thank you for reading!</p>
<p>Want to connect with me?</p>
<ul>
<li><p>Twitter / X: <a target="_blank" href="https://x.com/Timi471">@timi471</a></p>
</li>
<li><p>Linkedin: <a target="_blank" href="https://www.linkedin.com/in/timilehin-micheal/">Ayantunji Timilehin</a></p>
</li>
<li><p>Email: ayantunjitimilehin@gmail.com</p>
</li>
</ul>
<h3 id="heading-references">References</h3>
<ul>
<li><p><a target="_blank" href="https://nextjs.org/docs/pages/building-your-application/optimizing">Next.Js Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/caching-vs-content-delivery-network/">Caching-vs-content-delivery-network</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=EIGmcxwbbZw">Using next/bundle-analyzer</a></p>
</li>
<li><p><a target="_blank" href="https://blog.hubspot.com/marketing/cumulative-layout-shift">Cumulative layout shift</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Improve and Restructure Your Codebase with AI Tools & Version Control ]]>
                </title>
                <description>
                    <![CDATA[ A codebase can become messy and hard to manage over time. This happens because of quick fixes, outdated features, or just not enough time to clean things up. When code becomes difficult to read or change, it slows down progress and can even cause bug... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/improve-and-restructure-codebase-with-ai-tools/</link>
                <guid isPermaLink="false">6720f7fb2e452955f9433899</guid>
                
                    <category>
                        <![CDATA[ best practices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Programming Tips ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ improve performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ version control ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Git ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Pull Requests ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwadamisi Samuel ]]>
                </dc:creator>
                <pubDate>Tue, 29 Oct 2024 14:58:03 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1730194934749/feb606d0-bbbd-43ae-a58c-5932d8c2d76c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A codebase can become messy and hard to manage over time. This happens because of quick fixes, outdated features, or just not enough time to clean things up.</p>
<p>When code becomes difficult to read or change, it slows down progress and can even cause bugs. To keep a codebase healthy and easy to work with, you’ll need to take care of it.</p>
<p>Improving and organizing old code can feel like a big task, but there are tools and methods that can make it easier. This guide will show how to refresh your codebase step by step which will make it simpler to work with and less likely to cause issues.</p>
<h3 id="heading-table-of-contents">Table of Contents</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-how-to-review-your-code-effectively">How to Review Your Code Effectively</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-identify-technical-debt-and-problem-areas-in-code">How to Identify Technical Debt and Problem Areas in Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-measure-code-quality-with-code-analysis-tools">How to Measure Code Quality with Code Analysis Tools</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-ai-tools-to-help-you-improve-your-code">AI Tools to Help You Improve Your Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-version-control-best-practices-for-code-changes">Version Control Best Practices for Code Changes</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-how-to-review-your-code-effectively">How to Review Your Code Effectively</h2>
<p>Code reviews are essential for catching issues early, improving readability, and ensuring long-term maintainability. Reviewing your own code or someone else’s involves more than just scanning for errors – you’ll also want to make sure each part is clear, efficient, and follows good practices.</p>
<p>Here’s a step-by-step approach to help you review code effectively, with practical strategies, tools, and what to look for during the process.</p>
<h3 id="heading-strategies-for-effective-code-review">Strategies for Effective Code Review</h3>
<ol>
<li><p><strong>Break Down the Review Process:</strong> Reviewing code all at once can be overwhelming, especially in large projects. Focus on small sections of the codebase at a time, such as individual functions or modules. This approach helps you examine each part closely and avoids missing issues that could be overlooked in a quick scan.</p>
</li>
<li><p><strong>Review for Clarity and Simplicity:</strong> Good code should be easy to read and understand. When reading through the code:</p>
<ul>
<li><p><strong>Variable and Function Names:</strong> Are variable names descriptive enough to convey their purpose? Long, unclear names make code harder to follow.</p>
</li>
<li><p><strong>Function Length:</strong> Keep functions short and focused on one task. Long functions are harder to debug and maintain.</p>
</li>
<li><p><strong>Comments and Documentation:</strong> Comments should explain <em>why</em> something is done rather than <em>what</em> is happening, which should be clear from the code itself. For instance, avoid excessive commenting on trivial lines and focus on complex logic or business rules.</p>
</li>
</ul>
</li>
<li><p><strong>Check for Code Reusability and Modularity:</strong> Look for repeated code or functions performing multiple tasks. By modularizing code, you make it easier to test, update, and reuse. In a review, look for:</p>
<ul>
<li><p><strong>Duplicate Code:</strong> Repeated code can often be refactored into a function.</p>
</li>
<li><p><strong>Single Responsibility:</strong> Each function should handle one task, making it easier to maintain and update.</p>
</li>
</ul>
</li>
<li><p><strong>Examine Error Handling and Edge Cases:</strong> Robust code should handle unexpected inputs or errors gracefully. During a review, think about potential edge cases that could break the code:</p>
<ul>
<li><p><strong>Null or Undefined Values:</strong> Does the code check for undefined values where needed?</p>
</li>
<li><p><strong>Out-of-Range Errors:</strong> Ensure array indexes and calculations won’t produce errors with edge cases.</p>
</li>
<li><p><strong>Error Messages:</strong> Make sure error handling is meaningful, with clear error messages where applicable.</p>
</li>
</ul>
</li>
<li><p><strong>Look for Performance Issues:</strong> Performance may not always be critical, but it’s good to check for potential bottlenecks. Look for:</p>
<ul>
<li><p><strong>Loop Optimization:</strong> Avoid deeply nested loops or repeated work inside loops.</p>
</li>
<li><p><strong>Database Queries:</strong> Minimize unnecessary database calls.</p>
</li>
<li><p><strong>Heavy Computation in the Main Thread:</strong> Move any heavy processing outside the main application thread if possible.</p>
</li>
</ul>
</li>
<li><p><strong>Ensure Consistency with Coding Standards:</strong> Following a consistent coding style improves readability across the team. Many teams use linters or style guides to enforce these standards. Look for:</p>
<ul>
<li><p><strong>Code Format:</strong> Consistent indentation, spacing, and use of braces.</p>
</li>
<li><p><strong>Naming Conventions:</strong> Follow agreed naming conventions (camelCase, snake_case, and so on) consistently.</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-tools-to-assist-with-code-reviews">Tools to Assist with Code Reviews</h3>
<p>There are a number of tools out there that can help streamline your code reviews, whether you’re checking your own code or collaborating with others:</p>
<h4 id="heading-1-linters-like-eslint-and-pylint"><strong>1. Linters (like ESLint and Pylint)</strong></h4>
<p>Linters check for syntax errors, code smells, and style guide violations. They are especially useful for catching minor issues, like inconsistent formatting or unused variables. We will discuss ESLint more in an upcoming section.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Example: Run ESLint on a JavaScript project</span>
npx eslint src/
</code></pre>
<h4 id="heading-2-static-analysis-tools-like-sonarqube"><strong>2. Static Analysis Tools (like SonarQube)</strong></h4>
<p>These tools analyze code for deeper issues like security vulnerabilities, code duplication, and complex functions that might need refactoring.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Configuring SonarQube to scan a project</span>
sonar.projectKey=my_project
sonar.sources=src
sonar.host.url=http://localhost:9000
sonar.login=my_token
</code></pre>
<h4 id="heading-3-automated-testing-tools"><strong>3. Automated Testing Tools</strong></h4>
<p>Running tests can verify that code changes don’t introduce new bugs. Use testing frameworks like Jest for JavaScript, PyTest for Python, or JUnit for Java to confirm your code behaves as expected.</p>
<h3 id="heading-example-of-refactoring-during-code-review">Example of Refactoring During Code Review</h3>
<p>Let’s say you encounter a long function with multiple responsibilities. The goal is to split it into smaller, focused functions. Here’s how you can do that:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Original: A single function that handles everything</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processOrder</span>(<span class="hljs-params">order</span>) </span>{
    <span class="hljs-comment">// Calculate total price</span>
    <span class="hljs-keyword">let</span> total = <span class="hljs-number">0</span>;
    order.items.forEach(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> {
        total += item.price * item.quantity;
    });

    <span class="hljs-comment">// Apply discount</span>
    <span class="hljs-keyword">if</span> (order.discountCode) {
        total = total * <span class="hljs-number">0.9</span>; <span class="hljs-comment">// 10% discount</span>
    }

    <span class="hljs-comment">// Send order confirmation email</span>
    sendEmail(order.customerEmail, <span class="hljs-string">'Order Confirmation'</span>, <span class="hljs-string">'Your order total is '</span> + total);
}

<span class="hljs-comment">// Improved: Break into smaller functions for readability and reusability</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateTotal</span>(<span class="hljs-params">order</span>) </span>{
    <span class="hljs-keyword">return</span> order.items.reduce(<span class="hljs-function">(<span class="hljs-params">sum, item</span>) =&gt;</span> sum + item.price * item.quantity, <span class="hljs-number">0</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">applyDiscount</span>(<span class="hljs-params">total, discountCode</span>) </span>{
    <span class="hljs-keyword">return</span> discountCode ? total * <span class="hljs-number">0.9</span> : total;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendConfirmationEmail</span>(<span class="hljs-params">email, total</span>) </span>{
    sendEmail(email, <span class="hljs-string">'Order Confirmation'</span>, <span class="hljs-string">'Your order total is '</span> + total);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processOrder</span>(<span class="hljs-params">order</span>) </span>{
    <span class="hljs-keyword">let</span> total = calculateTotal(order);
    total = applyDiscount(total, order.discountCode);
    sendConfirmationEmail(order.customerEmail, total);
}
</code></pre>
<p>Breaking down the process into smaller functions makes the code cleaner, more readable, and easier to test. Each function now has a single responsibility, which helps reduce bugs and makes future updates simpler.</p>
<h2 id="heading-how-to-identify-technical-debt-and-problem-areas-in-code">How to Identify Technical Debt and Problem Areas in Code</h2>
<p>Technical debt refers to the accumulation of issues within a codebase that arise when development shortcuts are taken, often to meet tight deadlines or speed up releases. While these shortcuts may enable quicker progress initially, they lead to complications down the line.</p>
<p>Technical debt requires proactive management. If you leave it unchecked, it can reduce productivity, create bugs, and slow down development.</p>
<p>Think of technical debt like financial debt: taking on debt can be helpful in the short term, but failing to address it or pay it down will lead to greater challenges.</p>
<p>Common causes of technical debt include:</p>
<ul>
<li><p><strong>Rushed development cycles:</strong> When teams prioritize quick delivery over thorough design and testing, they may produce incomplete or hastily written code.</p>
</li>
<li><p><strong>Lack of planning for future changes:</strong> Sometimes, code is written without accounting for scalability, leading to issues as the project grows.</p>
</li>
<li><p><strong>Insufficient documentation or testing:</strong> Without proper documentation and test coverage, codebases become difficult to understand and validate over time.</p>
</li>
<li><p><strong>Outdated frameworks and dependencies:</strong> When frameworks or libraries aren’t updated, they can become incompatible with newer components or security standards, introducing risk and hindering future updates.</p>
</li>
</ul>
<h3 id="heading-types-of-technical-debt">Types of Technical Debt</h3>
<p>Technical debt manifests in different ways. Here are some common examples:</p>
<p><strong>1. Code Duplication:</strong></p>
<p>Repeated code across multiple places within a project can lead to inconsistencies, as fixing an issue or updating a feature in one area may not carry over to others. Refactoring duplicate code into reusable functions or components is an effective way to reduce this debt.</p>
<p><strong>Example:</strong> In a web application, you might find similar code for user authentication scattered across different modules. Instead, centralizing this logic into a single authentication module ensures consistent updates.</p>
<p><strong>2. Outdated Dependencies and Frameworks:</strong></p>
<p>Using old libraries or frameworks can slow down development and introduce security vulnerabilities. Over time, dependencies may lose support or become incompatible with new features, making them costly to maintain.</p>
<p><strong>Solution:</strong> Regularly update libraries and frameworks, and monitor for deprecations or vulnerabilities. This can be streamlined by using dependency managers, which help check for updates and security patches.</p>
<p><strong>3. Complex, Long Functions with Multiple Responsibilities:</strong></p>
<p>Large, complex functions that handle multiple tasks are difficult to understand, test, and modify. Known as “God functions,” these make debugging cumbersome and increase the risk of introducing new bugs.</p>
<p><strong>Solution:</strong> Follow the <strong>Single Responsibility Principle (SRP)</strong>. This means that each function or method should accomplish one task. Breaking down large functions into smaller, focused units makes the code easier to read and test.</p>
<p><strong>Example:</strong> Instead of having a single <code>processUserRequest</code> function that handles authentication, logging, and database queries, split it into three functions: <code>authenticateUser</code>, <code>logRequest</code>, and <code>queryDatabase</code>.</p>
<p><strong>4. Insufficient Error Handling:</strong></p>
<p>Code that lacks proper error handling can lead to bugs and unexpected behavior, especially in larger systems. Without clear error messages, diagnosing and fixing issues can be challenging.</p>
<p><strong>Solution:</strong> Include comprehensive error handling and ensure that meaningful error messages are displayed. Log errors in a way that helps developers track and diagnose issues.</p>
<p><strong>5. Hardcoded Values:</strong></p>
<p>Hardcoding values directly into code makes it difficult to adjust settings without modifying the source code. For example, using fixed URLs or credentials directly in the codebase can create security risks and maintenance headaches.</p>
<p><strong>Solution:</strong> Use configuration files or environment variables to store values that might change. This improves security and allows for easy updates.</p>
<p><strong>6. Lack of Documentation and Testing:</strong></p>
<p>Documentation and testing are often neglected when time is short. But without proper documentation and test coverage, the code becomes challenging to understand and validate, slowing down development and increasing the risk of bugs.</p>
<p><strong>Solution:</strong> Implement test-driven development (TDD) or include time in the development cycle for creating documentation and writing tests. Aim for at least basic test coverage for critical paths and functions.</p>
<h3 id="heading-how-to-identify-and-manage-technical-debt">How to Identify and Manage Technical Debt</h3>
<p>Identifying technical debt is crucial if you want to address and improve it. Here are some strategies you can follow:</p>
<ol>
<li><p><strong>Code Reviews:</strong> Regular peer reviews help uncover areas of potential debt. In reviews, team members can flag complex code, lack of tests, or unclear logic, helping address these issues early.</p>
</li>
<li><p><strong>Automated Static Code Analysis:</strong> Tools like SonarQube, Code Climate, and ESLint (for JavaScript) analyze codebases for code smells, vulnerabilities, and complexity. They’re effective for spotting issues like duplicate code, long functions, and outdated dependencies.</p>
</li>
<li><p><strong>Regular Refactoring Sessions:</strong> Scheduling dedicated time for refactoring allows the team to improve existing code quality. During these sessions, focus on simplifying code, breaking down large functions, and removing duplicates.</p>
</li>
<li><p><strong>Technical Debt Backlog:</strong> Track technical debt items in a backlog, prioritizing them alongside feature development. This backlog helps balance feature work with debt reduction and keeps everyone aware of existing debt.</p>
</li>
</ol>
<h3 id="heading-how-to-deal-with-technical-debt-in-code">How to Deal with Technical Debt in Code</h3>
<p>Here’s a practical example to demonstrate how refactoring can help address technical debt, specifically by removing code duplication.</p>
<h4 id="heading-example-removing-duplicate-code">Example: Removing Duplicate Code</h4>
<p>Let’s say we have two functions that send different types of emails but use repeated code:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Duplicate code example</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">send_welcome_email</span>(<span class="hljs-params">user</span>):</span>
    send_email(user.email, <span class="hljs-string">"Welcome!"</span>, <span class="hljs-string">"Thanks for joining!"</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">send_password_reset_email</span>(<span class="hljs-params">user</span>):</span>
    send_email(user.email, <span class="hljs-string">"Password Reset"</span>, <span class="hljs-string">"Click here to reset your password."</span>)
</code></pre>
<p>Each function has a similar structure, so refactoring can make the code cleaner and reduce duplication.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Refactored code</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">send_email_to_user</span>(<span class="hljs-params">user, subject, message</span>):</span>
    send_email(user.email, subject, message)

<span class="hljs-comment"># Use the refactored function</span>
send_email_to_user(new_user, <span class="hljs-string">"Welcome!"</span>, <span class="hljs-string">"Thanks for joining!"</span>)
send_email_to_user(existing_user, <span class="hljs-string">"Password Reset"</span>, <span class="hljs-string">"Click here to reset your password."</span>)
</code></pre>
<p>This example demonstrates how consolidation can reduce repetition and make the code more flexible.</p>
<h3 id="heading-how-to-avoid-technical-debt">How to Avoid Technical Debt</h3>
<p>Proactively managing technical debt helps reduce it over time. Here are ways to avoid accumulating more debt:</p>
<ul>
<li><p><strong>Establish Code Standards:</strong> Create and enforce coding standards within the team. Consistent practices reduce complexity, improve readability, and make it easier to identify issues early.</p>
</li>
<li><p><strong>Refactor Regularly:</strong> Rather than waiting for debt to accumulate, make minor improvements during routine work. A “leave it better than you found it” approach ensures code quality remains high over time.</p>
</li>
<li><p><strong>Encourage Thorough Testing:</strong> Strong test coverage identifies potential problems early, reducing the likelihood of code with hidden issues. Testing tools like Jest for JavaScript or PyTest for Python make it easy to add tests to each function and module.</p>
</li>
<li><p><strong>Plan for Scalability:</strong> Think about future needs when designing code. Avoid shortcuts that might restrict scalability and performance as the application grows.</p>
</li>
<li><p><strong>Limit Workarounds and Temporary Fixes:</strong> If temporary fixes are necessary, document them and prioritize removing them as soon as possible. Keeping track of these “quick fixes” ensures they don’t become long-term issues.</p>
</li>
</ul>
<h2 id="heading-how-to-measure-code-quality-with-code-analysis-tools">How to Measure Code Quality with Code Analysis Tools</h2>
<p>Code quality tools can help you find issues that might not be obvious. They can point out things like unused variables, code that’s hard to read, or security problems. Popular tools include <code>ESLint</code> for <code>JavaScript</code>, <code>Pylint</code> for <code>Python</code>, and <code>SonarQube</code> for different programming languages.</p>
<p>Here’s how to set up a simple code check with ESLint:</p>
<ol>
<li><p><strong>Install ESLint</strong>:</p>
<pre><code class="lang-bash"> npm install eslint --save-dev
</code></pre>
</li>
<li><p><strong>Initialize ESLint</strong>:</p>
<pre><code class="lang-bash"> npx eslint --init
</code></pre>
<p> This command will prompt you to answer a few configuration questions. You can choose your preferred style guide and select a few options about your environment and file format.</p>
</li>
<li><p><strong>Example Code with Issues</strong></p>
<p> Here’s a sample JavaScript file (<code>example.js</code>) with a few common issues:</p>
<pre><code class="lang-javascript"> <span class="hljs-comment">// example.js</span>

 <span class="hljs-keyword">var</span> x = <span class="hljs-number">10</span>;   <span class="hljs-comment">// Unused variable</span>
 <span class="hljs-keyword">let</span> y = <span class="hljs-number">5</span>;
 <span class="hljs-keyword">const</span> z = <span class="hljs-string">'Hello World'</span>

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

 calculateSum(<span class="hljs-number">3</span>, <span class="hljs-number">4</span>);

 <span class="hljs-comment">// Missing semicolon and inconsistent indentation</span>
 <span class="hljs-keyword">if</span>(y &gt; <span class="hljs-number">3</span>){
     <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Y is greater than 3"</span>)
 }
</code></pre>
</li>
<li><p><strong>Run ESLint</strong>:</p>
<pre><code class="lang-bash"> npx eslint example.js
</code></pre>
<p> After running this command, ESLint will analyze <code>example.js</code> and report any issues based on the configured rules.</p>
</li>
<li><p><strong>ESLint Output</strong></p>
<p> ESLint provides detailed feedback about the issues it detects:</p>
<pre><code class="lang-plaintext"> /path/to/example.js
   1:5  warning  'x' is assigned a value but never used          no-unused-vars
   3:12  error    Missing semicolon                               semi
   6:25  error    Missing semicolon                               semi
   10:1  error    Expected indentation of 4 spaces but found 3    indent
   11:26 error    Missing semicolon                               semi

 ✖ 5 problems (4 errors, 1 warning)
</code></pre>
<p> Here’s a breakdown of each issue detected by ESLint:</p>
<ul>
<li><p><strong>Unused Variable</strong>: ESLint identifies that <code>x</code> is declared but never used (<code>no-unused-vars</code> rule).</p>
</li>
<li><p><strong>Missing Semicolons</strong>: ESLint flags lines where semicolons are missing at the end of statements (<code>semi</code> rule).</p>
</li>
<li><p><strong>Inconsistent Indentation</strong>: ESLint notices that line 10 doesn’t follow consistent indentation (<code>indent</code> rule).</p>
</li>
</ul>
</li>
<li><p><strong>Fixing the Code</strong></p>
<p> Based on ESLint’s feedback, here’s the corrected code:</p>
<pre><code class="lang-javascript"> <span class="hljs-comment">// example.js</span>

 <span class="hljs-keyword">let</span> y = <span class="hljs-number">5</span>;
 <span class="hljs-keyword">const</span> z = <span class="hljs-string">'Hello World'</span>;

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

 calculateSum(<span class="hljs-number">3</span>, <span class="hljs-number">4</span>);

 <span class="hljs-keyword">if</span> (y &gt; <span class="hljs-number">3</span>) {
     <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Y is greater than 3"</span>);
 }
</code></pre>
<ul>
<li><p>We removed the unused variable <code>x</code>.</p>
</li>
<li><p>We added missing semicolons.</p>
</li>
<li><p>And we adjusted indentation for consistent spacing.</p>
</li>
</ul>
</li>
<li><p><strong>Re-run ESLint to Verify Fixes</strong></p>
<p> After making these changes, you can run <code>npx eslint example.js</code> again to confirm that there are no remaining issues. ESLint will return no output if everything is now clean, confirming that the code adheres to the configured standards.</p>
</li>
</ol>
<h3 id="heading-additional-tip-auto-fixing-with-eslint">Additional Tip: Auto-Fixing with ESLint</h3>
<p>ESLint can automatically fix some issues for you. To do this, use the <code>--fix</code> flag:</p>
<pre><code class="lang-bash">npx eslint example.js --fix
</code></pre>
<p>This command will automatically correct issues like indentation, unused variables, and missing semicolons where possible. But it’s important to review the changes to ensure they align with your intended functionality.</p>
<p>Reviewing code, spotting technical debt, and using quality tools help keep the codebase healthy. If you follow these steps, your project will be easier to manage and less likely to break.</p>
<h2 id="heading-ai-tools-to-help-you-improve-your-code">AI Tools to Help You Improve Your Code</h2>
<p>Using AI tools to restructure code makes improving code quality much faster and easier. These tools help find issues, suggest changes, and can even automate some parts of the refactoring process.</p>
<p>I'll share some AI tools that can help you with code analysis, refactoring, and dependency management, based on my own experience and what I've found useful.</p>
<h3 id="heading-best-ai-tools-for-code-restructuring">Best AI Tools for Code Restructuring</h3>
<p>AI-powered tools are becoming more common, and they offer different ways to boost code quality and simplify refactoring. Here are some I've found helpful:</p>
<h4 id="heading-1-github-copilot"><strong>1. GitHub Copilot</strong></h4>
<p>GitHub Copilot is like a coding assistant that provides smart suggestions as you write code. It can complete code snippets, suggest new functions, and help rework existing code to make it more efficient. I’ve found it useful for writing repetitive code blocks or coming up with quick refactorings.</p>
<p>For example, let’s say you need to rewrite a function to be more efficient:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Original function that checks if a number is prime</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">is_prime</span>(<span class="hljs-params">n</span>):</span>
    <span class="hljs-keyword">if</span> n &lt; <span class="hljs-number">2</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">2</span>, n):
        <span class="hljs-keyword">if</span> n % i == <span class="hljs-number">0</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
</code></pre>
<p>GitHub Copilot might suggest optimizing the function like this:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Optimized version suggested by Copilot</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">is_prime</span>(<span class="hljs-params">n</span>):</span>
    <span class="hljs-keyword">if</span> n &lt; <span class="hljs-number">2</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">2</span>, int(n**<span class="hljs-number">0.5</span>) + <span class="hljs-number">1</span>):
        <span class="hljs-keyword">if</span> n % i == <span class="hljs-number">0</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
</code></pre>
<p>The updated version checks factors only up to the square root of <code>n</code>, making it faster for large numbers.</p>
<h4 id="heading-2-qodogen"><strong>2. QodoGen</strong></h4>
<p>QodoGen provides automated suggestions for refactoring and can detect common code issues, like unused variables or large functions doing too many tasks. It also helps split complex code into smaller, more manageable pieces and can explain sections of the code base or the entire codebase which will facilitate the restructuring process.</p>
<p>This tool is capable of doing this because, unlike other AI assistants and general purpose code generation tools, Qodo focuses on code integrity, while generating tests that help you understand how your code behaves. This can help you discover edge cases and suspicious behaviors, and make your code more robust.</p>
<p>For example, if you have a function handling multiple tasks, QodoGen might suggest breaking it down:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Before refactoring</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">handle_user_data</span>(<span class="hljs-params">user_data</span>):</span>
    validate_data(user_data)
    save_to_database(user_data)
    send_welcome_email(user_data)

<span class="hljs-comment"># After refactoring</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">handle_user_data</span>(<span class="hljs-params">user_data</span>):</span>
    validated_data = validate_data(user_data)
    save_data(validated_data)
    notify_user(validated_data)
</code></pre>
<p>Separating the steps makes the code easier to maintain and test.</p>
<h4 id="heading-3-chatgpt-for-code-assistance"><strong>3. ChatGPT for Code Assistance</strong></h4>
<p>ChatGPT can act as a helpful companion when working on code restructuring tasks. Arguably the most used coding assistant, it provides advice on refactoring strategies, explains how to implement changes, or offers example snippets. It’s like having an expert to consult whenever you need guidance or ideas.</p>
<p>For instance, if you’re unsure how to optimize a function or restructure a class, ChatGPT can provide sample code or describe best practices. You can also ask it for help with understanding errors or fixing specific problems in your code.</p>
<p>Just make sure you double-check the code it provides (same goes for all these AI assistants) as it can hallucinate and make mistakes.</p>
<h3 id="heading-automated-tools-for-refactoring-and-analysis">Automated Tools for Refactoring and Analysis</h3>
<p>AI tools not only assist with writing code but also with analyzing it for quality improvements:</p>
<h4 id="heading-1-sonarqube"><strong>1. SonarQube</strong></h4>
<p>SonarQube scans the code to detect bugs, vulnerabilities, and code smells. It generates reports with suggestions on what to fix, helping maintain a healthy codebase.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Sample SonarQube configuration</span>
sonar.projectKey=my_project
sonar.sources=src
sonar.host.url=http://localhost:9000
sonar.login=my_token
</code></pre>
<h4 id="heading-2-resharper"><strong>2. ReSharper</strong></h4>
<p>This tool integrates with Visual Studio and offers automatic refactoring options. It highlights code that can be simplified or cleaned up and suggests ways to optimize the codebase.</p>
<h4 id="heading-3-depcheck-for-dependency-management"><strong>3. DepCheck for Dependency Management</strong></h4>
<p>AI tools like DepCheck help find unused dependencies in JavaScript projects, keeping package files clean.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Running DepCheck to find unused dependencies</span>
npx depcheck
</code></pre>
<h3 id="heading-how-these-tools-help-with-code-restructuring">How These Tools Help with Code Restructuring</h3>
<p>Using AI tools like GitHub Copilot, QodoGen, and ChatGPT speeds up the process of code restructuring. They provide suggestions that save time and catch issues early, making the code easier to maintain.</p>
<p>Combining these tools with automated analysis tools like SonarQube and ReSharper ensures all aspects of the codebase are covered, from quality checks to refactoring.</p>
<p>These AI tools have other features that facilitate this process: for example, they all have a chat feature that lets you ask questions and get replies about your code and any best practices you should be following. Also, QodoGen allows you to add parts of or the whole codebase for context with the click of a button, along with other features for test generation and pull request reviews.</p>
<p>When restructuring your codebase, having a variety of AI tools can make the process smoother and more efficient. This is AI usage at its best.</p>
<h2 id="heading-version-control-best-practices-for-code-changes">Version Control Best Practices for Code Changes</h2>
<p>Version control keeps track of code changes, making it easier to manage updates, collaborate with others, and fix issues. Following some best practices can help maintain a clean and organized codebase.</p>
<p>Let’s look at how to manage code changes, track updates, and ensure quality through code reviews.</p>
<h3 id="heading-using-git-branching-strategies-to-manage-code-changes">Using Git Branching Strategies to Manage Code Changes</h3>
<p>Git branching helps keep different versions of the code separate, allowing multiple developers to work without affecting the main codebase. Here are some common strategies:</p>
<h4 id="heading-1-feature-branching"><strong>1. Feature Branching</strong></h4>
<p>Feature branches allow developers to work on a new feature without changing the main codebase. Each feature gets its own branch, and once complete, it can be merged into the main branch.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Creating a new feature branch</span>
git checkout -b feature/new-login-page

<span class="hljs-comment"># Working on the new feature and then committing changes</span>
git add .
git commit -m <span class="hljs-string">"Added login page UI"</span>

<span class="hljs-comment"># Merging the feature branch into the main branch</span>
git checkout main
git merge feature/new-login-page
</code></pre>
<h4 id="heading-2-gitflow-strategy"><strong>2. GitFlow Strategy</strong></h4>
<p>This strategy involves using multiple branches for different stages of development, such as feature, develop, and release. It separates development work and allows smoother integration and deployment.</p>
<ul>
<li><p><strong>Main Branch</strong>: Contains production-ready code.</p>
</li>
<li><p><strong>Develop Branch</strong>: Holds the latest completed work, ready for the next release.</p>
</li>
<li><p><strong>Feature Branches</strong>: Created from the develop branch for new features.</p>
</li>
</ul>
<p>Example:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Switch to the develop branch</span>
git checkout develop

<span class="hljs-comment"># Create a new branch for a feature</span>
git checkout -b feature/upgrade-search

<span class="hljs-comment"># Commit changes and push the feature branch</span>
git add .
git commit -m <span class="hljs-string">"Improved search feature"</span>
git push origin feature/upgrade-search
</code></pre>
<h3 id="heading-how-to-track-and-document-code-updates">How to Track and Document Code Updates</h3>
<p>Documenting code changes helps keep the team informed and makes it easier to understand what was done later. Here are some tips for tracking updates:</p>
<h4 id="heading-1-writing-clear-commit-messages"><strong>1. Writing Clear Commit Messages</strong></h4>
<p>Commit messages should explain what was changed and why. A clear message helps others know the purpose of each update.</p>
<p>Example:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Good commit message</span>
git commit -m <span class="hljs-string">"Fixed bug that caused login failure on mobile devices"</span>

<span class="hljs-comment"># Bad commit message</span>
git commit -m <span class="hljs-string">"Fixed bug"</span>
</code></pre>
<h4 id="heading-2-using-tags-to-mark-releases"><strong>2. Using Tags to Mark Releases</strong></h4>
<p>Tags can be used to label important points in the project’s history, such as release versions. This makes it easier to find stable versions of the code.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create a tag for version 1.0</span>
git tag v1.0

<span class="hljs-comment"># Push the tag to the remote repository</span>
git push origin v1.0
</code></pre>
<h4 id="heading-3-creating-and-using-changelogs"><strong>3. Creating and Using Changelogs</strong></h4>
<p>A changelog lists the changes made in each version, helping developers and users see what was updated or fixed.</p>
<p>Example format for a changelog:</p>
<pre><code class="lang-plaintext">## [1.0.1] - 2024-10-01
### Added
- New login feature

### Fixed
- Resolved search issue on homepage

### Changed
- Updated user dashboard layout
</code></pre>
<h3 id="heading-importance-of-code-reviews-in-maintaining-code-quality">Importance of Code Reviews in Maintaining Code Quality</h3>
<p>Code reviews help catch errors, share knowledge, and ensure code stays clean and maintainable. Here are some practices to follow for effective code reviews:</p>
<h4 id="heading-1-keep-code-changes-small"><strong>1. Keep Code Changes Small</strong></h4>
<p>Smaller changes are easier to review, making it more likely to spot mistakes. Large changes can be broken down into smaller parts.</p>
<h4 id="heading-2-use-pull-requests-for-reviews"><strong>2. Use Pull Requests for Reviews</strong></h4>
<p>Pull requests create a space for discussion around changes. Team members can review the changes, suggest improvements, and approve the updates.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Push the feature branch to the remote repository</span>
git push origin feature/new-feature

<span class="hljs-comment"># Create a pull request on GitHub, GitLab, or Bitbucket</span>
</code></pre>
<h4 id="heading-3-provide-constructive-feedback"><strong>3. Provide Constructive Feedback</strong></h4>
<p>Code reviews should aim to improve the code without discouraging the developer. Suggest better ways to solve problems and explain the reasoning.</p>
<p>Example comments during a code review:</p>
<ul>
<li><p>"Consider using a list instead of a dictionary for this data structure, as it simplifies the code."</p>
</li>
<li><p>"This function is doing multiple tasks. It might be clearer if we split it into two separate functions."</p>
</li>
</ul>
<p>Using these practices helps ensure code changes are managed effectively, updates are well-documented, and the quality of the codebase remains high. Regular code reviews and proper branching strategies make it easier for teams to collaborate and keep the project on track.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Reviving and restructuring a codebase can seem like a big task, but taking small, planned steps makes it manageable. Start by checking the current state of the code and making a list of areas that need work. Set clear goals and create a plan to improve the code, step by step.</p>
<p>Using the tools we discussed here can help find issues, suggest changes, and even automate some tasks. Version control practices, such as branching strategies and code reviews, keep changes organized and ensure the quality stays high.</p>
<p>With a solid approach, even the messiest codebase can become clean, efficient, and easier to work with.</p>
<h3 id="heading-resources">Resources</h3>
<ul>
<li><p>AI tools have been developed to assist with the Git branching, Pull Request reviews and approval. Check out <a target="_blank" href="https://dev.to/oluwadamisisamuel1/merge-mastery-elevating-your-pull-request-game-in-open-source-projects-25fo">this article</a> to read more on one of my favorites.</p>
</li>
<li><p>If you want a step by step tutorial on how to revive and refactor your code, check out <a target="_blank" href="https://youtu.be/yMQJUaUtiJo?si=CGd2WBcD117p7lrS">this youtube video</a>.</p>
</li>
<li><p>Check out <a target="_blank" href="https://www.freecodecamp.org/news/best-practices-for-refactoring-code/">this freecodecamp article</a> on code restructuring to dive deeper.</p>
</li>
</ul>
<p>Connect with me on <a target="_blank" href="https://www.linkedin.com/in/samuel-oluwadamisi-01b3a4236/?lipi=urn%3Ali%3Apage%3Ad_flagship3_feed%3BxAUJMbSgQTeDtb7n2d0mQQ%3D%3D">LinkedIn</a>, <a target="_blank" href="https://twitter.com/Data_Steve_">Twitter</a>, and <a target="_blank" href="https://dev.to/dashboard">my peronal blog</a> if you found this helpful.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How AI Tools Can Help You Reuse Code ]]>
                </title>
                <description>
                    <![CDATA[ Reusing code is an important part of software development. Instead of writing the same code again and again, developers can save time and effort by using code that already works. This not only speeds up the development process but also helps improve ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/tools-for-code-reuse/</link>
                <guid isPermaLink="false">66f46fb236ee3dad69878324</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Programming Tips ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learning ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwadamisi Samuel ]]>
                </dc:creator>
                <pubDate>Wed, 25 Sep 2024 20:16:50 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727102263215/bcd245a1-4e4e-4563-8f6c-1715b5f8ed13.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Reusing code is an important part of software development. Instead of writing the same code again and again, developers can save time and effort by using code that already works. This not only speeds up the development process but also helps improve the quality of the final product.</p>
<p>There are several popular ways to create reusable code, and each has its strengths and weaknesses. But they all share a common goal: making it easier for you to avoid reinventing the wheel.</p>
<p>And now, with the improvements in AI, you can take advantage of the available technology to make the development process easier, faster, and more efficient.</p>
<p>In this article, we’ll explore the benefits of code reuse, discuss popular tools for finding reusable code (which, in my opinion, are the best tools to use), and examine how different solutions can help you work more efficiently.</p>
<h3 id="heading-table-of-contents">Table of Contents</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-the-benefits-of-code-reuse">Benefits of Code Reuse</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-popular-options-for-code-reuse">Popular Options for Code Reuse</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-the-benefits-of-code-reuse">The Benefits of Code Reuse</h2>
<p>Reusing code brings many advantages that make software development faster and better. Using code that already works helps you avoid doing the same tasks again and again. It also helps you follow the “DRY” principle, and lets you focus on more important parts of your projects.</p>
<h3 id="heading-time-savings-and-faster-development-cycles">Time Savings and Faster Development Cycles</h3>
<p>A key benefit of reusing code is the amount of time it saves. You no longer need to spend hours rewriting common functions or tasks that have already been solved. This allows you to quickly add these pieces to new projects and spend more time building new features that make your product unique.</p>
<h3 id="heading-improved-code-quality">Improved Code Quality</h3>
<p>Code that has already been tested and proven tends to have fewer mistakes. Using reusable code that has been checked before means you can trust that it will work properly, reducing the chances of bugs and errors in the final product.</p>
<h3 id="heading-increased-consistency">Increased Consistency</h3>
<p>Reusing code helps create consistency across different projects. The same functions and logic are applied in every project, ensuring everything works in a similar way. This makes the codebase easier to understand and maintain.</p>
<h3 id="heading-enhanced-collaboration-and-knowledge-sharing">Enhanced Collaboration and Knowledge Sharing</h3>
<p>When teams share and reuse components, collaboration becomes easier. Team members can work together more efficiently, using familiar code pieces. This also helps spread knowledge across the team, as everyone benefits from understanding and using the same code.</p>
<h3 id="heading-cost-efficiency">Cost Efficiency</h3>
<p>Reusing existing solutions helps reduce costs. Since you spend less time creating new code from scratch, the development process becomes cheaper. This can also lead to faster project completion, which saves money in the long run.</p>
<h2 id="heading-popular-options-for-code-reuse">Popular Options for Code Reuse</h2>
<p>There are several tools and platforms that developers rely on to find reuseable code. There are widely used options like Google, StackOverflow, and documentation. And on the other hand there are newer AI tools like ChatGPT, Gemini, and Codiumate to mention a few.</p>
<p>Each option has its own strengths and weaknesses, but they all aim to make coding easier and faster by offering pre-existing solutions. Below, we’ll look at some of the most popular options and compare how they help with code reuse.</p>
<h3 id="heading-google-search">Google Search</h3>
<p>Google is one of the most widely-used tools for finding code snippets and tutorials. Developers often search for specific solutions, reading through blog posts, forums, and official documentation to find what they need.</p>
<p><strong>Advantages</strong>:</p>
<ul>
<li><p>Access to a vast amount of information, tutorials, and resources across the web.</p>
</li>
<li><p>Great for finding niche solutions or specific examples.</p>
</li>
<li><p>Helpful for discovering documentation and learning new technologies.</p>
</li>
</ul>
<p><strong>Disadvantages</strong>:</p>
<ul>
<li><p>Finding the right solution often involves sifting through a lot of content.</p>
</li>
<li><p>Not all resources are trustworthy or up-to-date.</p>
</li>
<li><p>It can take longer to find specific, reusable code compared to other platforms.</p>
</li>
</ul>
<p><strong>Google in Action</strong>: A quick goggle search will show results comprised of articles and publications related to your question. Going through these articles might help with the exact code you are searching for.</p>
<h3 id="heading-stack-overflow">Stack Overflow</h3>
<p>Stack Overflow is a popular online forum where developers ask questions and share solutions to programming problems, and it’s been a reliable friend to developers over the years.</p>
<p>It has a massive library of answers and code snippets provided by the developer community. It also now has an AI feature which we’ll discuss in the next section. You get access to different solutions to the same problem provided by developers.</p>
<p><strong>Advantages</strong>:</p>
<ul>
<li><p>Large collection of real-world code examples and solutions.</p>
</li>
<li><p>Answers are often reviewed and voted on by other users, making it easier to find high-quality code.</p>
</li>
<li><p>Covers a wide range of coding topics and issues.</p>
</li>
</ul>
<p><strong>Disadvantages</strong>:</p>
<ul>
<li><p>Requires manual searching, which can be time-consuming.</p>
</li>
<li><p>Some solutions may be outdated or not relevant to modern development practices.</p>
</li>
<li><p>It’s not always easy to find code that fits perfectly with your specific project needs.</p>
</li>
</ul>
<p><strong>StackOverflow in Action</strong>: You can just open up the site in your browser and search what ever question you need and the highest rated answers will be provided:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727287523667/2d476910-327a-42b2-a52f-6247e3b0e1f9.png" alt="StackOverflow search results example" class="image--center mx-auto" width="1856" height="1320" loading="lazy"></p>
<h3 id="heading-multi-purpose-ai-tools-like-chatgpt-and-gemini">Multi-Purpose AI Tools (like ChatGPT and Gemini)</h3>
<p>ChatGPT and Gemini are AI tools that help developers by providing code snippets and answering programming questions. They are known for their versatility, supporting a wide range of programming languages and offering quick suggestions on how to solve coding problems.</p>
<p>These tools are growing each day and have truly revolutionised the tech space. They can provide code snippets quickly and with sources.</p>
<p><strong>Advantages</strong>:</p>
<ul>
<li><p>Can generate code for various languages and frameworks.</p>
</li>
<li><p>Provides quick explanations and examples and sources.</p>
</li>
<li><p>Easy to use for beginners and experienced developers alike.</p>
</li>
</ul>
<p><strong>Disadvantages</strong>:</p>
<ul>
<li><p>These AI toools are general-purpose, so they may not always provide the most optimized or accurate code for complex tasks and sometimes struggle with context.</p>
</li>
<li><p>Since they’re not focused solely on coding, they might miss important details or suggest outdated solutions.</p>
</li>
</ul>
<p><strong>ChatGPT in Action</strong>: Let’s see ChatGPT in action with a simple question and the sample code it gives us:</p>
<p><strong>Question:</strong> “Can you generate a function to validate form inputs in JavaScript?"</p>
<p><strong>Response:</strong> Here’s a reusable JavaScript function to validate form inputs. This function will validate if inputs are not empty, and optionally check for conditions such as valid email addresses, minimum character length, and numeric validation. You can expand it depending on the form requirements.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">validateForm</span>(<span class="hljs-params">inputs</span>) </span>{
  <span class="hljs-keyword">let</span> errors = {};

  inputs.forEach(<span class="hljs-function"><span class="hljs-params">input</span> =&gt;</span> {
    <span class="hljs-keyword">const</span> { name, value, type, required, minLength, pattern } = input;

    <span class="hljs-comment">// Check if the input is required and empty</span>
    <span class="hljs-keyword">if</span> (required &amp;&amp; !value) {
      errors[name] = <span class="hljs-string">`<span class="hljs-subst">${name}</span> is required`</span>;
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-comment">// Check for minimum length</span>
    <span class="hljs-keyword">if</span> (minLength &amp;&amp; value.length &lt; minLength) {
      errors[name] = <span class="hljs-string">`<span class="hljs-subst">${name}</span> must be at least <span class="hljs-subst">${minLength}</span> characters`</span>;
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-comment">// Check for valid email format</span>
    <span class="hljs-keyword">if</span> (type === <span class="hljs-string">'email'</span> &amp;&amp; !<span class="hljs-regexp">/\S+@\S+\.\S+/</span>.test(value)) {
      errors[name] = <span class="hljs-string">'Invalid email address'</span>;
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-comment">// Check if the input matches the specified pattern (e.g., phone number)</span>
    <span class="hljs-keyword">if</span> (pattern &amp;&amp; !<span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(pattern).test(value)) {
      errors[name] = <span class="hljs-string">`<span class="hljs-subst">${name}</span> is invalid`</span>;
      <span class="hljs-keyword">return</span>;
    }
  });

  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.keys(errors).length ? errors : <span class="hljs-literal">true</span>;
}

<span class="hljs-comment">// Example usage:</span>
<span class="hljs-keyword">const</span> inputs = [
  { <span class="hljs-attr">name</span>: <span class="hljs-string">'username'</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">'john_doe'</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">minLength</span>: <span class="hljs-number">5</span> },
  { <span class="hljs-attr">name</span>: <span class="hljs-string">'email'</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">'john@example'</span>, <span class="hljs-attr">type</span>: <span class="hljs-string">'email'</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span> },
  { <span class="hljs-attr">name</span>: <span class="hljs-string">'password'</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">'1234'</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">minLength</span>: <span class="hljs-number">6</span> },
];

<span class="hljs-keyword">const</span> validation = validateForm(inputs);
<span class="hljs-built_in">console</span>.log(validation);
</code></pre>
<p>This response will save you the trouble of thinking about the logic and still gives space for customization. Just make sure to test the code to make sure it works for your purposes.</p>
<h3 id="heading-overflow-ai-from-stack-overflow">Overflow AI (from Stack Overflow)</h3>
<p>Overflow AI is a generative AI tool integrated into the Stack Overflow platform where users can ask questions in natural language and receive summarized answers. The answers include proper citations for existing content from Stack Overflow’s massive library.</p>
<p>Overflow AI can provide code snippets and solutions to your problems using the highest rated answers. Just keep in mind that there doesn’t appear to be a free version at the moment, so you may have to pay for the service.</p>
<p><strong>Advantages</strong>:</p>
<ul>
<li><p>Access to Stack Overflow’s large collection of real-world code examples and solutions.</p>
</li>
<li><p>Answers provided are the highest voted answers to your specific question.</p>
</li>
<li><p>Code provided is usually of the highest quality.</p>
</li>
<li><p>It can be integrated into your IDE and Slack platform for teams.</p>
</li>
</ul>
<p><strong>Disadvantages</strong>:</p>
<ul>
<li><p>Some answers may not suit your specific needs for more complex problems or code.</p>
</li>
<li><p>It struggles with context as other multi-purpose AI tools do as there is no way to train it specifically for your project.</p>
</li>
</ul>
<p><strong>OverFlow AI in Action</strong>: OverFlow AI is currently only available for Stack Overflow for Teams Enterprise. Companies are required to have a subscription for their teams.</p>
<h3 id="heading-codiumate">Codiumate</h3>
<p>Codiumate is an open-source AI-powered coding assistant designed specifically to enhance the software development process. It’s trained solely for the purpose of assisting developers by providing high quality and reusable code, iterative tests, PR reviews, and code completion.</p>
<p>It also has a chat feature which lets you ask questions. But the most impressive feature it has, in my view, is the option to input your entire codebase or chunks of it so that it has context for the code you need from it.</p>
<p>When it comes to reusing code effectively, having a tool specifically designed for that purpose makes all the difference. And it’s great that Codiumate is an open-source tool, too.</p>
<h4 id="heading-advantages">Advantages:</h4>
<ul>
<li><p>Codiumate is specialized. While other tools like ChatGPT are useful for many tasks, Codiumate’s focus allows it to deliver more precise and relevant recommendations for code reuse.</p>
</li>
<li><p>It can scan large codebases quickly, identifying opportunities to reuse code, and offering seamless integration options.</p>
</li>
<li><p>It possesses features like automatic test creation and real-time bug detection.</p>
</li>
<li><p>It has smart code completion, a coding assistant, and a PR-agent for Pull Request reviews(chrome extension) which makes it a one-stop shop.</p>
</li>
</ul>
<h4 id="heading-limitations">Limitations:</h4>
<ul>
<li><p>As an open-source tool, Codiumate may require some initial setup or customization to fit your specific development environments. This can take a little extra time upfront, especially for developers who aren't familiar with the tool. But once it's integrated, the time savings and improvements to code quality make it well worth the effort. <a target="_blank" href="https://codiumate-docs.codium.ai/installation/">You can find the link to setup here.</a></p>
</li>
<li><p>Since Codiumate is designed specifically for code reuse, it may not be the best tool for handling broader queries outside the realm of coding. If you’re looking for more general advice or help with non-code-related tasks, you might still need to use other tools like ChatGPT. But for focused, efficient code reuse, Codiumate is a great choice.</p>
</li>
</ul>
<p><strong>Codiumate in Action</strong>: Let’s see Codiumate in action:</p>
<p>After setting Codiumate up (which takes about 2 minutes), you can access the chat feature where you can add the entire codebase or highlight part of it for context to get more specific results:</p>
<p>Question: “Can you generate a function to validate form inputs in JavaScript?"</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727285759800/4ff8044f-30b6-49a7-a9ef-ba264f215f33.png" alt="4ff8044f-30b6-49a7-a9ef-ba264f215f33" class="image--center mx-auto" width="994" height="224" loading="lazy"></p>
<p>Response:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727285642041/d56681a4-94f0-410d-ac4d-b4706bc6c363.gif" alt="Codiumate generating the code to validate inputs in JavaScript" class="image--center mx-auto" width="1152" height="648" loading="lazy"></p>
<p>You can expand this function to include more validations as needed, such as checking for special characters in the password, matching passwords, and so on by clicking the “continue this chat” button.</p>
<h3 id="heading-additional-resources">Additional Resources</h3>
<p>There are a ton of AI tools and platforms available with similar features and we’re almost spoiled for choice at this point.</p>
<p>Here are a few additional resources about some of my favorite tools I discussed:</p>
<ul>
<li><p>Read more on <a target="_blank" href="https://codiumate-docs.codium.ai/">Codiumate</a></p>
</li>
<li><p><a target="_blank" href="https://stackoverflow.co/teams/resources/introducing-overflowai/">Read more on OverflowAI</a></p>
</li>
<li><p><a target="_blank" href="https://youtu.be/ui5SdYR7Ivs?si=UEyIeg1UtsXxkk2O">How to reuse code with codiumate (Youtube)</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-ai-to-improve-code-quality/">Using AI to improve code quality</a></p>
</li>
</ul>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Reusing code is a useful practice that makes development faster and easier. It allows developers to focus on creating new features while keeping their projects consistent. Reusing code also helps teams work together better and share knowledge more easily.</p>
<p>There are a ton of AI platforms available like to help with code reuse, and each has its own benefits (and I haven’t covered them all here.</p>
<p>You should take advantage of these AI tools and make your choice based on which tools suits you more. Codiumate and OverflowAI stand out above the rest to me, but the right tool will depend on what you need at that moment.</p>
<p>In the end, AI tools are there to make the development process more streamlined, cheaper, and to ultimately make your life easier as a developer.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React Optimization Techniques to Help You Write More Performant Code ]]>
                </title>
                <description>
                    <![CDATA[ Performance optimization is a critical aspect of developing web applications. Users expect applications to load quickly and respond to their interactions smoothly.  In the React ecosystem, performance optimization techniques can significantly enhance... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-performance-optimization-techniques/</link>
                <guid isPermaLink="false">66bf4b68be10d17622ff3a0c</guid>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Temitope Oyedele ]]>
                </dc:creator>
                <pubDate>Fri, 16 Feb 2024 00:57:28 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/pexels-howard-adams-575835--1-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Performance optimization is a critical aspect of developing web applications. Users expect applications to load quickly and respond to their interactions smoothly. </p>
<p>In the React ecosystem, performance optimization techniques can significantly enhance the user experience by reducing load times and improving responsiveness.</p>
<p>In this article, we will discuss eight effective techniques for optimizing the performance of your React application.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-why-performance-optimization-is-important">Why Performance Optimization is Important</a></li>
<li><a class="post-section-overview" href="#heading-list-visualization">List visualization</a></li>
<li><a class="post-section-overview" href="#heading-lazy-loading-images">Lazy Loading Images</a></li>
<li><a class="post-section-overview" href="#heading-memoization">Memoization</a></li>
<li><a class="post-section-overview" href="#heading-throttling-and-debouncing-events">Throttling and Debouncing Events</a></li>
<li><a class="post-section-overview" href="#heading-code-splitting">Code Splitting</a></li>
<li><a class="post-section-overview" href="#heading-react-fragments">React Fragments</a></li>
<li><a class="post-section-overview" href="#heading-web-workers">Web Workers</a></li>
<li><a class="post-section-overview" href="#heading-usetransition-hook">UseTransition Hook</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<h2 id="heading-why-performance-optimization-is-important">Why Performance Optimization is Important</h2>
<p>Optimizing the performance of your React application is crucial for several reasons:</p>
<ul>
<li><strong>Better User Experience:</strong> A slow-loading or laggy application can lead to a poor user experience, negatively impacting your business. Users expect fast and responsive interactions, and performance optimization helps deliver that.</li>
<li><strong>Improved SEO:</strong> Search engines like Google consider page load times and overall performance when ranking websites. A well-optimized application will rank higher in search results, making it more visible to potential users.</li>
<li><strong>Reduced Bounce Rates:</strong> If your application takes too long to load or respond, users will likely leave and never return. By optimizing performance, you can reduce bounce rates and increase engagement.</li>
<li><strong>Cost Savings</strong> A performant application requires fewer resources (like servers and memory) to handle the same workload. This means lower hosting costs and reduced infrastructure needs.</li>
<li><strong>Competitive Advantage:</strong> A fast and efficient application sets you apart from competitors whose applications may be slower or less optimized. According to research by <a target="_blank" href="https://www.portent.com/blog/analytics/research-site-speed-hurting-everyones-revenue.htm">Portent</a>, a website that loads within one second has a conversion rate five times higher than a site that takes ten seconds to load. Therefore, ensuring your React applications perform well is crucial for retaining users and maintaining a competitive edge.</li>
</ul>
<h2 id="heading-8-react-performance-optimization-techniques">8 React Performance Optimization Techniques</h2>
<p>Below are eight React performance optimization techniques you can use to speed up your applications.</p>
<h3 id="heading-list-visualization">List visualization</h3>
<p>List visualization, or windowing, involves rendering only the items currently visible on the screen. </p>
<p>When dealing with a large number of items in a list, rendering all the items at once can lead to slow performance and consume a significant amount of memory. List virtualization tackles this issue by rendering only a subset of the list items currently visible within the view, which conserves resources as the users scroll through the list.</p>
<p>The virtualization technique dynamically replaces rendered items with new ones, keeping the visible portion of the list updated and responsive. It efficiently allows you to render large lists or tabular data by only rendering the visible portion, recycling components as needed, and optimizing scroll performance.</p>
<p>There are different approaches to implementing list visualization in React, and one is using a popular library called <a target="_blank" href="https://www.npmjs.com/package/react-virtualized">React Virtualized</a>. </p>
<p>To install <code>react-virtualized</code>, you can use the following command:</p>
<pre><code class="lang-bash">npm install react-virtualized --save
</code></pre>
<p>After installing <code>react-virtualized</code>, you can import the required components and styles. Below is an example of how to use the <code>List</code> component to create a virtualized list:</p>
<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> { List } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-virtualized'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'react-virtualized/styles.css'</span>; <span class="hljs-comment">// Import styles</span>

<span class="hljs-comment">// Your list data</span>
<span class="hljs-keyword">const</span> list = <span class="hljs-built_in">Array</span>(<span class="hljs-number">5000</span>).fill().map(<span class="hljs-function">(<span class="hljs-params">_, index</span>) =&gt;</span> ({
  <span class="hljs-attr">id</span>: index,
  <span class="hljs-attr">name</span>: <span class="hljs-string">`Item <span class="hljs-subst">${index}</span>`</span>
}));

<span class="hljs-comment">// Function to render each row</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rowRenderer</span>(<span class="hljs-params">{ index, key, style }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{key}</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{style}</span>&gt;</span>
      {list[index].name}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// Main component</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyVirtualizedList</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">List</span>
      <span class="hljs-attr">width</span>=<span class="hljs-string">{300}</span>
      <span class="hljs-attr">height</span>=<span class="hljs-string">{300}</span>
      <span class="hljs-attr">rowCount</span>=<span class="hljs-string">{list.length}</span>
      <span class="hljs-attr">rowHeight</span>=<span class="hljs-string">{20}</span>
      <span class="hljs-attr">rowRenderer</span>=<span class="hljs-string">{rowRenderer}</span>
    /&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyVirtualizedList;
</code></pre>
<p>In this example, <code>List</code> is the main component provided by <code>react-virtualized</code>. The <code>rowRenderer</code> function defines how each row should be rendered. The <code>width</code>, <code>height</code>, <code>rowCount</code>, <code>rowHeight</code>, and <code>rowRenderer</code> props are essential for configuring the list's behavior and appearance. </p>
<p>React applications can handle massive amounts of data by leveraging list virtualization without sacrificing performance or user experience.</p>
<h3 id="heading-lazy-loading-images">Lazy Loading Images</h3>
<p>Similar to the list virtualization technique, lazy loading images prevents the creation of unnecessary DOM nodes, thereby boosting performance. Lazy loading allows you to defer or delay the loading of images until they are needed or visible to the user instead of loading all the images on page load.</p>
<p>The concept behind lazy loading is to initiate the load of a placeholder or a small low-resolution version of the image, typically a small-sized thumbnail or a blurred placeholder. As the user scrolls or interacts with the page, the actual image is loaded dynamically, replacing the placeholder when the user enters the viewport or when it becomes visible.</p>
<p>Lazy loading in React can be achieved using various libraries and techniques. One of the popular libraries is the <a target="_blank" href="https://www.npmjs.com/package/react-lazyload">react-lazyload</a>.  </p>
<p>To install <code>react-lazyload</code>, you can use the following command:</p>
<pre><code class="lang-bash">npm install --save react-lazyload
</code></pre>
<p>Below is an example of a simple React component that uses <code>react-lazyload</code> to implement lazy loading for images:</p>
<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> LazyLoad <span class="hljs-keyword">from</span> <span class="hljs-string">'react-lazyload'</span>;

<span class="hljs-keyword">const</span> MyLazyLoadedImage = <span class="hljs-function">(<span class="hljs-params">{ src, alt }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">LazyLoad</span> <span class="hljs-attr">height</span>=<span class="hljs-string">{200}</span> <span class="hljs-attr">offset</span>=<span class="hljs-string">{100}</span>&gt;</span>
      {/* The height and offset props control when the image should start loading */}
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{src}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">{alt}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">LazyLoad</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyLazyLoadedImage;
</code></pre>
<p>In this example, <code>MyLazyLoadedImage</code> uses the <code>LazyLoad</code> component from <code>react-lazyload</code>. The <code>height</code> prop specifies the height of the placeholder, and the <code>offset</code> prop determines how far below the viewport the placeholder should start loading.</p>
<p>Another approach is to use the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API">intersection observer API</a>, which is a web API that allows you to detect when an element enters or exists the viewport efficiently. Here's how we can use the Intersection Observer API along with the <code>useEffect</code> hook in React:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useEffect, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> IntersectionLazyLoad = <span class="hljs-function">(<span class="hljs-params">{ src, alt }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> imageRef = useRef();

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> options = {
      <span class="hljs-attr">root</span>: <span class="hljs-literal">null</span>, <span class="hljs-comment">// Use the viewport as the root</span>
      <span class="hljs-attr">rootMargin</span>: <span class="hljs-string">'0px'</span>, <span class="hljs-comment">// No margin around the root</span>
      <span class="hljs-attr">threshold</span>: <span class="hljs-number">0.5</span>, <span class="hljs-comment">// 50% of the image should be visible</span>
    };

    <span class="hljs-keyword">const</span> observer = <span class="hljs-keyword">new</span> IntersectionObserver(handleIntersection, options);

    <span class="hljs-keyword">if</span> (imageRef.current) {
      observer.observe(imageRef.current);
    }

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-comment">// Cleanup the observer when the component is unmounted</span>
      observer.disconnect();
    };
  }, []);

  <span class="hljs-keyword">const</span> handleIntersection = <span class="hljs-function">(<span class="hljs-params">entries</span>) =&gt;</span> {
    entries.forEach(<span class="hljs-function">(<span class="hljs-params">entry</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (entry.isIntersecting) {
        <span class="hljs-comment">// Load the image when it becomes visible</span>
        imageRef.current.src = src;
        imageRef.current.alt = alt;
      }
    });
  };

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{imageRef}</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">height:</span> '<span class="hljs-attr">200px</span>' }} <span class="hljs-attr">alt</span>=<span class="hljs-string">"Placeholder"</span> /&gt;</span></span>;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> IntersectionLazyLoad;
</code></pre>
<p>In this example, <code>IntersectionLazyLoad</code> uses the Intersection Observer API to determine when the image becomes visible in the viewport. </p>
<p>By utilizing this API along with React <code>useEffect</code> hook, you can implement your custom lazy loading solution for images in React.</p>
<h3 id="heading-memoization">Memoization</h3>
<p>Memoization in React is a technique used to optimize the performance of functional components by caching the results of expensive computations or function calls. It's particularly useful when dealing with computationally intensive or frequently called functions with the same input values, as it helps avoid redundant calculations and improves the overall efficiency of the application.</p>
<p>In React, there are three techniques for memoization: <code>React.memo()</code>, <code>useMemo(),</code> and <code>useCallback().</code> Let's delve into the details for each:</p>
<h4 id="heading-how-to-use-reactmemo">How to use <code>React.memo()</code></h4>
<p>This higher-order component wraps purely functional components to prevent re-rendering if the received props remain unchanged.</p>
<p>By using <code>React.memo()</code>, the rendering result is cached based on props. If the props haven't changed since the last render, React reuses the previously rendered result instead of redoing the rendering process. This saves time and resources.</p>
<p> Below is an example on how to use the <code>React.memo</code> with a functional component:</p>
<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> Post = <span class="hljs-function">(<span class="hljs-params">{ signedIn, post }</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Rendering Post'</span>);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{post.title}<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>{post.content}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      {signedIn &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Edit Post<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> React.memo(Post);
</code></pre>
<p>In the code above, <code>Post</code> (functional component) depends on the <code>signedIn</code> and <code>post</code> props. By wrapping it with <code>React.memo()</code>, React will only re-render the <code>Post</code> component if either <code>signedIn</code> or <code>post</code> changes.</p>
<p>You can now use the memoized component like any other component in your application:</p>
<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> Post <span class="hljs-keyword">from</span> <span class="hljs-string">'./Post'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [signedIn, setSignedIn] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> post = { <span class="hljs-attr">title</span>: <span class="hljs-string">'Hello World'</span>, <span class="hljs-attr">content</span>: <span class="hljs-string">'Welcome to my blog!'</span> };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Post</span> <span class="hljs-attr">signedIn</span>=<span class="hljs-string">{signedIn}</span> <span class="hljs-attr">post</span>=<span class="hljs-string">{post}</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setSignedIn(!signedIn)}&gt;
        Toggle Signed In
      <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>
<p>When you click the <code>Toggle Signed In</code> button, it will toggle the <code>signedIn</code> state. Since <code>Post</code> is wrapped with <code>React.memo()</code>, it will only re-render when the <code>signedIn</code> prop changes, thus saving rendering time and resources</p>
<h4 id="heading-how-to-use-usememo">How to use <code>useMemo()</code></h4>
<p>The <code>useMemo()</code> hook optimizes performance by memoizing the result of a function call or an expensive computation. It caches the result and recalculates it only when the input values change. Below is an example on how to use the <code>useMemo</code> hook in functional component:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useMemo } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [count, setCount] = React.useState(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">const</span> [otherState, setOtherState] = React.useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">const</span> expensiveComputation = <span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> {
    <span class="hljs-keyword">let</span> i =  <span class="hljs-number">0</span>;
    <span class="hljs-keyword">while</span> (i &lt;  <span class="hljs-number">1000000000</span>) i++;
    <span class="hljs-keyword">return</span> num * num;
  };

  <span class="hljs-keyword">const</span> memoizedValue = useMemo(<span class="hljs-function">() =&gt;</span> expensiveComputation(count), [count]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {count}<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>Square: {memoizedValue}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count +  1)}&gt;Increase Count<span class="hljs-tag">&lt;/<span class="hljs-name">button</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">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setOtherState(e.target.value)} /&gt;
    <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>
<p>In the code above, the <code>expensiveComputation</code> function simulates a resource-intensive operation, like squaring a number. </p>
<p>The <code>useMemo</code> hook is utilized to cache the result of this computation. The memoized value, stored in <code>memoizedValue</code>, is only recalculated when the <code>count</code> state changes, as <code>count</code> is specified as a dependency in the <code>useMemo</code> dependency array. Consequently, clicking the <code>Increase Count</code> button increments the <code>count</code> state, triggering a recalculation of the memoized value. </p>
<p>Conversely, changing the <code>otherState</code> via the input field does not prompt a recalculation, as <code>otherState</code> is not included in the <code>useMemo</code> dependency array.</p>
<h4 id="heading-how-to-use-usecallback">How to use <code>useCallback()</code></h4>
<p>The <code>useCallback()</code> hook in React is used to memoize a function instead of memoizing the function result. It is particularly useful when passing events as props to child components to prevent unnecessary re-renders. </p>
<p><code>useCallback()</code> memoizes the function, ensuring it remains the same across re-renders as long as the dependencies haven't changed. </p>
<p>This is especially beneficial when passing functions as props to child components, preventing unnecessary re-renders. It is often used with <code>React.memo()</code> to ensure child components do not re-render when unnecessary. Below is an exmple of how to use the <code>useCallback()</code> hook:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState, useCallback } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

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

  <span class="hljs-comment">// Define a function that increments the count state</span>
  <span class="hljs-keyword">const</span> incrementCount = <span class="hljs-function">() =&gt;</span> {
    setCount(count + <span class="hljs-number">1</span>);
  };

  <span class="hljs-comment">// Memoize the incrementCount function using useCallback</span>
  <span class="hljs-keyword">const</span> memoizedIncrement = useCallback(incrementCount, [count]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> <span class="hljs-attr">onIncrement</span>=<span class="hljs-string">{memoizedIncrement}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">const</span> ChildComponent = React.memo(<span class="hljs-function">(<span class="hljs-params">{ onIncrement }</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Child component rendered'</span>);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onIncrement}</span>&gt;</span>Increment Count<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> ParentComponent;
</code></pre>
<p>In the code above, the <code>ParentComponent</code> is responsible for managing a state variable named <code>count</code> and introduces a function called <code>incrementCount</code>, which handles the incrementation of the count. Utilizing the <code>useCallback</code> hook, the <code>incrementCount</code> function is memoized, guaranteeing its stability across renders unless any of its dependencies, in this case, <code>count</code>, undergo changes.</p>
<p>On the other hand, the <code>ChildComponent</code> is a component nested within the parent. It receives the memoized <code>onIncrement</code> function from the parent as a prop. </p>
<p>To optimize performance and prevent unnecessary re-renders when the props remain constant, the <code>ChildComponent</code> is wrapped with <code>React.memo()</code>. This ensures that the child component will only re-render when its props, specifically the memoized function, experience changes, contributing to a more efficient rendering process.</p>
<p>It's important to note that <code>useCallback</code> should be used sparingly and only for performance-critical parts of your application. Overusing <code>useCallback</code> can actually lead to worse performance due to the overhead of memoization itself. Always measure the performance impact before and after using <code>useCallback</code> to ensure it's having the desired effect.</p>
<h3 id="heading-throttling-and-debouncing-events">Throttling and Debouncing Events</h3>
<p>Throttling in React is a technique used to limit the number of times a function or an event handler is invoked. It ensures that the function is called at a specified interval, preventing it from being executed too frequently. </p>
<p>Throttling allows you to control the rate at which the function is called by setting up a minimum time interval between each function invocation. If the function is called multiple times within that interval, only the first invocation is executed, and subsequent invocations are ignored until the interval elapses</p>
<p>Now, let's illustrate throttling with a code example. First, without throttling:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Without throttling, this function will be called every time the event is triggered</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleResize</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Window resized'</span>);
}

<span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">'resize'</span>, handleResize);
</code></pre>
<p>With throttling, we can limit how often the <code>handleResize</code> function is called:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Throttling function</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">throttle</span>(<span class="hljs-params">func, delay</span>) </span>{
  <span class="hljs-keyword">let</span> lastCall =  <span class="hljs-number">0</span>;
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">...args</span>) </span>{
    <span class="hljs-keyword">const</span> now = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime();
    <span class="hljs-keyword">if</span> (now - lastCall &lt; delay) {
      <span class="hljs-keyword">return</span>;
    }
    lastCall = now;
    func(...args);
  };
}

<span class="hljs-comment">// Throttled event handler</span>
<span class="hljs-keyword">const</span> throttledHandleResize = throttle(handleResize,  <span class="hljs-number">200</span>);

<span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">'resize'</span>, throttledHandleResize)
</code></pre>
<p>In this example, the <code>throttle</code> function wraps <code>handleResize</code> and ensures it's not called more often than every 200 milliseconds. If the <code>resize</code> event fires more frequently than that, the <code>handleResize</code> function will only be executed once every 200 milliseconds, reducing the potential for performance issues caused by rapid, repeated function calls</p>
<p>Debouncing, on the other hand, is also used to limit the number of times a function or an event handler is invoked. It ensures that the function is called only after a certain period of inactivity. Debouncing allows you to postpone the function call until the user has finished typing or a specific time has elapsed since the last event.</p>
<p>For example, imagine you have a search input field and want to trigger a search API request only when the user has finished typing for a certain duration, like <code>300ms</code>. </p>
<p>With debouncing, the search function will only be invoked after the user stops typing for <code>300ms</code>. If the user continues typing within that interval, the function call will be delayed until the pause occurs. Without debouncing, the function will be called for every keystroke, potentially leading to excessive function calls and unnecessary computation. let's demonstrate with a code example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> SearchComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [searchTerm, setSearchTerm] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-comment">// Function to simulate a search API request</span>
  <span class="hljs-keyword">const</span> searchAPI = <span class="hljs-function">(<span class="hljs-params">query</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Searching for: <span class="hljs-subst">${query}</span>`</span>);
    <span class="hljs-comment">// In a real application, you would make an API request here</span>
  };

  <span class="hljs-comment">// Debounce function to delay the searchAPI call</span>
  <span class="hljs-keyword">const</span> debounce = <span class="hljs-function">(<span class="hljs-params">func, delay</span>) =&gt;</span> {
    <span class="hljs-keyword">let</span> timeoutId;
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">...args</span>) </span>{
      <span class="hljs-built_in">clearTimeout</span>(timeoutId);
      timeoutId = <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
        func(...args);
      }, delay);
    };
  };

  <span class="hljs-comment">// Debounced search function</span>
  <span class="hljs-keyword">const</span> debouncedSearch = debounce(searchAPI, <span class="hljs-number">300</span>);

  <span class="hljs-comment">// useEffect to watch for changes in searchTerm and trigger debouncedSearch</span>
  useEffect(<span class="hljs-function">() =&gt;</span> {
    debouncedSearch(searchTerm);
  }, [searchTerm, debouncedSearch]);

  <span class="hljs-comment">// Event handler for the search input</span>
  <span class="hljs-keyword">const</span> handleSearchChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    setSearchTerm(event.target.value);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"search"</span>&gt;</span>Search:<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">"search"</span>
        <span class="hljs-attr">value</span>=<span class="hljs-string">{searchTerm}</span>
        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleSearchChange}</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Type to search..."</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> SearchComponent;
</code></pre>
<p>With this setup, the <code>searchAPI</code> function will only be invoked after the user stops typing for 300ms, preventing excessive API requests and improving the overall performance of the search functionality.</p>
<h3 id="heading-code-splitting">Code Splitting</h3>
<p>Code splitting in React is a technique used to split a large JavaScript bundle into smaller, manageable chunks. It helps improve performance by loading only the necessary code for a specific part of an application rather than loading the entire bundle upfront. </p>
<p>When you develop a new React application, all your JavaScript code is typically bundled together into a single file. This file contains all the components, libraries, and other code required for your application to function. But as your application grows, the bundle size can become quite large, resulting in slow initial load times for your users.</p>
<p>Code splitting allows you to divide a single bundle into multiple chunks, which can be loaded selectively based on the current needs of your application. Instead of downloading the entire bundle upfront, only the necessary code is fetched and executed when a user visits a particular page or triggers a specific action.</p>
<p>Below is a basic example of code splitting:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// AsyncComponent.js</span>
<span class="hljs-keyword">import</span> React, { lazy, Suspense } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

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

<span class="hljs-keyword">const</span> AsyncComponent = <span class="hljs-function">() =&gt;</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">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">DynamicComponent</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span></span>
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AsyncComponent;


<span class="hljs-comment">// DynamicComponent.js</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> DynamicComponent = <span class="hljs-function">() =&gt;</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This is a dynamically loaded component!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> DynamicComponent;
</code></pre>
<p>In this example, <code>AsyncComponent</code> is a component that uses <code>lazy</code> and <code>Suspense</code> to perform code splitting. The <code>DynamicComponent</code> is dynamically imported using the import() syntax. </p>
<p>When <code>AsyncComponent</code> is rendered, React will load <code>DynamicComponent</code> only when it is needed, reducing the initial bundle size and improving the application's performance. The fallback prop in Suspense specifies what to render while waiting for the dynamic import to resolve, providing a better user experience during the loading process.</p>
<h3 id="heading-react-fragments">React Fragments</h3>
<p>React Fragments are a feature introduced in <a target="_blank" href="https://legacy.reactjs.org/blog/2017/11/28/react-v16.2.0-fragment-support.html">React 16.2</a> that allows you to group multiple elements together without adding an additional DOM node. This is particularly useful when you need to return multiple elements from a component's render method, but you don't want to introduce unnecessary DOM elements that could affect the layout or styles of your application.</p>
<p>Imagine you are arranging books on a bookshelf. Each book represents a React component, and the bookshelf represents the DOM. </p>
<p>Normally, if you have multiple books, you might want to group them together under a category label (analogous to a DOM element like a <code>&lt;div&gt;</code>). But sometimes you just want to place the books side by side without a label because the label itself doesn't hold any value and only takes up physical space. </p>
<p>React Fragments are like the option to arrange the books without a label, saving space and making the arrangement cleaner.</p>
<p>Here's an example of how to utilize React fragments:</p>
<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-function"><span class="hljs-keyword">function</span> <span class="hljs-title">BookShelf</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Book</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"React for Beginners"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Book</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"Mastering Redux"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Book</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"JavaScript Essentials"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Book</span>(<span class="hljs-params">{ title }</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> BookShelf;
</code></pre>
<p>In this example, the <code>BookShelf</code> component returns a list of <code>Book</code> components without wrapping them in a <code>&lt;div&gt;</code> or other unnecessary DOM element. Instead, it uses the <code>&lt;&gt;</code> shorthand syntax for React Fragments. </p>
<p>This results in a cleaner DOM structure, which can improve the performance of your React application by reducing the number of elements that the browser has to process and render. Using fragments can also reduce unnecessary markup and contribute to a cleaner and more efficient render tree.</p>
<h3 id="heading-web-workers">Web Workers</h3>
<p>JavaScript operates as a single-threaded application designed to handle synchronous tasks. </p>
<p>When a web page is being rendered, JavaScript executes multiple tasks, including manipulating DOM elements, managing UI interactions, handling API response data, and enabling CSS animations, all within a single thread. Despite its efficiency in managing these tasks, executing them in a single thread can sometimes lead to performance bottlenecks.</p>
<p>Web Workers serve as a solution to alleviate the burden on the main thread. They allow the execution of scripts in the background on a separate thread, distinct from the main JavaScript thread. </p>
<p>This separation enables the handling of computationally intensive tasks, execution of long-running operations, or management of tasks that might otherwise block the main thread. By doing so, Web Workers contribute to maintaining user interface responsiveness and overall application performance.</p>
<p>To use web worker in React, create a new JavaScript file that will contain the code for the worker thread:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// worker.js</span>
self.onmessage = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>) </span>{
  <span class="hljs-keyword">var</span> input = event.data;
  <span class="hljs-keyword">var</span> result = performHeavyComputation(input);
  postMessage(result);
};

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">performHeavyComputation</span>(<span class="hljs-params">input</span>) </span>{
  <span class="hljs-comment">// Insert your heavy computation logic here</span>
  <span class="hljs-keyword">return</span> input *   <span class="hljs-number">2</span>; <span class="hljs-comment">// Just a placeholder operation</span>
}
</code></pre>
<p>In your React component, instantiate the Web Worker and establish a communication channel with it:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useEffect, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> workerRef = useRef();

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Initialize the worker</span>
    workerRef.current = <span class="hljs-keyword">new</span> Worker(<span class="hljs-string">'path-to-your-worker-file.js'</span>);

    <span class="hljs-comment">// Handle incoming messages from the worker</span>
    workerRef.current.onmessage = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Message received from worker:'</span>, event.data);
    };

    <span class="hljs-comment">// Cleanup the worker when the component unmounts</span>
    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      workerRef.current.terminate();
    };
  }, []);

  <span class="hljs-comment">// Function to send a message to the worker</span>
  <span class="hljs-keyword">const</span> sendMessageToWorker = <span class="hljs-function">(<span class="hljs-params">message</span>) =&gt;</span> {
    workerRef.current.postMessage(message);
  };

  <span class="hljs-comment">// Rest of your component</span>
  <span class="hljs-keyword">return</span> (
    <span class="hljs-comment">// ...</span>
  );
}
</code></pre>
<p>In this example, a Web Worker is initialized in the <code>useEffect</code> hook and stored in a ref for future use. Messages from the worker are handled with an <code>onmessage</code> event listener, and the worker is terminated when the component is unmounted to clean up resources. The <code>sendMessageToWorker</code> function demonstrates how to communicate with the worker using <code>postMessage</code></p>
<h3 id="heading-usetransition-hook">UseTransition Hook</h3>
<p>The <code>useTransition</code> hook in React plays a pivotal role in improving the performance of applications by allowing the marking of state updates as non-blocking transitions. This capability enables React to defer rendering for these updates, preventing UI blocking and enhancing overall responsiveness. </p>
<p>When utilizing <code>useTransition,</code> state updates within the <code>startTransition</code> function are treated as low-priority transitions, susceptible to interruption by higher-priority state updates. So if a high-priority update occurs during a transition, React may prioritize finishing the high-priority update, interrupting the ongoing transition.</p>
<p>This non-blocking transition mechanism is valuable in preventing UI blocking during intensive operations such as data fetching or large-scale updates. By deferring the rendering of components associated with transition updates, React ensures that the user interface remains responsive even in scenarios where the UI might otherwise become unresponsive.</p>
<p>This example demonstrates the use of <code>useTransition</code> in a React component:</p>
<pre><code class="lang-javascript=">import React, { useState, useTransition } from 'react';

function MyComponent() {
  const [state, setState] = useState(initialState);
  const [isPending, startTransition] = useTransition();

  function handleClick() {
    startTransition(() =&gt; {
      setState(newState); // This state update is marked as a transition
    });
  }

  return (
    &lt;&gt;
      {/* Your component JSX */}
      &lt;button onClick={handleClick}&gt;Update State&lt;/button&gt;
      {isPending &amp;&amp; &lt;div&gt;Loading...&lt;/div&gt;}
    &lt;/&gt;
  );
}
</code></pre>
<p>This example showcases how React avoids blocking the UI during transitions triggered by user actions, allowing for interruption if higher-priority state updates are detected. </p>
<p>Note that <code>useTransition</code> is part of the Concurrent Mode API, introduced in React 18 and later versions. As a powerful tool for altering the default behavior of state updates, make sure you use it with care, considering the specific implications of deferring rendering within the context of your application.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Optimizing the performance of a React application involves a combination of strategies, from the fundamental understanding of React's diffing algorithm to leveraging built-in features and third-party tools. </p>
<p>By applying these techniques judiciously, you can create applications that are not only visually appealing but also performant, leading to a better overall user experience.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ LinkedIn Profile Optimization – A Web Developer's Guide to Attract Opportunity ]]>
                </title>
                <description>
                    <![CDATA[ As a web developer, an optimized LinkedIn profile can bring numerous opportunities directly to you. After implementing invaluable optimization advice from industry experts who reviewed my profile, I now receive a steady flow of enticing prospects in ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/linkedin-profile-optimization/</link>
                <guid isPermaLink="false">66bc4c0b099736fc91bcbef9</guid>
                
                    <category>
                        <![CDATA[ career advice ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Job Hunting ]]>
                    </category>
                
                    <category>
                        <![CDATA[ LinkedIn ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ recruitment ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Michael Larocca ]]>
                </dc:creator>
                <pubDate>Tue, 03 Oct 2023 08:32:42 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/FFC-01-NEW.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As a web developer, an optimized LinkedIn profile can bring numerous opportunities directly to you. After implementing invaluable optimization advice from industry experts who reviewed my profile, I now receive a steady flow of enticing prospects in my inbox.</p>
<p>In this article, I'll share the insights I've gained to help you optimize your profile so that you can achieve similar success.</p>
<p>Hello, my name is Michael. Like many others, I am a self-taught web developer on a journey to transition from my current career into the tech industry. </p>
<p>Although I haven't finished learning front-end web development, I am already earning side income by writing articles and providing code reviews. How did I accomplish this? One of the ways is through an optimized LinkedIn profile, which helps bring monetary opportunities directly to me.</p>
<p>In this article, I will share with you what I learned from having my LinkedIn profile reviewed by employees from LinkedIn and Microsoft, recruiters, and a tech celebrity during livestream events. 📺</p>
<h2 id="heading-why-should-you-optimize-your-linkedin-profile">Why should you optimize your LinkedIn profile?</h2>
<p>Having a LinkedIn profile in today's industry is arguably just as important as having a resume/CV. </p>
<p>By optimizing your LinkedIn profile, you will not only stand out from the crowd of other web developers but also help attract recruiters, hiring managers, and additional opportunities directly to you. 💸</p>
<h2 id="heading-how-you-should-treat-linkedin">How you should treat LinkedIn</h2>
<p>Unlike other platforms, LinkedIn is a professional work-related platform, and it should be treated as such. Refrain from posting personal social content, your opinions on controversial subjects, and anything else that may hinder your reputation. </p>
<p>You have a right to voice your opinions, but you should consider posting them on other social media platforms. It is not in your best interest for potential hiring managers to dismiss you from employment opportunities simply by judging you based on your posted content. 😬</p>
<h2 id="heading-linkedin-profile-sections">LinkedIn Profile Sections</h2>
<p>To optimize your LinkedIn profile, I will guide you through each of the following LinkedIn profile sections:</p>
<ul>
<li><a class="post-section-overview" href="#heading-how-to-optimize-your-linkedin-profile-picture-and-banner">How to Optimize your LinkedIn Profile Picture and Banner</a></li>
<li><a class="post-section-overview" href="#heading-open-to-work-banner">Open to Work Banner</a></li>
<li><a class="post-section-overview" href="#heading-headline-section">Headline Section</a></li>
<li><a class="post-section-overview" href="#heading-location-setting">Location Setting</a></li>
<li><a class="post-section-overview" href="#heading-featured-section">Featured Section</a></li>
<li><a class="post-section-overview" href="#heading-activity-section">Activity Section</a></li>
<li><a class="post-section-overview" href="#heading-summary-about-section">Summary (About) Section</a></li>
<li><a class="post-section-overview" href="#heading-experience-section">Experience Section</a></li>
<li><a class="post-section-overview" href="#heading-education-section">Education Section</a></li>
<li><a class="post-section-overview" href="#heading-licenses-and-certifications-section">Licenses and Certifications Section</a></li>
<li><a class="post-section-overview" href="#heading-projects-section">Projects Section</a></li>
<li><a class="post-section-overview" href="#heading-skills-and-endorsements-section">Skills and Endorsements Section</a></li>
<li><a class="post-section-overview" href="#heading-recommendations-section">Recommendations Section</a></li>
<li><a class="post-section-overview" href="#heading-honors-amp-awards-accomplishments-section">Honors &amp; Rewards (Accomplishments) Section</a></li>
<li><a class="post-section-overview" href="#heading-creator-mode">Creator Mode</a></li>
</ul>
<p><strong>Additional tips:</strong></p>
<ol>
<li><a class="post-section-overview" href="#heading-1-post-external-links-in-the-comments">Post external links in the comments</a></li>
<li><a class="post-section-overview" href="#heading-2-change-the-default-profile-url-to-your-name">Change the default profile URL to your name</a></li>
<li><a class="post-section-overview" href="#heading-3-separate-profile-for-separate-languages">Separate Profile for separate languages</a></li>
<li><a class="post-section-overview" href="#heading-4-linkedin-learning">LinkedIn Learning</a></li>
<li><a class="post-section-overview" href="#heading-5-linkedin-skill-assessments">LinkedIn Skill Assessments</a></li>
</ol>
<p>💡 <strong>Tip:</strong> Did you know many recruiters are not programmers? Keep this in mind to better optimize your LinkedIn profile.</p>
<h2 id="heading-how-to-optimize-your-linkedin-profile-picture-and-banner">How to Optimize your LinkedIn Profile Picture and Banner</h2>
<p>In this section, you'll learn how to optimize your profile picture and banner on LinkedIn to make your profile look more professional. </p>
<h3 id="heading-how-to-optimize-your-profile-picture">How to Optimize your Profile Picture</h3>
<p>Your profile picture is easy, so we'll start with that. Since the absence of a picture or an avatar in its place may be perceived as a red flag to hiring managers, use a real picture of yourself (don't be shy). 😏</p>
<p>Use a close-up picture of yourself in professional clothing, as you would in an interview, from the shoulder area up, and a professional-looking or blank background.</p>
<h3 id="heading-how-to-optimize-your-banner-image">How to Optimize your Banner Image</h3>
<p>For your banner, your goal is to convey a clear picture of your desired job role.</p>
<p>When creating a custom banner, here are things to consider:</p>
<ul>
<li>The banner image should reflect your desired job role, not contradict it.</li>
<li>Other people viewing your profile may not be programmers.</li>
<li>Everyone will not recognize tech icons without the corresponding names.</li>
<li>Add contact information as an alternative method to be reached.</li>
<li>Incorporate a hobby to spark conversation.</li>
</ul>
<h4 id="heading-banner-image">Banner Image</h4>
<p>An unintentional mistake I made was to use on my blog's logo as a banner, which included the word "self-taught" in big letters. Danny Thompson brought to my attention during a livestream review that it wasn't in my best interest to broadcast that I am a self-taught developer, as it can be seen as a red flag to hiring managers. </p>
<p>Other banner image mistakes include unrelated tech images such as nature scenery or having no banner at all. Remember, you want your banner to reflect your desired job role.</p>
<p>Another thing to remember is that other people viewing your profile may not be programmers, so including icons alone without corresponding names, such as HTML, CSS, JavaScript, and React logos, may not be recognized by everyone.</p>
<h4 id="heading-adding-contact-information">Adding contact information</h4>
<p>Another thing I learned while having my profile reviewed is that recruiters have a limited number of monthly LinkedIn InMail credits available to reach out to potential candidates. So, adding your contact information to your banner, such as your website, email, and phone number, creates an alternative means of reaching you without having to utilize their InMail credits.</p>
<h4 id="heading-conversation-starter">Conversation starter</h4>
<p>This will not be for everyone, but it is definitely worth mentioning. Recruiter Taylor Desseyn told us of a developer who incorporated his time as a sound engineer for the Backstreet Boys in his LinkedIn banner. This caught the attention of a recruiter who contacted the developer due to their music industry experience, ultimately securing them a tech job. So, if you have a personal, non-tech-related experience or hobby that could potentially spark a conversation, consider including it.</p>
<p>💡 <strong>Tip:</strong> Recruiters have a limited number of InMail credits, which they use to reach out to potential candidates. Providing your contact information in your LinkedIn banner provides an alternative method for others to get in touch with you.</p>
<h3 id="heading-open-to-work-banner">Open to Work Banner</h3>
<p>If you are feeling brave, you can display an "OPEN TO WORK" banner that proudly displays your availability to everyone. </p>
<p>However, since this is a delicate topic, and everyone's situation varies, there is an option that allows you to maintain the privacy of your open-to-work status. There will not be a displayed banner, but recruiters will know you are available to work. 🤫</p>
<p>To set the "Open to Work" banner on LinkedIn, follow these steps:</p>
<ol>
<li>Log in to your LinkedIn account and navigate to "Edit job preferences."</li>
<li>Fill in the fields, such as job titles, location types, start date, and employment types.</li>
<li>Now, for visibility, choose whether to share your open-to-work status with all LinkedIn members or only with recruiters. Selecting the first option will display the "Open to Work" banner on your profile picture, while the second option keeps it private.</li>
<li>Click "Save" to apply the changes.</li>
</ol>
<p><strong>Note:</strong> Please proceed with caution when selecting your open-to-work status, regardless of whether you choose to display the banner or not, as LinkedIn has a disclaimer stating they cannot guarantee complete privacy. Use this feature at your own risk.</p>
<h3 id="heading-headline-section">Headline Section</h3>
<p>In your headline section, briefly describe yourself by adding keywords that match the job role you seek and your skill sets. In my case, I entered "Technical Writer | Front-End Web Developer | React | JavaScript | CSS | HTML | Scrimba Code Reviewer." </p>
<p>Of course, you can get more descriptive and tell a little about yourself, but the main goal is to provide specific keywords.</p>
<p>The reason for including keywords related to your skills and desired job role in your headline ensures that you appear in relevant search results of recruiters and employers.</p>
<h3 id="heading-location-setting">Location Setting</h3>
<p>For my LinkedIn location setting, I initially set it to Brooklyn, New York, which is where I am based. When LinkedIn employee Austin Henline reviewed my profile, he explained that setting my profile to Brooklyn limits the searches I appeared to just Brooklyn.</p>
<p>By modifying my LinkedIn location from Brooklyn to the New York City Metropolitan Area, which includes Brooklyn, I substantially expanded the range of job searches in which I appear.</p>
<p>To optimize your LinkedIn location setting most effectively, select the broadest range that encompasses the specific location where you live or desire to work.</p>
<h4 id="heading-how-to-change-the-location-setting-on-linkedin">How to change the location setting on LinkedIn:</h4>
<ol>
<li>Click on your profile picture or the "Me" icon at the top of the LinkedIn homepage.</li>
<li>Click "View Profile" to access your profile page.</li>
<li>In the "Intro" section, click the pencil icon to edit your information.</li>
<li>In the "Location" field, enter the desired location or select from the suggested options.</li>
<li>Click "Save" to apply the changes.</li>
</ol>
<p>💡 <strong>Tip:</strong> Optimize your LinkedIn location setting by choosing an area that covers a broad radius, ensuring your profile appears in more job searches.</p>
<h3 id="heading-featured-section">Featured Section</h3>
<p>The <strong>Featured</strong> section is the place to proudly display your achievements, awards, best original projects (not direct copies of tutorial projects), and similar content to showcase yourself in the spotlight. This section is arranged horizontally, scrolls like a carousel, and enables you to rearrange and pin your most recent content to the beginning/top.</p>
<p>Examples of content to feature include:</p>
<ul>
<li>Testimonials received</li>
<li>Awards or recognitions received</li>
<li>Published articles or blog posts</li>
<li>Appearances (such as Livestream events)</li>
<li>Presentations or conference talks</li>
</ul>
<p>Keep in mind that others viewing your work might not be developers, so be sure to provide clear descriptions and context for each featured item, including the technologies used if applicable (such as React, Tailwind, JavaScript, and so on).</p>
<p>You can optimize your Featured section by including all relevant materials that demonstrate your skills and experience. Additionally, include content that you believe will effectively grab the attention of recruiters and hiring managers.</p>
<p>I display all of my colorful article thumbnails with external links to each, in the Featured section, transforming it into a visually appealing scrolling magazine rack. 📰</p>
<p>💡 <strong>Tip:</strong> Showcase your best content in the Featured section to capture the attention of recruiters and hiring managers, and remember to update it frequently.</p>
<h3 id="heading-activity-section">Activity Section</h3>
<p>It's vital for you to keep your LinkedIn profile active because a profile without activity will display a "hasn't posted lately" message in the <strong>Activity</strong> section. Recruiters and hiring managers are hesitant to reach out to profiles without activity because they are uncertain whether their attempts to make contact will be successful.</p>
<p>You can keep your profile active by:</p>
<ul>
<li><strong>Creating posts:</strong> Share updates, articles, or insights to showcase your expertise and engage with your network.</li>
<li><strong>Leaving comments on posts:</strong> Interact with others by providing valuable feedback, asking questions, or sharing your thoughts on their content.</li>
<li><strong>Sharing posts:</strong> Amplify the reach of interesting content with your network, helping spread valuable insights and knowledge.</li>
<li><strong>Attending LinkedIn Livestream events</strong>: Participate in live video events hosted by industry experts, companies, or influencers to learn, network, and engage with others (Taylor Desseyn has great ones).</li>
<li><strong>Publishing articles:</strong> Write long-form content on LinkedIn to demonstrate your knowledge, share your experience, and establish yourself as a thought leader in your field.</li>
</ul>
<p>Having an active profile will increase your visibility to recruiters and hiring managers, and since they know you frequently use the platform, they will not be hesitant to reach out to make contact with you.</p>
<p>💡 <strong>Tip:</strong> Keep your profile active to avoid the "hasn't posted lately" message in the Activity section, which may discourage recruiters and hiring managers from attempting to contact you.</p>
<h3 id="heading-summary-about-section">Summary (About) Section</h3>
<p>Everyone seems to have various opinions about what to put in your <strong>About</strong> section. From what I gathered through my profile reviews and research of LinkedIn documentation, the overall idea is to craft it like an elevator pitch.</p>
<p>So, what is an elevator pitch? An elevator pitch is a short speech briefly describing your background, skills, goals, and unique value, typically around 30 seconds to 1 minute (the length of time spent in an elevator with someone).</p>
<p>If you alternatively prefer a more detailed approach to crafting your About section, I recommend following the guidance of LinkedIn employee, Austin Henline. He advises providing five paragraphs that contain the following:</p>
<ol>
<li><strong>A hook:</strong> A captivating opening statement that grabs the reader's attention.</li>
<li><strong>Your past:</strong> A brief overview of your previous experiences and accomplishments.</li>
<li><strong>Your present:</strong> A description of your current role, responsibilities, and ongoing projects.</li>
<li><strong>Your future:</strong> A statement outlining your career goals and aspirations.</li>
<li><strong>Your skills:</strong> A list of your relevant technical and soft skills showcasing your expertise.</li>
</ol>
<p>To further optimize your <strong>About</strong> section and make it more visible in search results of potential employers, be sure to incorporate plenty of relevant keywords, as this section is also keyword-searchable. You can incorporate web developer keywords such as HTML, CSS, JavaScript, React, responsive design, UX/UI design, accessibility, performance optimization, etc.</p>
<h4 id="heading-the-mistakes-i-made">The Mistakes I made</h4>
<p>To further improve your LinkedIn About section, consider the constructive feedback I received from recruiter Molly-May Gallagher. Enhance your LinkedIn summary by clearly stating desired work, highlighting key technical skills, focusing on relevant experiences, detailing current role technologies, and removing unrelated information for a concise, impactful summary.</p>
<p>Also, be sure to clarify your desired job roles to avoid confusion. Alishah Novin from Microsoft pointed out that listing multiple roles, like technical writing and front-end development, as I did, can make your true passion unclear, leading to potential missed opportunities.</p>
<p>💡 <strong>Tip:</strong> Include keywords relevant to your industry and desired job role in your About section to increase search results visibility.</p>
<h3 id="heading-experience-section">Experience Section</h3>
<p>To best optimize the Experience section of your LinkedIn profile, list your experiences relevant to the job roles you are currently seeking (not all of your unrelated tech roles). For each experience listed, be sure to include details for each, including company name, duration, and a brief description of your responsibilities and achievements.</p>
<p>For example, I will share a tech-related experience I included. Since I work part-time remotely as a paid code reviewer for Scrimba, in addition to a detailed description of the job role, I added the following keyword searchable skills: React, JavaScript, CSS, HTML, and Teaching. I also linked to a playlist of my recorded code reviews so that others can see a demonstration of my skills.</p>
<p>💡 <strong>Tip:</strong> If you are currently in college or recently graduated and lack work experience, you can highlight your volunteer experience, club experiences, and projects in your profiles Experience section.</p>
<h3 id="heading-education-section">Education Section</h3>
<p>In the <strong>Education</strong> section, list the degrees and diplomas you have earned, along with the schools, colleges, or universities you have attended. You also have the opportunity to include any additional relevant information, such as participation in activities, societies, or honors you have received.</p>
<p>To best optimize the Education section, emphasize relevant coursework, highlight achievements, and explain the impact of education on your career trajectory as it relates to computer programming.</p>
<p>💡 <strong>Tip:</strong> If you have a time gap between jobs due to a career transition or break, you can create a positive spin on it by adding supplemental work experience such as completing Bootcamps, earning certificates, studying, and freelancing.</p>
<h3 id="heading-licenses-and-certifications-section">Licenses and Certifications Section</h3>
<p>This section lets you showcase your professional certifications, licenses, and achievements. As a web developer, I'm sure you have completed many online courses that issued certificates from schools such as freeCodeCamp, Scrimba, Sololearn, and similar. You can add each of your earned certificates in this section and link to them (I have my linked certificates stored on GitHub).</p>
<p>To add a certification, go to your LinkedIn profile, click "Add profile section," select "Licenses &amp; certifications," and enter the required details such as certification name, issuing organization, issue date, expiration date, and associated credential ID.</p>
<h3 id="heading-projects-section">Projects Section</h3>
<p>As a developer, you are definitely going to want to utilize this elusive yet extremely valuable LinkedIn feature, the <strong>Projects</strong> section. I wasn't even aware this section existed until LinkedIn employee Austin Henline revealed it during a YouTube Livestream.</p>
<p>The Projects section allows you to showcase your work, giving you an opportunity to demonstrate your skills and expertise. For each project, be sure to include a brief description and the technologies used _(<em>remember, not all recruiters and hiring managers are programmers</em>)_. You can also provide a link to the deployed project or repository, which allows others to view it.</p>
<p>I decided to showcase my deployed Tetris project. I followed freeCodeCamp's game tutorial, taught by Ania Kubow, and took it to the next level by adding styling, sounds and music, a scoring system, and more. </p>
<p>When users click on the link to the deployed project directly within the LinkedIn app, they are instantly mesmerized as they suddenly take control of the falling tetrominoes trying to clear completed solid rows. My hope is that they become momentarily lost in the game, and when it ends, they click back to my profile and think, "We have to hire this guy!"</p>
<p>To access the LinkedIn Projects section and add projects:</p>
<ol>
<li>Click on "Add profile section".</li>
<li>Click on "Recommended".</li>
<li>Choose "Add projects".</li>
<li>Fill in the project details, such as the project name, description, and date.</li>
<li>You can add your top 5 skills used in this project.</li>
<li>You can add media such as images, documents, sites, or presentations</li>
<li>Click "Save" to add the project to your profile.</li>
</ol>
<p>💡 <strong>Tip:</strong> To best optimize your LinkedIn profile, include unique projects in your Projects section that will captivate and draw the interest of recruiters and hiring managers.</p>
<h3 id="heading-skills-and-endorsements-section">Skills and Endorsements Section</h3>
<p>The <strong>Skills</strong> section enables you to showcase your abilities, such as HTML, CSS, and JavaScript and allows others to endorse each skill mentioned.</p>
<p>Be sure to add skills that are most relevant to the job roles you are seeking, and prioritize obtaining endorsements for them. The more endorsements you accumulate, the more credible you and your profile appear to potential employers.</p>
<h3 id="heading-recommendations-section">Recommendations Section</h3>
<p>Be sure to utilize the <strong>Recommendations</strong> section of your profile by asking others you have worked with to provide them. Just like receiving endorsements for your skills, having recommendations will also help increase your credibility and will make your profile more appealing to recruiters and hiring managers.</p>
<p>You can also write and provide recommendations for fellow LinkedIn members in your network.</p>
<h3 id="heading-honors-amp-awards-accomplishments-section">Honors &amp; Awards (Accomplishments) Section</h3>
<p>In your LinkedIn profile's <strong>Honors &amp; awards</strong> section, you can showcase your achievements, awards, and recognitions. Be sure to add ( and earn ) relevant honors and awards, as this section demonstrates additional credibility to potential employers, further optimizing your LinkedIn profile.</p>
<p>Honors &amp; awards may include:</p>
<ul>
<li>Coding competition awards</li>
<li>Scholarships and grants</li>
<li>Community leadership roles</li>
<li>Technical writing achievements</li>
<li>Speaking achievements</li>
<li>Mentorship roles</li>
</ul>
<h3 id="heading-creator-mode">Creator Mode</h3>
<p>If you are a content creator, turning on LinkedIn <strong>Creator mode</strong> provides additional tools such as a "Follow" button, analytics, profile topics, and a set of creator tools that you can use to optimize your LinkedIn profile further.</p>
<h4 id="heading-follow-button">Follow button</h4>
<p>The Follow button provides LinkedIn members with an alternative option to connect with you. Once you surpass five hundred connections, a "500+ connections" displays, whereas there is no limit to the number of displayed followers.</p>
<h4 id="heading-analytics">Analytics</h4>
<p>Analytics includes your post impressions, profile views, followers, and your search appearances. You will gain insights into your content's performance by selecting date ranges from a week to a year and choosing from a list of demographics. This information will help you clearly understand who is engaging with your content, allowing you to make informed decisions about your content strategy.</p>
<h4 id="heading-profile-topics">Profile topics</h4>
<p>Creator mode allows you to showcase five "Profile Topics" that highlight your expertise, making it simpler for audiences to understand your focus, enhancing credibility, and attracting a targeted audience.</p>
<p>Creator tools include:</p>
<ul>
<li><strong>Collaborative articles:</strong> Jointly written articles by multiple authors on LinkedIn.</li>
<li><strong>LinkedIn Live:</strong> Real-time video streaming feature on LinkedIn for engaging audiences.</li>
<li><strong>Audio Event:</strong> Virtual audio-based discussions or presentations on LinkedIn.</li>
<li><strong>Newsletters:</strong> Periodic publications sent to subscribers, sharing updates and insights.</li>
<li><strong>Follow link:</strong> Button on LinkedIn profiles for users to follow and receive content updates.</li>
</ul>
<p>The collaborative article is a new feature where the LinkedIn team creates an AI article, and invites select members to participate by adding their valuable insights. </p>
<p>As an active LinkedIn member, I was recognized and invited to participate. As I continue to add value to these collaborative articles, I currently have a "Top Writing Voice" badge displayed. However, I hold this badge for a minimum of 60 days, and if LinkedIn members stop finding my insights valuable, they will take the badge away. (No pressure, right? 😅)</p>
<p>At this time, collaborative articles are by invitation only, but they mentioned LinkedIn members who engage with them by liking or reacting to them will be considered.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/linkedIn.png" alt="Image" width="600" height="400" loading="lazy">
<em>Attribution: LinkedIn logo by LinkedIn Corporation, used under fair use for informational purposes.</em></p>
<h3 id="heading-additional-tips">Additional tips</h3>
<p>In this section, I included a few additional LinkedIn tips I have learned that are worth sharing with you.</p>
<p>They include:</p>
<h4 id="heading-1-post-external-links-in-the-comments">1. Post external links in the comments</h4>
<p>When sharing content that is located on other platforms using links, do not put the link directly in your LinkedIn post. Instead, add external links in the comments of your LinkedIn post. This tip came from a LinkedIn employee who explained that doing this significantly improves your post's reach/performance on the platform.</p>
<h4 id="heading-2-change-the-default-profile-url-to-your-name">2. Change the default profile URL to your name</h4>
<p>For a more professional URL, you have the option to change the default one created to your name. My original URL was "<a target="_blank" href="https://www.linkedin.com/in/michael-larocca-9315a3202/">https://www.linkedin.com/in/michael-larocca-9315a3202/</a>". I have since changed it to "<a target="_blank" href="https://www.linkedin.com/in/michaeljudelarocca">https://www.linkedin.com/in/michaeljudelarocca</a>"</p>
<p>Here are the steps to changing your profile URL:</p>
<ul>
<li>Click on your profile picture or the "Me" icon at the top of the LinkedIn homepage.</li>
<li>Click "View Profile" to access your profile page.</li>
<li>In the "Intro" section, click the pencil icon to edit your information.</li>
<li>Scroll down to "Edit public profile &amp; URL" on the top right and click it.</li>
<li>On the new page, under "Edit your custom URL," click the pencil icon next to your current URL.</li>
<li>Enter your desired custom URL and click "Save" to apply the changes.</li>
</ul>
<h4 id="heading-3-separate-profile-for-separate-languages">3. Separate Profile for separate languages</h4>
<p>If you speak more than one language, you may be filling out your profile multilingually. Doing so will quickly deplete your allotted character limit for each section and may cause confusion for others viewing your profile. </p>
<p>As an alternative, you can create separate profiles for each language. Maintaining a profile for each language provides the advantage of personalizing them to attract diverse job opportunities in their respective languages.</p>
<p>Here are steps to add a profile in another language (desktop/laptop version only):</p>
<ul>
<li>On the top right, click on "ME."</li>
<li>Then click on "View Profile."</li>
<li>Finally, on the right, click on "Add profile in another language."</li>
</ul>
<h4 id="heading-4-linkedin-learning">4. LinkedIn Learning</h4>
<p>With a premium membership, you can access LinkedIn Learning, an online educational platform offering a wide range of courses. Upon completing these courses, you will receive LinkedIn Learning certificates, which optimize your LinkedIn profile by displaying your skills and professional development to prospective employers and connections. </p>
<p>You can take advantage of a free trial period to explore the platform by signing up for a one-month LinkedIn Premium membership. _(<em>You can take LinkedIn Learning courses from Dylan Israel, a successful graduate of freeCodeCamp and a LinkedIn Learning instructor.</em>)_</p>
<h4 id="heading-5-linkedin-skill-assessments">5. LinkedIn Skill Assessments</h4>
<p>Skill Assessments are FREE tests offered by LinkedIn to evaluate your proficiency in various skills. A corresponding badge will be added on your profile when you pass a Skill Assessment test. If you fail the test, no worries! You are allowed to retake them after three months.</p>
<p>LinkedIn advertises that candidates who complete Skill Assessments are 30% more likely to get hired, so they are definitely worth trying to attain. Programming LinkedIn skill assessments you may be interested in include HTML, CSS, JavaScript, React.js, Angular, jQuery, and Vue.js.</p>
<p>To get an idea of what taking these tests are like, you can watch Kyle Cook's (Web Dev Simplified) recorded Livestream YouTube videos taking them.</p>
<p>Kyle Cook (Web Dev Simplified) LinkedIn Skill Assessments:</p>
<ul>
<li><a target="_blank" href="https://www.youtube.com/watch?v=R5KH_vwcQ48&amp;t=14s">LinkedIn HTML Quiz</a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=4iXKlZCYd2s">LinkedIn CSS Quiz</a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=V__irponAuA">LinkedIn JavaScript Quiz</a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=0va5IF2xu0s">LinkedIn React Quiz</a></li>
</ul>
<h3 id="heading-special-thanks">Special thanks</h3>
<p>Special thanks to Scrimba and the industry experts who reviewed my LinkedIn profile and provided valuable, constructive criticism, which enabled me to optimize it, resulting in a continual flow of opportunities coming directly to me:</p>
<ul>
<li><a target="_blank" href="https://www.linkedin.com/in/dthompsondev/">Danny Thompson</a> - Tech Celebrity!</li>
<li><a target="_blank" href="https://www.linkedin.com/in/austinhenline/">Austin Henline</a> - LinkedIn</li>
<li><a target="_blank" href="https://www.linkedin.com/in/taylordesseyn/">Taylor Desseyn</a> - Recruiter</li>
<li><a target="_blank" href="https://www.linkedin.com/in/alishahnovin/">Alishah Novin</a> - Microsoft</li>
<li><a target="_blank" href="https://www.linkedin.com/in/molly-may-gallagher/">Molly-May Gallagher</a> - Recruiter</li>
<li><a target="_blank" href="https://www.youtube.com/@CodewithLeanne/videos">Leanne Rybintsev</a> - <a target="_blank" href="https://scrimba.com/">Scrimba</a> Livestream host</li>
</ul>
<h3 id="heading-conclusion">Conclusion</h3>
<p>As a web developer, having a LinkedIn profile is equally important as having a resume. Creating and optimizing a LinkedIn profile will help you stand out from the competition, draw the attention of recruiters and hiring managers, and attract a wealth of opportunities directly to you.</p>
<p>Once you have created and optimized your LinkedIn profile, you must stay active on the platform, as inactivity can be seen as a red flag for recruiters and hiring managers. You can stay active by interacting with posts through creation, commenting, and sharing them. You can also attend and participate in LinkedIn Livestream events to keep your account active.</p>
<p>Remember, LinkedIn is a professional platform and should be treated accordingly. Refrain from posting, commenting, or engaging in any form of communication that could potentially damage your reputation.</p>
<p>You can further enhance your LinkedIn profile by increasing your credibility. Make sure to include your honors and awards, consider taking LinkedIn Skill Assessments and courses, and ask for endorsements and recommendations from your network. Also, be on the lookout for new features you can take part in to boost your credibility, such as collaboration articles that award exclusive badges.</p>
<p>Most importantly, don't just take my word for it: regularly update your profile, discover what works best for you, and also observe how others have effectively optimized their LinkedIn profiles. If you or someone else has further optimization tips that I haven't covered, please share them so that we can all have the best-optimized profiles, leading to daily opportunities coming directly to each of us.</p>
<h3 id="heading-other-articles-ive-written-related-to-linkedin">Other articles I've written related to LinkedIn</h3>
<ul>
<li><a target="_blank" href="https://selftaughttxg.com/2022/10-22/LinkedIn-AustinHenline/">LinkedIn Profile Optimization With Austin Henline</a></li>
<li><a target="_blank" href="https://selftaughttxg.com/2023/08-23/revamp-your-resume-and-linkedin-profile-expert-tips-to-get-noticed-and-hired/">Revamp Your Resume and LinkedIn Profile: Expert Tips to Get Noticed and Hired</a></li>
<li><a target="_blank" href="https://selftaughttxg.com/2021/05-21/LinkedInReviewWithDannyThompson/">LinkedIn Review with Danny Thompson</a></li>
<li><a target="_blank" href="https://selftaughttxg.com/2021/03-21/LinkedIn-Profile-Review/">Create a LinkedIn profile that gets noticed by tech recruiters</a></li>
<li><a target="_blank" href="https://scrimba.com/articles/linkedin-for-developers/">How to use LinkedIn as a developer to get a job in tech</a></li>
</ul>
<p>Let's connect! I'm active on <a target="_blank" href="https://www.linkedin.com/in/michaeljudelarocca/">LinkedIn</a> and <a target="_blank" href="https://twitter.com/MikeJudeLarocca">Twitter</a>.</p>
<p><img src="https://uploads-ssl.webflow.com/5f21f5bb63183fc595ff8426/649b64bfb2d7d7f783c83e48_Logo-White-Slogan-e33c0614b0d4934fac45d58883ebb935.jpeg" alt="selftaughttxg logo" width="600" height="400" loading="lazy"></p>
<h6 id="heading-you-can-read-all-of-my-articles-on-selftaughttxgcomhttpselftaughttxgcom"><strong>You can read all of my articles on <a target="_blank" href="http://selftaughttxg.com">selftaughttxg.com</a></strong></h6>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
