Blog #11: Don't wait until 'heavy web' to lose weight for your Bundle
To my past self who didn't know what Bundle size was. Back when optimization only crossed my mind when the boss complained the web loaded too slowly.
Dear my younger self,
I remember how proud you were when you finished that new feature. You were immersed in coding, adding grand animation libraries and magnificent UI frameworks. You confidently said: "My machine has an i7 chip, the company network is lightning fast, so loading in 1 second is plenty fast!". You never bothered to open the Network tab to see that your main.js file had ballooned to 2MB.
To you back then, optimizing bundle size was a luxury meant for bored experts. But believe me, that laziness was a trap that would take you weeks to escape later on.
1. Simple Explanation: The Suitcase Story
Imagine you're preparing for a short trip. Instead of packing only the essentials, you toss everything you find at home into the suitcase: from the iron and hairdryer to a 20kg dumbbell set... just "in case I might need it."
The result? You can't even lift the suitcase out the door, and if you do manage to carry it, you'll pay hefty overweight fees at the airport. The Bundle file is that suitcase, and users are the ones who have to "carry" it to their computers via the network.
2. Current Perspective: Why 'Optimize Early' is a Wise Investment?
Now I understand that bundle size isn't something we fix when it's broken. It's something we must control from the very first line of code.
- The 1% Rule: For every 100kb you add to the bundle, you lose about 1% conversion rate on mobile environments.
- JS Parsing Cost: A 2MB JS file isn't just about download time; it also makes the user's CPU work extremely hard to "translate" all that code. On mid-range devices, this is the main cause of lag upon entering a site.
3. Concrete Example: "Death" by Convenience
You used to write like this because it was... convenient:
// Junior's way: Importing the entire "universe"
import * as Icons from 'lucide-react'; // Loads all 1000+ icons even if you only use 2
import { Page, Button, Table, Modal, Tooltip, ... } from 'my-huge-ui-library';
Why is this a problem? Because even with a great build tool like Webpack or Vite, import * can sometimes make Tree-shaking difficult, or you might be accidentally creating circular dependencies that prevent the bundle from shrinking.
Sustainable Approach (Modern Approach):
// Get only exactly what you need
import { ChevronRight, Settings } from 'lucide-react';
// Use Dynamic Import for heavy components or those not needed immediately
const HeavyChart = dynamic(() => import('./components/HeavyChart'), {
loading: () => <Skeleton />,
ssr: false
});
4. Comparison: "Doing it Fast" vs "Doing it Sustainably"
| Criteria | Doing it Fast (Install first, think later) | Doing it Sustainably (Control every byte) |
|---|---|---|
| Mindset | Just make it work, optimize later | Always ask: How heavy is this? |
| Lighthouse Score | Bright red in Performance | Deep green (90+) |
| Mobile Experience | A disaster, freezes up | Smooth immediately upon loading |
| Supporting Tools | None used | Webpack Bundle Analyzer, BundlePhobia |
A Junior often thinks: "If the web is heavy, just buy a better server." But in reality, a better server doesn't make the user's network faster, nor does it make their phone's CPU stronger.
5. Practical Lesson: Don't guess, look at the charts
I once spent 3 days just trying to find why the build suddenly increased by 1MB. It turned out a team member had accidentally imported a mockup file of entire test data into the production folder. If we had turned on Webpack Bundle Analyzer every time we ran a build, we would have caught that in 5 seconds.
The biggest lesson is: Measure frequently. Don't let Bundle size be a mystery. Treat it as one of the "vital" metrics of the project, on par with the number of bugs.
And remember: Users don't care how "cool" your code is; they only care if the website appears instantly when they click.
Notes for my 22-year-old self, back when I looked down on KB numbers.
Series • Part 11 of 50