<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Akash Paul</title>
    <description>The latest articles on DEV Community by Akash Paul (@akash_paul_e83687cdbe1368).</description>
    <link>https://dev.to/akash_paul_e83687cdbe1368</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3909057%2F5e07d1c0-5dff-4d38-b45d-ec4bc5e86631.png</url>
      <title>DEV Community: Akash Paul</title>
      <link>https://dev.to/akash_paul_e83687cdbe1368</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/akash_paul_e83687cdbe1368"/>
    <language>en</language>
    <item>
      <title>How I Cut JS Bundle Size by 83% and Made a Page Load 3x Faster</title>
      <dc:creator>Akash Paul</dc:creator>
      <pubDate>Sat, 02 May 2026 13:45:24 +0000</pubDate>
      <link>https://dev.to/akash_paul_e83687cdbe1368/how-i-cut-js-bundle-size-by-83-and-made-a-page-load-3x-faster-1m2a</link>
      <guid>https://dev.to/akash_paul_e83687cdbe1368/how-i-cut-js-bundle-size-by-83-and-made-a-page-load-3x-faster-1m2a</guid>
      <description>&lt;p&gt;Our app was embarrassingly slow.&lt;/p&gt;

&lt;p&gt;13.5 seconds to First Contentful Paint on mobile. A Lighthouse score of 47. Users were waiting — and probably leaving.&lt;/p&gt;

&lt;p&gt;I'd just joined as the frontend engineer at a SaaS startup. Nobody told me to fix the performance. But the numbers were bad enough that I couldn't ignore them.&lt;/p&gt;

&lt;p&gt;Here's exactly what I did, and what I learned.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Starting Point (It Was Bad)
&lt;/h2&gt;

&lt;p&gt;Before I touched anything:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JS Bundle&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2,054 KB (~2MB)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;175 KB&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First Contentful Paint&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;13.5 seconds&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lighthouse Mobile&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;47 / 100&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lighthouse Desktop&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;60 / 100&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A 2MB JavaScript bundle. On mobile. In 2025.&lt;/p&gt;

&lt;p&gt;This wasn't a slow app — it was a broken experience. Nobody waits 13 seconds for a dashboard to load.&lt;/p&gt;




&lt;h2&gt;
  
  
  Finding the Culprit
&lt;/h2&gt;

&lt;p&gt;First step: understand &lt;em&gt;why&lt;/em&gt; it's this bad. I ran a bundle analysis and found three main problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Everything was loading upfront&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The app had no code splitting. Every route, every modal, every component — all of it loaded on the very first page visit. Users were downloading code for screens they'd never even open.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. A massive unused script: &lt;code&gt;gptengineer.js&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This was the biggest single win. Someone had added a heavy script from an AI prototyping tool during early development and it never got removed. It was sitting in the bundle, loading on every page, doing absolutely nothing in production.&lt;/p&gt;

&lt;p&gt;This single file was responsible for a significant chunk of that 2MB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. CSS bloat&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;175KB of CSS — most of it unused. Styles imported globally, never cleaned up, just accumulating.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Fixes (Nothing Exotic)
&lt;/h2&gt;

&lt;p&gt;I want to be honest: I didn't use any fancy techniques here. These are standard practices. The problem was they just hadn't been applied yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix 1: Lazy loading routes and heavy components
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before — loads everything immediately&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Dashboard&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/Dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CampaignManager&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/CampaignManager&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Analytics&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/Analytics&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// After — loads only when needed&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Dashboard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/Dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CampaignManager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/CampaignManager&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Analytics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/Analytics&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wrap with &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; and you're done. React does the heavy lifting — it splits each lazy import into its own chunk and only fetches it when the user navigates to that route.&lt;/p&gt;

&lt;p&gt;The impact was immediate. The initial bundle dropped significantly because users on the login page no longer needed to download the entire dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix 2: Remove dead code ruthlessly
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;gptengineer.js&lt;/code&gt; — gone. It was one line to remove it. That one line recovered hundreds of KB.&lt;/p&gt;

&lt;p&gt;This is a lesson I'll carry forward: &lt;strong&gt;audit your dependencies regularly&lt;/strong&gt;. Dev tools leave artifacts. Prototyping libraries get committed. Nobody notices until someone runs a bundle analysis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run this. Look at what's in your bundle.&lt;/span&gt;
npx vite-bundle-visualizer
&lt;span class="c"&gt;# or for webpack:&lt;/span&gt;
npx webpack-bundle-analyzer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fix 3: Clean up global CSS imports
&lt;/h3&gt;

&lt;p&gt;Instead of importing everything globally, I scoped styles to where they were actually used and removed entire CSS files that had no live references in the codebase.&lt;/p&gt;

&lt;p&gt;This took the CSS from 175KB → 40KB. A 77% reduction just from cleanup.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Results
&lt;/h2&gt;

&lt;p&gt;After three focused days of work:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;th&gt;Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JS Bundle&lt;/td&gt;
&lt;td&gt;2,054 KB&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;359 KB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;83% smaller&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS&lt;/td&gt;
&lt;td&gt;175 KB&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;40 KB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;77% smaller&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First Contentful Paint&lt;/td&gt;
&lt;td&gt;13.5s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.4s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lighthouse Mobile&lt;/td&gt;
&lt;td&gt;47&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;68&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;+21 points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lighthouse Desktop&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;96&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;+36 points&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Desktop went from 60 to 96. Mobile from 47 to 68.&lt;/p&gt;

&lt;p&gt;The app felt like a different product.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd Tell My Past Self
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Measure first, always.&lt;/strong&gt; I knew the app was slow but I didn't know &lt;em&gt;why&lt;/em&gt; until I ran the bundle analysis. Guessing wastes time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The basics compound.&lt;/strong&gt; Code splitting + removing dead code + cleaning CSS. Nothing groundbreaking. But each one reinforced the others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance is everyone's job.&lt;/strong&gt; It took me joining the team for this to get fixed. That's too late. Bundle audits should be part of regular dev cycles — not something discovered by accident.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The 2MB was embarrassing in hindsight, but that's fine.&lt;/strong&gt; Fast-moving startups ship features first and optimize later. The key is knowing when "later" has arrived.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Checklist if You're in the Same Situation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Run a bundle visualizer — find what's actually in there&lt;/li&gt;
&lt;li&gt;[ ] Search for dev/prototyping tools left in production (&lt;code&gt;gptengineer&lt;/code&gt;, &lt;code&gt;lovable&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;[ ] Add &lt;code&gt;React.lazy()&lt;/code&gt; + &lt;code&gt;Suspense&lt;/code&gt; for route-level code splitting&lt;/li&gt;
&lt;li&gt;[ ] Check for globally imported CSS with no live references&lt;/li&gt;
&lt;li&gt;[ ] Set a bundle size budget in your build config so this doesn't creep back&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you've got a React app that feels sluggish and haven't run a bundle analysis yet — do it today. You might be surprised what you find.&lt;/p&gt;

&lt;p&gt;Happy to answer questions in the comments. What's the worst bundle size you've seen in the wild?&lt;/p&gt;

</description>
      <category>webperf</category>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
