TL;DR
Choose Preact when its approximately 3kB core, reactive Signals model, and preact/compat migration path solve a measured delivery constraint. Choose React when current React APIs, React-specific frameworks, or dependency compatibility are requirements.
preact/compat is a compatibility layer, not a promise. Test the application, build output, third-party components, and critical browser flows before treating a React-to-Preact change as releasable.
Key takeaways
- Preact's official documentation positions the core at approximately 3kB.
- For 2026-08-13 through 2026-08-19, React had 143,911,781 npm downloads and Preact had 25,527,492, a 5.64x ratio.
- In the repository's 2026-08-16 snapshot, React was version 19.2.8 with 247,283 stars; Preact was version 10.29.8 with 38,819 stars.
- Download and star totals are dated activity signals, not measures of team availability, ecosystem quality, or application performance.
- Preact documents Signals as reactive primitives for values that update over time.
- React 19 includes APIs and capabilities that must be checked explicitly against Preact and the application's framework.
Comparison matrix
| Decision axis | Preact | React |
|---|---|---|
| Core positioning | Approximately 3kB in official Preact documentation | Measure the actual React and framework output in your build |
| State model | Hooks plus optional Signals reactive primitives | React state, transitions, Actions, and current React APIs |
| Compatibility | preact/compat, verified per application and dependency | Reference target for React ecosystem packages |
| Framework fit | Preact-native tools or custom client applications | React frameworks and React-specific server/client features |
| Migration posture | Pilot by aliasing and testing | No compatibility substitution required |
| npm downloads, 2026-08-13 to 2026-08-19 | 25,527,492 | 143,911,781 |
| Version and stars, 2026-08-16 snapshot | 10.29.8 / 38,819 | 19.2.8 / 247,283 |
What the size claim does and does not say
Preact's getting-started documentation presents its core as approximately 3kB. That makes it a credible candidate for embedded widgets, constrained mobile delivery, and pages where the framework is a meaningful share of shipped JavaScript.
It does not predict the size of your application. A Preact build may still include large editors, charts, analytics, polyfills, or compatibility dependencies. A React framework may split and stream code in ways a raw package comparison does not capture. The only defensible comparison is the production build for the same user flow.
Before changing frameworks, record:
- route-level JavaScript transferred on first load;
- parsed and executed JavaScript on representative devices;
- hydration and interaction timing;
- third-party script cost;
- the portion attributable to framework code rather than application features.
Use those measurements to decide whether the migration addresses a real bottleneck.
Signals: reactive values in Preact
Preact documents Signals as reactive primitives. A signal holds a value, a computed signal derives from other signals, and an effect can respond to dependencies. Components can read signal values without moving every piece of state into a component-local hook.
import { computed, signal } from '@preact/signals'
const quantity = signal(1)
const unitPrice = signal(12)
const total = computed(() => quantity.value * unitPrice.value)
export function CartTotal() {
return <output>{total}</output>
}
Signals can reduce the amount of component plumbing for shared or frequently updated values. They do not make every UI faster automatically. Rendering cost still depends on component structure, DOM work, effects, data fetching, and the frequency and shape of updates. Profile the actual interaction before and after a state-model change.
preact/compat: evaluate, do not assume
Preact's switching guide documents aliases that redirect React-oriented imports to preact/compat. A Vite configuration can establish a contained pilot:
import { defineConfig } from 'vite'
export default defineConfig({
resolve: {
alias: {
react: 'preact/compat',
'react-dom': 'preact/compat',
'react-dom/test-utils': 'preact/test-utils',
'react/jsx-runtime': 'preact/jsx-runtime',
},
},
})
Run the existing unit, integration, and browser suites after applying the aliases. Pay special attention to portals, controlled inputs, refs, event behavior, Suspense, testing utilities, and packages that inspect React internals.
The migration should stop if a required dependency relies on an unsupported API or if the compatibility adapter creates more maintenance work than the measured delivery benefit justifies.
React 19 and framework requirements
React 19 added capabilities including Actions and the use API. React frameworks can also depend on server/client behavior that a client-side alias cannot reproduce. If an application uses those features, list them before a Preact pilot and verify each one against current Preact documentation.
React is often the lower-risk choice when a framework owns rendering, routing, data loading, and server components as one integrated system. The "nobody gets fired for choosing React" phrase captures familiarity, but familiarity is not a technical benchmark. The decision should rest on the application's supported APIs, maintenance capacity, and measured delivery constraints.
Native events and behavioral differences
Preact documents differences from React, including event and rendering behavior. These differences may be invisible in ordinary components and material in complex ones. Tests should cover event propagation, focus management, input composition, and browser accessibility behavior rather than only snapshot markup.
React Native also remains a separate platform requirement. There is no "Preact Native." If the product shares components or team practices with a React Native application, that constraint may outweigh a client-bundle reduction on the web.
Dated package activity
The official npm API reported 143,911,781 downloads for React and 25,527,492 for Preact during 2026-08-13 through 2026-08-19. Dividing those same-period values gives a 5.64x ratio.
The repository snapshot dated 2026-08-16 recorded React 19.2.8 with 247,283 GitHub stars and Preact 10.29.8 with 38,819. These figures help establish current package identity and activity. They do not prove that one framework has proportionally more compatible libraries, available engineers, or production reliability.
See the live package comparison at pkgpulse.com/compare/preact-vs-react.
Migration notes
- Define the constraint. Record the route, device class, and metric the migration is expected to improve.
- Create an alias-only pilot. Keep feature work out of the same branch so compatibility findings are attributable.
- Run the full test suite. Unit tests alone will not catch event, focus, portal, or hydration differences.
- Exercise critical browser flows. Test forms, modals, navigation, authentication, and error handling.
- Inspect dependencies. Identify packages that require current React APIs or touch internal behavior.
- Measure production output. Compare equivalent optimized builds and representative user flows.
- Plan rollback. Keep the React build reproducible until the Preact release has passed production monitoring.
For a new Preact application, prefer Preact-native setup instead of beginning with a large React compatibility surface. For an existing React application, migrate only if the measured benefit survives compatibility and maintenance costs.
Security notes and reliability
Both frameworks escape interpolated text by default, but either can render unsafe HTML when an application bypasses that protection. Treat HTML strings as untrusted, avoid direct HTML injection, and sanitize at a reviewed seam when rich content is required.
A compatibility migration changes dependency resolution. Review the lockfile, confirm that only intended packages were replaced, and run dependency and license checks. Keep Preact, React-oriented dependencies, the bundler, and test utilities on compatible supported versions.
SSR and hydration failures can expose stale or inconsistent UI state even when they are not direct security vulnerabilities. Test authentication state, authorization-dependent controls, and destructive actions after any rendering-runtime change. Never rely on client-side component visibility as the authorization check.
Methodology
The source ledger below records the official materials used for this refresh.
Sources
This refresh used official Preact and React documentation, official npm API values for a fixed weekly interval, npm registry metadata, Preact's current release record, and the repository's frozen package snapshot. Volatile values were rechecked on 2026-08-21. No synthetic bundle, network, parse-time, hiring, or conversion benchmark was used.
Primary sources:
Explore related comparisons: HTMX vs React, React vs Vue, and Redux vs Zustand. Related guides: Angular vs React, HTMX vs React, and Qwik vs React.
