Preact
Frontend UI LibrariesFast 3kB alternative to React with the same modern API
Overview
Preact is a fast, lightweight JavaScript library for building user interfaces using a component-based architecture. With a minified/gzipped size of just 3-4 KB, it delivers React-like functionality—including JSX, hooks, and virtual DOM diffing—while maintaining a significantly smaller footprint than React's 100+ KB bundle. Created to prioritize performance and minimal overhead, Preact is particularly valuable for bandwidth-constrained environments, progressive web apps, and mobile-first applications where initial load time directly impacts user experience.
The library achieves its small size through deliberate architectural choices. Instead of React's synthetic event system, Preact uses the browser's native addEventListener, reducing abstraction overhead and improving DOM compliance. It employs an h() hyperscript function rather than createElement, and supports raw HTML attributes like class instead of className. For teams needing React ecosystem compatibility, the preact/compat alias layer enables most React libraries to work seamlessly with minimal configuration changes.
Preact has gained adoption among developers building performance-critical applications, particularly in e-commerce, media, and PWA contexts where every kilobyte matters. With over 11 million weekly downloads, it's used by companies optimizing for Core Web Vitals and first paint metrics. The library has evolved to include first-class support for Signals—a fine-grained reactivity system that outperforms React's state model for certain update patterns—while maintaining backward compatibility with its established API.
Recent versions emphasize framework interoperability, working with build tools like Vite, and supporting modern patterns like server-side rendering via preact-render-to-string. While it lacks React's advanced features like concurrent rendering and Server Components, Preact's focused scope makes it ideal for projects where bundle size and runtime performance outweigh ecosystem breadth.
Quick Start
import { h, render } from 'preact';
import { useState, useEffect } from 'preact/hooks';
function TodoApp() {
const [todos, setTodos] = useState([]);
const [input, setInput] = useState('');
useEffect(() => {
const saved = localStorage.getItem('todos');
if (saved) setTodos(JSON.parse(saved));
}, []);
const addTodo = () => {
if (!input.trim()) return;
const newTodos = [...todos, { id: Date.now(), text: input, done: false }];
setTodos(newTodos);
localStorage.setItem('todos', JSON.stringify(newTodos));
setInput('');
};
const toggleTodo = (id) => {
const updated = todos.map(t =>
t.id === id ? { ...t, done: !t.done } : t
);
setTodos(updated);
localStorage.setItem('todos', JSON.stringify(updated));
};
return (
<div class="app">
<h1>Preact Todos</h1>
<div class="input-group">
<input
type="text"
value={input}
onInput={(e) => setInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && addTodo()}
placeholder="Add a todo..."
/>
<button onClick={addTodo}>Add</button>
</div>
<ul>
{todos.map(todo => (
<li
key={todo.id}
onClick={() => toggleTodo(todo.id)}
style={{ textDecoration: todo.done ? 'line-through' : 'none', cursor: 'pointer' }}
>
{todo.text}
</li>
))}
</ul>
</div>
);
}
render(<TodoApp />, document.getElementById('root'));Use Cases
Progressive Web Applications (PWAs): Preact's minimal bundle size makes it ideal for PWAs targeting users on slow networks or low-powered devices. The fast initial load and native event handling improve Time to Interactive scores, while the library's default PWA-friendly configuration simplifies service worker integration and offline support.
Mobile-first websites and applications: When targeting mobile users with varying network conditions, Preact's 3-4 KB footprint reduces data transfer costs and accelerates first paint. E-commerce sites, news platforms, and content-heavy applications benefit from faster page loads without sacrificing component-based architecture.
Migrating from React with performance constraints: Teams with existing React codebases can use preact/compat to switch the underlying library while keeping most code unchanged. This is common in scenarios where bundle size became a bottleneck after feature growth, allowing gradual optimization without full rewrites.
Embedded widgets and third-party components: When building embeddable UI components for external sites—like chat widgets, feedback forms, or analytics dashboards—Preact's small footprint minimizes impact on host page performance. The library won't bloat the parent application's bundle or conflict with existing frameworks.
Prototyping and lightweight tools: Internal dashboards, admin panels, and developer tools often don't require React's full ecosystem. Preact provides sufficient component abstractions with hooks and state management while keeping build times fast and deployment bundles lean, making it suitable for projects where simplicity matters more than advanced features.
Pros & Cons
Pros
- +Extremely small bundle size (3-4 KB gzipped) dramatically improves load times and Core Web Vitals scores, especially on mobile and slow networks
- +Native event system using addEventListener provides better performance and DOM standards compliance without synthetic event overhead
- +First-class Signals support enables fine-grained reactivity and optimal rendering performance for state-heavy applications
- +High React compatibility via preact/compat allows leveraging much of React's ecosystem with minimal code changes
- +Faster runtime performance for simple to medium-complexity applications compared to React's heavier abstractions
Cons
- −Smaller ecosystem means fewer Preact-specific libraries, tutorials, and community solutions compared to React's massive ecosystem
- −Lacks advanced features like concurrent rendering, automatic batching optimizations, and Server Components available in modern React
- −Some React libraries require preact/compat shim and may have subtle behavioral differences or incomplete compatibility
- −Less sophisticated developer tools compared to React DevTools, making complex debugging and performance profiling more challenging
- −Event system differences (native vs synthetic) can cause subtle bugs when porting React code that relies on specific event bubbling behavior
Install
npm install preactpnpm add preactbun add preact