ADR-031: Preact Over React for Islands
Documents the decision to use Preact rather than React as the islands framework, covering bundle size rationale, React compat layer, and when users should consider switching.
Last updated
Status
Accepted
Context
Astro supports multiple UI frameworks for islands. The starter ships with @astrojs/preact as the default. This is not self-evident — React is far more widely known. This ADR documents why Preact was chosen and how users can still access the React ecosystem without switching.
Bundle Size: The Primary Reason
| Framework | Runtime (gzipped) |
|---|---|
| Preact | ~3KB |
| Preact + compat | ~5KB |
| React + ReactDOM | ~45KB |
| Vue 3 | ~22KB |
| SolidJS | ~7KB |
With a 160KB total JS budget and a zero-JS baseline, React would consume ~28% of the entire budget before any application code. Preact costs ~2% of the same budget. For a performance-first starter this difference is the entire value proposition.
React Compatibility via preact/compat
The most important thing to understand: Preact ships a full React compatibility layer.
preact/compat implements the complete React API. To use React component libraries with Preact, add these aliases to astro.config.mjs:
vite: { resolve: { alias: { react: 'preact/compat', 'react-dom': 'preact/compat', 'react-dom/server': 'preact/compat/server', }, },},With these aliases in place:
- React hooks (
useState,useEffect,useContext,useRef, etc.) work identically - JSX syntax is unchanged
forwardRef,createContext,memo,lazy,Suspenseall work- Most React component libraries (Radix UI, Headless UI, React Hook Form, etc.) work without modification
- The bundle cost increases from ~3KB to ~5KB — still 9x smaller than React
Considered Options
Option 1: React (standard)
Pros: Largest ecosystem, most familiar to developers, best IDE tooling, most third-party components
Cons: ~45KB runtime gzipped — incompatible with performance budget goals for a starter that defaults to zero JS
Option 2: Preact with compat (chosen)
Pros: ~3-5KB runtime, full React API compatibility, access to React ecosystem via aliases, identical JSX syntax
Cons: Less familiar name, occasional edge-case incompatibilities with React libraries that use internal React APIs
Option 3: Svelte
Pros: Smallest compiled output, no shared runtime
Cons: Different syntax (not JSX), no React ecosystem compatibility, steeper learning curve for React developers
Option 4: No islands framework (CSS-only)
Pros: True zero JS
Cons: Eliminates all interactive island capability — too restrictive for a general-purpose starter
When to Switch to React
Users should consider switching from Preact to React if:
- A required library uses React internal APIs not covered by
preact/compat(rare but possible with some animation libraries) - The project’s JS budget is not a concern (e.g. a full SPA built on top of the starter)
- The team has strong React expertise and the compat aliases cause confusion
To switch, replace @astrojs/preact with @astrojs/react in astro.config.mjs and package.json, and remove the compat aliases.
Decision
Use Preact as the default islands framework. Document preact/compat aliases prominently so users understand they have full React ecosystem access. This is not a limitation — it is a deliberate performance optimisation that costs nothing in API compatibility.
Consequences
Positive
- ~3KB islands runtime vs ~45KB for React — 15x smaller
- Full React API available via
preact/compat - Most React component libraries work without modification
- Consistent with zero-JS philosophy — JS additions are minimal and justified
Negative
- Developers unfamiliar with Preact may not realise React libraries work
- Rare incompatibilities with libraries using React internals (e.g. some versions of React Spring, Framer Motion)
- IDE error messages may reference Preact types rather than React types
Neutral
- JSX syntax is identical — no learning curve for React developers
preact/compataliases are opt-in, not configured by default in the starter (to avoid confusion for users who don’t need them)
Planned Work
Add a guide to docs/patterns/ documenting how to configure preact/compat aliases and which popular React libraries have been tested.
Status: Not yet implemented. The
docs/patterns/directory exists but does not yet contain apreact/compatguide.
References
Date: 2026-02-18
Participants: Template maintainers
Outcome: Accepted