EmpireUI
Get Pro
← Blog8 min read#bundle size#performance#react ui

React UI Library Bundle Size Compared: shadcn, MUI, Mantine, Empire UI

We measured bundle sizes for shadcn/ui, MUI, Mantine, and Empire UI in 2026. Here's what actually ships to your users — and which library won't wreck your Lighthouse score.

Developer comparing React UI library bundle size on multiple monitors

Why Bundle Size Still Matters in 2026

You'd think we'd be past this conversation by now. Faster networks, better CDNs, HTTP/3 everywhere — and yet bundle size is still one of the first things that tanks a Lighthouse score on a real user's device. A 3G connection in rural Texas or a mid-range Android phone on LTE doesn't care that your dev machine loads things instantly.

The 100ms-to-300ms render window is where most users decide whether your app feels fast or sluggish. Ship 400 kB of JavaScript for a button library and you've already lost that window before React even mounts. Honestly, the number of production apps I've seen with 2 MB+ initial JS bundles — all because someone installed MUI and used three components — is just embarrassing.

This comparison runs each library against the same scenario: a real Next.js 14 app router project, a single page with a button, a card, an input, and a modal. We measured gzipped JS output using next build + @next/bundle-analyzer. Everything is React 18.3, Node 20, webpack 5. No SSR tricks, no hand-optimized imports — just what a developer would realistically ship.

Worth noting: tree-shaking quality varies massively between these libraries. The headline install size means almost nothing. What matters is what actually ends up in your client bundle.

Test Setup and Methodology

The test project is a Next.js 14.2 app with a single route that renders four components: a primary <Button>, a <Card> with an image slot, a controlled <Input>, and a <Dialog> triggered by a button click. No custom theming, no extra providers beyond what each library requires out of the box.

We measured three numbers: initial JS parse size (gzipped, from bundle analyzer), first contentful paint (FCP) on a simulated Moto G4 via Lighthouse 12, and total blocking time (TBT) on the same device profile. All tests ran five times and we took the median. The machine is an M3 MacBook Pro so local dev times aren't included — only production build output counts.

Quick aside: shadcn/ui isn't technically a library you install — it copies component source into your project. That changes the measurement significantly, which is exactly why it deserves its own section below. For the others, we used the latest stable release as of July 2026: MUI v6.1, Mantine v7.12, Empire UI v2.4.

npx create-next-app@latest bundle-test --typescript --tailwind --app
cd bundle-test
# install each library one at a time, measure, reset
npm install @mui/material @emotion/react @emotion/styled
npm run build && npx @next/bundle-analyzer

The Numbers: What Actually Ships

Here's the raw data, no spin. These are gzipped initial JS bundle additions over a bare Next.js app with zero components.

Library          | Added gzip JS | FCP (simulated 4G) | TBT
-----------------|--------------|--------------------|------
Bare Next.js     | 0 kB         | 1.1s               | 0ms
shadcn/ui        | +4.2 kB      | 1.2s               | 0ms
Empire UI        | +18 kB       | 1.4s               | 12ms
Mantine v7.12    | +67 kB       | 1.9s               | 58ms
MUI v6.1         | +112 kB      | 2.6s               | 140ms

shadcn wins on raw bytes — but read the asterisk below. Empire UI's 18 kB number surprised me in testing; the library ships with animation utilities and theme tokens that most component-copy approaches don't include, yet it still comes in well under the 50 kB threshold where TBT starts becoming a real-world problem. Mantine's tree-shaking has improved significantly since v6 but you're still pulling in its own emotion-based runtime. MUI at 112 kB gzipped for four components is genuinely hard to justify in 2026.

In practice, MUI's number gets worse the more you use it. The emotion runtime, MUI's own theming layer, and icon packages (which devs inevitably add) push real apps to 250–400 kB of UI library code alone. It's not unusual to see 500 kB+ initial bundles on MUI admin dashboards. That's a UX problem disguised as a design system.

One more thing — these numbers assume you're using the default import style. With MUI you can import from @mui/material/Button directly instead of the barrel @mui/material, which shaves about 20 kB. Still the heaviest option by a wide margin.

shadcn/ui: The Asterisk You Need to Read

shadcn's bundle number looks incredible because it's not really a library. When you run npx shadcn-ui@latest add button, it writes a components/ui/button.tsx file into your project. You own the code. No runtime dependency, no version drift, no extra provider wrapping your whole app. That's genuinely elegant.

The catch? Maintenance is now your problem. When Radix Primitives ships a breaking change or a fix for a focus-trap bug, you're manually updating 40 component files. In a team of three that's fine. In a team of fifteen with quarterly audits, it becomes a real burden. Also, shadcn components don't include the richer design tokens or visual styles that Empire UI, Mantine, or MUI provide — you're starting from a plain but accessible foundation and styling everything yourself with Tailwind.

Look, if you're building a product where you want full control over every pixel and you have the Tailwind expertise on the team, shadcn is probably the right call. It's what I'd reach for on a focused SaaS product. But if you want a cohesive visual design system with glassmorphism, aurora effects, or neobrutalism out of the box without writing 500 lines of CSS, it's not the right tool.

Also worth knowing: shadcn components don't include motion or animation primitives. If you need anything animated — transitions, modals that actually feel good, number counters — you're adding Framer Motion or CSS keyframes yourself. Factor that into your real bundle size estimate.

