Skip to main content

Preact vs React: When the Lighter Alternative Wins

·PkgPulse Team

Preact is 3KB gzipped. React + ReactDOM is ~40KB. That's not a rounding error — it's a 10x difference.

On a throttled 3G connection, that 37KB gap translates to roughly 1.5 seconds of additional load time. On a budget Android phone, it's even worse — the parse and execution cost of 40KB of JavaScript is measurably heavier than 3KB. For billions of users accessing the web on mid-range devices and spotty networks, this isn't academic. It's the difference between a page that loads and a page that bounces.

Yet React has 190+ million weekly npm downloads. Preact has ~3.5 million. That's a 50x adoption gap. So what does Preact actually offer — and when does it genuinely win?

We compared both using real data from PkgPulse. Here's what the numbers say.

TL;DR

Preact is a 3KB drop-in alternative to React with a compatibility layer that supports most of the React ecosystem. Its killer feature in 2026 is Signals — a fine-grained reactivity system that bypasses the Virtual DOM entirely and delivers updates without re-rendering. If you're building mobile-first apps, embedded widgets, or performance-critical pages, Preact is a serious contender. If you need React 19's latest features, a massive ecosystem, or enterprise hiring confidence, stay with React.

Key Takeaways

  • Preact is 3KB gzipped vs React's ~40KB — a 10x+ size difference that materially impacts first paint on mobile
  • preact/compat provides drop-in React compatibility — alias it in your bundler and most React libraries just work
  • Preact Signals are the standout feature — fine-grained reactivity without re-renders, available via @preact/signals
  • React 19 features like the use() hook are not yet supported in preact/compat
  • Preact uses native browser events instead of React's synthetic event system, reducing overhead
  • React's ecosystem is 50x larger — more libraries, more tutorials, more hiring confidence
  • Preact 11 is in beta with Hydration 2.0 and Object.is for hook dependencies, but is not production-ready yet

At a Glance: The Numbers

MetricReactPreact
Weekly Downloads190M+~3.5M
GitHub Stars234K+37K+
Bundle Size (min+gzip)~40KB (react + react-dom)~3KB (core)
Virtual DOMYes (synthetic events)Yes (native events)
Signals SupportNo (via third-party)Built-in (@preact/signals)
React Compat LayerN/Apreact/compat
Current Stable Version19.x10.x
Next VersionReact 19+Preact 11 (beta)
TypeScriptFirst-classFirst-class
LicenseMITMIT

See the full live comparison — download trends and health scores — at pkgpulse.com/compare/preact-vs-react

The headline stat: Preact delivers a functionally similar development experience to React in less than one-tenth the bundle size. For projects where every kilobyte counts, that ratio is hard to ignore.

Bundle Size Deep Dive

The raw numbers don't tell the full story. Let's break down what 3KB vs 40KB means in practice.

ScenarioReactPreactDifference
Framework size (gzipped)~40KB~3KB37KB
Parse time (4x CPU throttle)~120ms~12ms10x faster
3G download time~1.6s~0.12s~1.5s saved
4G download time~320ms~24ms~300ms saved

Those parse times matter more than the download times. JavaScript is the most expensive resource browsers handle — unlike CSS or images, every byte of JavaScript must be parsed, compiled, and executed before the page becomes interactive. A 10x reduction in framework size means 10x less work for the JavaScript engine at startup.

In real terms: Uber rebuilt m.uber.com with Preact. For a ride-hailing app used heavily on mobile in emerging markets, shaving 37KB off the framework alone — before any app code — meaningfully improved Time to Interactive. Google has explored Preact for AMP pages for similar reasons.

The impact compounds when you consider what comes after the framework. A typical React app ships 200-500KB of JavaScript. Swapping React for Preact saves 37KB — but the compatibility layer also enables a smaller dependency tree since Preact's internals are simpler. Real-world savings often exceed 50KB.

Where it doesn't matter: If your app already ships 2MB of JavaScript and your users are on fast connections, 37KB is noise. Preact's size advantage is most relevant for mobile-first, performance-sensitive, or bandwidth-constrained contexts.

The Signals Advantage

Preact Signals are the most compelling technical differentiator against React in 2026. They represent a fundamentally different approach to reactivity.

How React Updates Work

React re-renders components. When state changes, React re-executes the component function, diffs the old and new Virtual DOM trees, and patches the real DOM with the differences. Every component in the subtree re-runs — even if only one piece of data changed.

// React: changing `count` re-renders the entire component
function Counter() {
  const [count, setCount] = useState(0)
  return (
    <div>
      <h1>Dashboard</h1>
      <p>Expensive calculation: {heavyComputation()}</p>
      <span>{count}</span>
      <button onClick={() => setCount(c => c + 1)}>+1</button>
    </div>
  )
}

