Open your Chrome DevTools right now. Open the Network tab, throttle your connection to Fast 4G, set CPU throttling to 4x slowdown (to simulate a typical $200 Android handset), and hard reload your product landing or web checkout page.
Watch the CPU thread peg at 100% for five straight seconds while the browser parses, compiles, and executes 3.8 megabytes of minified JavaScript.
During those five seconds, if a prospective customer taps your “Sign Up” or “Add to Cart” button, nothing happens. The browser literally cannot respond because the main thread is trapped running hydration scripts for UI elements that the user hasn’t even scrolled to yet.
They tap twice. Still frozen. They assume your site is broken, hit back, and buy from your competitor.
The Barrel File Disease
When we run webpack-bundle-analyzer or rollup-plugin-visualizer on client web applications, 60% of the bundle bloat usually boils down to three sloppy patterns.
The biggest offender is the innocent-looking barrel file:
// components/index.ts
export * from './Button';
export * from './Header';
export * from './HeavyDataGridChart'; // Pulls in 850KB of D3 & Canvas
export * from './VideoPlayer'; // Pulls in 420KB of HLS.js
Somewhere in your lightweight marketing footer, someone wrote:
import { Button } from '@/components';
Because of how module bundlers evaluate side-effects in common re-export files, Vite or Webpack frequently fails to tree-shake the rest of the barrel. Congratulations: your simple footer just bundled a full enterprise charting suite and a video codec library into the critical initial chunk.
The Fix: Explicit Deep Imports & Lint Rules
We ban broad re-export barrel files in performance-critical paths and enforce strict ESLint import restrictions:
// .eslintrc.js
module.exports = {
rules: {
'no-restricted-imports': ['error', {
paths: [{
name: 'lodash',
message: 'Import specific utilities directly, e.g., import debounce from "lodash/debounce".',
}, {
name: '@lucide/lab',
message: 'Import individual SVG icons directly from lucide-react/dist/esm/icons/...',
}],
}],
},
};
Islands Architecture: Why We Ship Zero JS By Default
For any public-facing web platform—marketing pages, e-commerce storefronts, documentation, onboarding flows—we refuse to ship an all-or-nothing Single Page Application (SPA).
Using Astro, we render 100% of the layout, typography, navigation, and content as pure, zero-JS HTML and CSS.
Interactive components (like a complex currency converter, cart drawer, or sign-up modal) are isolated into independent islands using client:idle or client:visible:
---
// This entire hero section ships ZERO kilobytes of client-side JavaScript
import HeroCopy from '../components/HeroCopy.astro';
import PricingCalculator from '../components/PricingCalculator.vue';
---
<section class="hero-section">
<HeroCopy />
<!-- Only hydrate this single interactive widget when the browser is idle -->
<PricingCalculator client:idle />
</section>
The browser receives semantic HTML that paints in 250 milliseconds. The user can read immediately, typography doesn’t shift, and the total JavaScript payload delivered over the wire drops from 3.2MB to under 45KB.
If your marketing or SaaS app is struggling with poor Core Web Vitals (INP and LCP), stop trying to optimize React hydration. Stop sending the JavaScript in the first place.