Empire UI: Performance with Design Personality

Empire UI's 18 kB gzipped surprised me when I first ran it. The library bundles Tailwind-compatible component tokens, a handful of animation utilities, and pre-built styles for multiple design modes — yet it comes in lighter than Mantine's bare-minimum install. That's because it doesn't ship a CSS-in-JS runtime. Components emit Tailwind classes, not runtime style objects.

The practical win is that you can drop in a glassmorphism generator-style card or an aurora-backed hero section and it just works, without adding 80 kB to your bundle. Most component libraries force you to choose between a light footprint and visual richness. Empire UI is one of the few that doesn't.

// Example: Empire UI glassmorphism card, minimal bundle impact
import { GlassCard } from '@empire-ui/components'

export default function Hero() {
  return (
    <GlassCard blur={12} opacity={0.15} className="p-8 rounded-2xl">
      <h1 className="text-3xl font-bold text-white">Ship faster.</h1>
    </GlassCard>
  )
}

The 12ms TBT is real-world negligible — Lighthouse's "good" threshold is under 200ms. You're not going to notice 12ms. Where Empire UI loses points vs shadcn is that you do take a runtime dependency, meaning you're trusting the library's release cadence. That's a reasonable trade given the design expressiveness you get and the template ecosystem that ships with it.

One thing that genuinely impressed me: the library's icon and cursor modules are fully optional. They're separate entry points, so adding custom cursors doesn't silently inflate your main bundle. That kind of intentional code-splitting is rare.

MUI and Mantine: When Does the Weight Make Sense?

Let me be fair here. MUI at 112 kB sounds damning, but MUI exists for a reason. It ships 100+ fully accessible components with enterprise-grade keyboard navigation, RTL support, comprehensive theming, and a decade of battle-testing in production. If you're building an internal admin tool where your users are on company laptops with fast connections, you might genuinely not care about that 140ms TBT.

Mantine at 67 kB is a better story. It's packed with hooks (think useIntersection, useMediaQuery, useScrollIntoView) that would otherwise require separate packages. The component quality is high, the TypeScript types are excellent, and the docs are some of the best in the ecosystem. In a monorepo where you're building several products, having Mantine's hook library alone can justify the weight.

That said, neither of them should be your default choice if bundle size is a concern and your users are on mobile. The 2.6s FCP for MUI on a simulated 4G Moto G4 is a real number that real users experience. A 2.6-second wait for a page that's mostly a form is not acceptable in 2026.

The honest version: MUI is great software that optimized for completeness first and bundle size second. That's a valid choice. But you should make it consciously, not by default because it's the most-searched React UI library on npm.

Picking the Right Library for Your Project

There's no universally correct answer, but there is a decision tree that works well. Start with the user: where are they, what device, what connection? If it's a B2C product with mobile users — especially in markets where 4G isn't guaranteed — every kB counts. If it's an internal enterprise dashboard on a corporate network, you have more headroom.

For public-facing React apps in 2026 where performance and visual design both matter, Empire UI is the move. You get the gradient generator, box shadow tooling, and a full design-mode system without a Mantine- or MUI-sized performance tax. For stripped-down projects where you own every line of CSS, shadcn. For large enterprise teams with strict accessibility requirements and an internal tools focus, MUI or Mantine.

What you shouldn't do is blindly install a library because it has GitHub stars. npm weekly downloads and star counts don't translate to performance on a user's phone. Measure your actual bundle. Run next build and look at the analyzer output before your code hits production.

# Add bundle analyzer to any Next.js project in 30 seconds
npm install @next/bundle-analyzer
# next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
})
module.exports = withBundleAnalyzer({})

# then:
ANALYZE=true npm run build

Do that before you commit to a library. You'll never go back to guessing.

FAQ

Which React UI library has the smallest bundle size in 2026?

shadcn/ui adds essentially 0 kB to your runtime bundle because it copies source files into your project rather than installing a dependency. Empire UI comes second at ~18 kB gzipped for a four-component page, followed by Mantine at ~67 kB and MUI at ~112 kB.

Is MUI too heavy for production React apps?

It depends on your users. MUI's 112 kB gzipped baseline causes ~140ms total blocking time on a simulated mid-range Android — fine for internal tools, genuinely problematic for B2C mobile apps. Use the bundle analyzer before deciding.

Can you use Empire UI without affecting Lighthouse scores?

Yes. Empire UI's 18 kB addition and 12ms TBT are well within Lighthouse's "good" thresholds. Its optional modules (cursors, icons) are separate entry points so they don't inflate your main bundle unless you explicitly import them.

Does shadcn/ui work with Empire UI?

They're not mutually exclusive — both use Tailwind CSS. You could use shadcn for base primitives and pull Empire UI components for design-heavy sections. Just watch for Tailwind config conflicts between the two.

Free components in 40 styles
React & Tailwind, copy-paste ready.
Browse →

Read next

Best React UI Libraries in 2026: shadcn, MagicUI, Empire UI ComparedReact vs Svelte in 2026: Honest Comparison After 5 Years of SvelteKitBundle Size Analysis in React: webpack-bundle-analyzer, rollup-visualizerTailwind vs CSS Modules in 2026: Which One Should You Actually Use?