Clicking the button re-renders everything — the heading, the expensive computation, and the count display. You can optimize with useMemo and React.memo, but that's manual work the developer has to think about.

How Preact Signals Work

Signals are reactive primitives. When a signal's value changes, only the specific DOM nodes that reference that signal update. No component re-render. No Virtual DOM diff.

// Preact Signals: changing `count` updates ONLY the text node
import { signal } from '@preact/signals'

const count = signal(0)

function Counter() {
  return (
    <div>
      <h1>Dashboard</h1>
      <p>Expensive calculation: {heavyComputation()}</p>
      <span>{count}</span>
      <button onClick={() => count.value++}>+1</button>
    </div>
  )
}

Clicking the button updates only the <span> text node. The component function does not re-execute. The heading doesn't re-render. The expensive computation doesn't re-run. The Virtual DOM is bypassed entirely for signal-driven updates.

The performance implication: In UIs with frequent, fine-grained updates — dashboards, tickers, form validation, animations — Signals eliminate the re-render overhead that React developers spend significant effort optimizing around with useMemo, useCallback, and React.memo.

Signals Work with React Too

The @preact/signals-react package brings signals to React projects. You don't need to migrate to Preact to benefit from the reactivity model. But the integration is smoother in Preact, where signals are a first-class citizen rather than a bolt-on.

React Compatibility: How Far Does It Go?

Preact's preact/compat module is a compatibility layer that aliases react and react-dom to Preact. The setup is a bundler config change:

Vite

// vite.config.js
export default defineConfig({
  resolve: {
    alias: {
      react: 'preact/compat',
      'react-dom': 'preact/compat',
      'react/jsx-runtime': 'preact/jsx-runtime',
    },
  },
})

Webpack

// webpack.config.js
module.exports = {
  resolve: {
    alias: {
      react: 'preact/compat',
      'react-dom/test-utils': 'preact/test-utils',
      'react-dom': 'preact/compat',
      'react/jsx-runtime': 'preact/jsx-runtime',
    },
  },
}

With this alias in place, most React ecosystem libraries work without modification. React Router, TanStack Query, Zustand, styled-components, and many UI libraries are compatible.

What Works

  • Most React hooks (useState, useEffect, useRef, useContext, useReducer, useMemo, useCallback)
  • React Router, TanStack Query, Zustand, Jotai
  • CSS-in-JS libraries (styled-components, Emotion)
  • Most component libraries that don't rely on React internals
  • createPortal, forwardRef, lazy, Suspense

