文档
Preact 入门教程:从 React 到 Preact 无缝迁移
一、Preact 是什么?
Preact 是 Jason Miller 创建的 React 替代品,核心目标:用 3KB 的体积实现 React 的绝大部分 API。它保持与 React 几乎相同的编程模型(组件、Hooks、JSX),但去掉了合成事件系统、Fiber 调度器等大型内部机制,直接使用原生 DOM 事件和微任务调度。
为什么选择 Preact?
| 场景 | 推荐 |
|---|---|
| 移动端 H5 / 嵌入式 WebView | ✅ 体积敏感场景 |
| Widget / 微前端组件 | ✅ 独立部署,3KB 几乎可忽略 |
| 从 React 渐进迁移 | ✅ compat 模式无缝兼容 |
| 学习 React 前的过渡 | ✅ API 相同,概念更简单 |
二、从 React 迁移
方案 A:直接使用 preact/compat
最简单的方式——改两行 import + alias:
npm install preact
// vite.config.js
import preact from "@preact/preset-vite";
export default {
plugins: [preact({
aliases: [
{ find: "react", replacement: "preact/compat" },
{ find: "react-dom", replacement: "preact/compat" },
{ find: "react/jsx-runtime", replacement: "preact/jsx-runtime" },
],
})],
};
不改任何组件代码,React 项目直接运行在 Preact 上,体积减少约 100KB。
方案 B:逐文件替换 import
- import { useState } from "react";
+ import { useState } from "preact/hooks";
- import { render } from "react-dom";
+ import { render } from "preact";
三、API 兼容性
完全兼容
useState、useEffect、useRef、useContext、useReducer、useMemo、useCallbackcreateContext、Fragment、memo、createPortal- 所有 HTML 属性和事件处理
需要 compat 层
Suspense/lazy:Preact 原生支持但行为略有差异,compat 层提供完全匹配useId、useSyncExternalStore、useInsertionEffect:仅 compat 层createRootAPI(React 18):仅 compat 层
Preact 独有特性
import { render } from "preact";
// render 可以直接在 body 上(React 不允许)
render(<App />, document.body);
四、Preact Signals(可选状态管理)
Preact 团队也开发了 Signals,与 Solid.js 类似的细粒度响应式:
npm install @preact/signals
import { signal, computed, effect } from "@preact/signals";
const count = signal(0);
const double = computed(() => count.value * 2);
// 组件中直接使用,无需 useState
function Counter() {
return (
<div>
<p>{count.value} / {double.value}</p>
<button onClick={() => count.value++}>+1</button>
</div>
);
}
effect(() => {
console.log("count 变了:", count.value);
});
五、打包优化
对比体积(gzip)
| React + ReactDOM | Preact | Preact + compat | |
|---|---|---|---|
| 大小 | ~42KB | ~3KB | ~4.5KB |
| 相比 React | 100% | 7% | 11% |
实际项目节省
一个中等规模的 React 项目迁移到 Preact 后,vendor bundle 通常从 130KB 降至 90KB 左右(包含依赖库)。
六、注意事项
- 合成事件差异:Preact 使用原生 DOM 事件,
event.currentTarget行为一致,但某些边缘情况(如onChange触发时机)有细微差异 - React DevTools:Preact 有独立 DevTools 扩展,也可通过 compat 兼容 React DevTools
findDOMNode不支持,请使用 ref- React 18 的并发特性(
useTransition、useDeferredValue)Preact 原生不支持
七、思考题
- 为什么 Preact 能只用 3KB 做到 React 大部分功能?它省略了什么?
- 什么类型的项目不适合用 Preact 替代 React?
- Preact Signals 和 useState 在性能上有什么本质区别?