All Docs
FeaturesSaaS FactoryUpdated February 19, 2026

Cutting 150–300 KB: How We Fixed the lucide-react Barrel Import Problem

Cutting 150–300 KB: How We Fixed the lucide-react Barrel Import Problem

Version: 1.0.25
Category: Performance

Background

lucide-react is a popular icon library that ships a single barrel export — one entry point that re-exports all 563 icons. Named imports like:

import { Flame, Search, Shield } from 'lucide-react';

...look clean and are idiomatic JavaScript, but they carry a hidden cost: unless the bundler can reliably tree-shake the barrel, it may include the full package in the output bundle.

What We Found

Across the platform, 50+ component files use this named import pattern. beast-mode-tab.tsx alone pulls in 23 icons. Without an explicit signal to the bundler, every one of those import sites is a potential vector for the full 563-icon payload.

Next.js does perform tree-shaking, but barrel files can defeat it — especially in edge cases involving re-exports, dynamic imports, or certain module graph shapes. The safe fix is to not rely on probabilistic tree-shaking at all.

The Fix

Next.js 13.5+ ships experimental.optimizePackageImports, a compiler-level feature that rewrites barrel imports into direct path imports before the bundler ever sees them. Enabling it for lucide-react is a one-line change:

// next.config.ts
const nextConfig = {
  experimental: {
    optimizePackageImports: ['lucide-react'],
  },
};

At compile time, Next.js transforms:

// What you write
import { Flame, Search, Shield } from 'lucide-react';

Into the equivalent of:

// What the bundler sees
import Flame  from 'lucide-react/icons/flame';
import Search from 'lucide-react/icons/search';
import Shield from 'lucide-react/icons/shield';

Direct path imports cannot accidentally drag in unrelated icons. Tree-shaking is guaranteed — not assumed.

No Component Changes Required

The rewrite happens entirely at the compiler level. Every existing import { ... } from 'lucide-react' statement across all 50+ component files remains unchanged. Developers continue writing idiomatic named imports.

Estimated Impact

  • Bundle reduction: 150–300 KB of JavaScript removed from the client bundle
  • Icons bundled: Reduced from up to 563 to only those actually imported
  • Files modified: 1 (next.config.ts)
  • Component changes: 0

The range reflects uncertainty in how aggressively the bundler was already tree-shaking without the hint. In the best pre-fix case, some icons were already dropped; in the worst case, none were. With optimizePackageImports the outcome is deterministic regardless of bundler behavior.

Takeaway

For any library that uses a barrel entry point (a single index.js that re-exports everything), adding it to experimental.optimizePackageImports in next.config.ts is a low-risk, high-reward optimization. It costs one line of config and requires zero changes to application code.