What Doesn't (Yet)

  • React 19's use() hook — not yet supported in preact/compat
  • React Server Components — Preact has no equivalent
  • Libraries that deeply depend on React internals — some UI frameworks (particularly those using React's reconciler directly) may not work
  • Concurrent featuresuseTransition, useDeferredValue, and concurrent rendering are not available

The practical rule: If your app uses standard React patterns and popular ecosystem libraries, preact/compat will likely work. If you're leveraging React 19's newest APIs or a library that patches React internals, you'll hit compatibility walls.

The Migration Test

The fastest way to evaluate compatibility is to try it:

npm install preact
# Add aliases to your bundler config
# Run your test suite

If your tests pass, you're likely good. The compat layer is well-maintained and covers the vast majority of real-world React usage patterns.

When Preact Shines

Mobile-First Applications

Preact's 3KB footprint makes it the natural choice for apps targeting mobile users on constrained networks. The math is simple: less JavaScript means faster Time to Interactive, lower data usage, and fewer dropped users on slow connections. If your analytics show significant traffic from 3G/4G connections or mid-range devices, Preact's size is a tangible advantage.

Embedded Widgets and Micro-Frontends

Building a widget that gets embedded on third-party sites? Preact is 3KB. React is 40KB. When your widget ships alongside the host page's existing JavaScript, every kilobyte of overhead matters. Preact lets you ship a full component-based widget without meaningfully increasing the host page's load time.

Performance-Critical Pages

Landing pages, e-commerce product pages, and any page where Time to Interactive directly impacts conversion rates. Studies consistently show that every 100ms of load time improvement increases conversion by 1-2%. Preact's 10x smaller framework size translates to measurably faster first paint.

Preact Signals for High-Frequency Updates

Dashboards, trading interfaces, data visualization, live sports scores — any UI where data changes frequently and re-rendering entire component trees is wasteful. Signals provide surgical DOM updates that scale with the number of changes, not the size of the component tree.

When to Stay with React

You Need React 19 Features

Server Components, the use() hook, Actions, and concurrent rendering are React-only. If your architecture depends on these features — particularly Server Components for RSC-based frameworks like Next.js — Preact is not a viable substitute.

Enterprise and Team Scale

React has 190M+ weekly downloads. That means more developers know it, more tutorials exist, more Stack Overflow answers are available, and hiring is easier. For large teams and enterprise projects, React's ecosystem dominance reduces risk. The "nobody gets fired for choosing React" factor is real.

Deep Ecosystem Dependencies

If your project depends on libraries that don't work with preact/compat — UI frameworks that use React's reconciler, testing libraries that mock React internals, or tools that assume React-specific behavior — migrating to Preact creates friction that may not be worth the bundle savings.

React Native

If you need to share code between web and mobile via React Native, React is the only option. There is no "Preact Native."

Migration Guide: React to Preact

Swapping React for Preact in an existing project is one of the lowest-effort migrations in frontend development. Here's the process:

Step 1: Install Preact

npm install preact

Step 2: Add Bundler Aliases

See the Vite and Webpack examples above. This tells your bundler to resolve react and react-dom imports to preact/compat.

Step 3: Run Your Tests

npm test

If your existing test suite passes, you're most of the way there.

Step 4: Test in Browser

Run the app locally and test critical user paths. Pay attention to:

  • Third-party libraries that render UI (modals, tooltips, dropdowns)
  • Complex forms with controlled inputs
  • Portals and refs
  • Any code using React-specific APIs

Step 5: Measure the Impact

Compare bundle sizes before and after. Use Lighthouse or WebPageTest to measure real performance differences. The size savings should be immediately visible.

Common gotcha: If something breaks, it's usually a library that accesses React internals. Check Preact's compatibility documentation for known issues and workarounds.

Preact 11: What's Coming

Preact 11 is in beta and introduces meaningful improvements:

  • Hydration 2.0 — improved server-side rendering hydration for faster initial page loads
  • Object.is for hook dependencies — aligns with React's behavior for dependency comparison in hooks like useEffect and useMemo
  • Security improvements — a January 2026 fix addressed a VNode constructor strict-equality vulnerability

Preact 11 is not production-ready yet. For production applications, Preact 10.x remains the stable, recommended version.

The Verdict

Preact is not trying to replace React. It's offering a trade-off: give up some ecosystem breadth and React 19's cutting-edge features, and in return get a 10x smaller bundle, Signals for fine-grained reactivity, and a compatibility layer that lets you use most of the React ecosystem anyway.

Choose Preact when bundle size is a competitive advantage — mobile-first apps, embedded widgets, performance-critical pages, or any context where Time to Interactive directly impacts business metrics. Signals are a bonus that make Preact genuinely better than React for high-frequency UI updates.

Choose React when you need the full ecosystem, React 19 features (especially Server Components), React Native code sharing, or the hiring and community confidence that comes with 190M weekly downloads.

For teams currently on React who want a quick win, the migration path is remarkably smooth: alias your imports, run your tests, and measure. If it works — and for most standard React apps, it will — you've just cut your framework footprint by 90% with an afternoon of work.

Compare Preact vs React on PkgPulse →


Frequently Asked Questions

Can I use React libraries with Preact?

Yes, most of them. Preact's preact/compat module provides a compatibility layer that aliases react and react-dom imports to Preact. Libraries like React Router, TanStack Query, Zustand, and styled-components work without modification. The main exceptions are libraries that depend on React internals, concurrent features, or React 19-specific APIs like Server Components and the use() hook. Check the live comparison on PkgPulse for current ecosystem data.

What are Preact Signals and why do they matter?

Signals are a fine-grained reactivity system. Unlike React's model where changing state re-renders the entire component, Signals update only the specific DOM nodes that reference the changed value — bypassing the Virtual DOM entirely. This makes frequent updates (dashboards, tickers, form validation) significantly more efficient. Signals are available via @preact/signals for Preact or @preact/signals-react for React projects.

How much smaller is Preact than React?

Preact core is ~3KB gzipped. React + ReactDOM is ~40KB gzipped — a 10x+ difference. In practice, swapping React for Preact in a typical app saves 37-50KB+ of JavaScript. On a 3G connection, that translates to roughly 1.5 seconds of faster load time. On throttled mobile CPUs, the parse time reduction is even more significant.

Is Preact production-ready?

Yes. Preact 10.x is stable and used in production by companies including Uber (m.uber.com), Etsy, and others. It has been actively maintained since 2015. Preact 11 is in beta and not yet recommended for production use. The stable 10.x line receives regular updates and security patches.


Explore more comparisons: React vs Vue, HTMX vs React, or Zustand vs Redux on PkgPulse.

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.