什么是 React 的替代品呢?
就是在语法和操作上都类似于 React 的框架或库,但它们可能具有 React 没有的某些功能。
React 的替代品有很多,比如 Preact、Solid 和 Inferno。这次我和大家聊聊 Preact。
什么是 Preact?
Preact 是一个和 React 类似的用于构建用户界面 (UI) 的前端库。
根据官方文档介绍,Preact 是「具有和 React 相同 API 的快速 3kb 替代方案」。
Preact 的特性与 React 几乎完全相同,它同样使用虚拟 DOM、Context、Hooks 等概念。
在本文中,我们将深入了解 Preact 的世界。我将带你了解为什么创建这个库,它是如何工作的,以及它与 React 的比较。我还将讨论是否应该使用 Preact。
在开始之前,我要声明本文不是介绍 Preact 的教程。Preact在他们的网站上提供了一个很好的教程。本文着重比较 React 和 Preact,来帮助你在为项目选择框架时做出合适的决定。
现在我们开始吧。
Preact 的由来
Preact 是由加拿大软件开发人员 Jason Miller 开发的。他曾经有一个演讲,主题是「Putting the P in Preact」。在演讲中,Jason 表示他已经为 Web 构建了许多 UI 框架/模板引擎。
Jason 永远无法构建一个完美的框架来支持他想要的一切。他一直遇到与文档对象模型 (DOM) 相关的问题。然后他发现 JSX 和 React,这两者满足了他的需求和他想要的框架。
当 Jason 找到这个解决方案时,他的下一步就是学习 React。为了学习 React,他创建了一个项目来模拟 React 具体的 API 和工作方式。
Preact 最初是一个 Codepen 上面的项目,它可以像 React 一样呈现数百个 DOM 元素。Jason 不断优化这个程序并添加新的功能。有一天,他在真实的设备中对这个项目进行了性能测试。他得到的结果非常好,而且比 React 快得多。速度非常接近纯 JavaScript。
根据 「Putting the P in Preact」 的演讲,Jason 继续开发这个项目。他将它变成了一个库,供那些因为性能不佳而不喜欢 React 的开发人员使用。Preact 拥有几乎和 React 完全相同的功能,但是它更轻、更快。Github 上库的第一个版本(v2.0.0)可追溯到 2015 年 11 月 13 日。
从那时起,Preact 社区一直在与用户、贡献者和维护者一起成长。
Preact 是如何工作的?
Preact 的工作原理与 React 非常相似,但它对 React 的许多功能进行了单独的实现。接下来,我们将研究 Preact 的核心功能,我把它们分为三类:
- 虚拟 DOM
- 无需构建工具
- 适合嵌入式
虚拟 DOM
DOM 表示任何 HTML 文档中元素的层次结构。网页上的每个元素几乎都是建立在 DOM 上的。而虚拟 DOM 就是真实 DOM 的一种映射。
大多数 UI 框架都会使用虚拟 DOM,这是因为使用 JavaScript 更新真实 DOM 时渲染速度较慢。这对于动态 Web 应用程序来说是一个大的性能问题,因为它们需要不断更新元素。
根据 Codecademy 的介绍,React 中使用虚拟 DOM 的渲染过程包含以下阶段:
- 整个虚拟 DOM 都会更新。
- 将新的 Virtual DOM 与更新前的 Virtual DOM 进行比较。React 计算出变化的元素(这个过程也称为Diffing)。
- React 只会更新真实 DOM 上需要更新的元素(此过程也称为 reconciliation)。
- 页面的内容被更新。
Preact 没有像 React 那样实现虚拟 DOM。
在 Preact 的文档网站上有一段介绍:
“Preact 在 DOM 之上提供了最薄的虚拟 DOM 抽象。它建立在稳定的平台特性之上,并且会注册真实事件,并且能够和其他库进行很好地配合。”
简单来说,这意味着 Preact 的虚拟 DOM 只会处理真实 DOM 发现耗时的进程。Preact 有效地使用虚拟 DOM,不像 React,它将每个任务交给虚拟 DOM。
Preact 也不使用合成事件,它是普通 DOM 事件对象的抽象。相反,Preact 会使用元素的真实事件。这使得 Preact 的虚拟 DOM 更小,性能更高。\
无需构建工具
构建工具是为开发人员执行重复任务并节省时间的一系列工具链。
构建工具的类型包括 CSS 预处理器、lint 工具、编译器、打包器、图像压缩器等等。
与其他前端框架一样,React 同样依赖底层的构建工具来处理代码,构建出可以在生产环境运行的文件。
尽管构建工具在开发过程中有很多帮助,但它们会增加项目的复杂性。开发人员不得不去处理各种各样的配置文件,或者要花大量的时间去学习如何使用新的工具。
Preact 的设计理念是开发完成后直接部署到生产环境,不需要构建工具也可正常运行。
Preact 可以通过将 JS 导入到 HTML 中来开发一个简单的 Preact 应用。
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Simple Preact App</title> </head> <body> <script type="module"> import { h, Component, render } from 'https://unpkg.com/preact?module'; // 创建应用 function App() { return h('h1', null, 'Hello World!'); } render(App(), document.body); </script> </body> </html>
从示例代码中可以看出,因为 App 是一个返回 h1 元素的 JS 函数,所以只需要将该函数作为 render 函数的参数调用就可以了。
我们把 app 声明为变量,也同样有效。
<script type="module"> import { h, Component, render } from 'https://unpkg.com/preact?module'; const app = h('h1', null, 'Hello World!'); render(app, document.body); </script>
但是,在 Preact 中使用 JSX,仍然需要一个构建步骤。
Preact 提供了一个替代 JSX 的方案,它具有和 htm 类似的功能和语法,但不需要构建步骤。
本文后面会讨论它。
适合嵌入式
HTML 中有一个 iframe 标签,可以让特定的网站嵌入到另一个网站上进行显示。
将网站嵌入其他网站的场景很多,它的主要用途是显示主网站不支持的内容(视频、游戏、音乐、地图等)。
但是通常对嵌入式的性能要求很高。
而 Preact 体积小、性能强。这就是为什么 Preact 适合嵌入式的原因。
Preact 与 React 的差异?
这一部分我们将在一些标准维度上来比较这两个框架。
在为项目选择框架/库时,这些标准的比较是必不可少的。
- 语法
- 体积
- 性能
- 人气
语法
比较 Preact 和 React 的语法,下面是一些区别。
- 将 State 和 Props 传递给 Render 方法
在 Preact 中,类组件的 render 方法可以接受 props 和 states。但是在 React 中,render 方法不接受任何参数。
render(props, state) { // 返回一个组件 }
- 在组件中使用class代替className
我们可以 在 Preact中使用class 代替 className,同时也支持 className。
function Hello(){ return ( <h1 class='hello-box'>Hello World!</h1> ); }
- 创建组建的方式。
在 Preact 中,可以通过三种不同的方式创建组件。
JSX
function JsxComponent(props) { return ( <h1>I am rendered with JSX</h1> ) }
h 函数或者 createElement 函数
import { h } from 'preact'; function HComponent(props) { return h('h1', null, 'I an rendered with h') }
使用 htm 库。
import { h, render } from 'preact'; import { htm } from 'htm'; // Initialize htm with Preact const html = htm.bind(h); function HtmComponent(props) { return ( html`<h1>I am rendered with HTM</h1>` ) }
React 通常只能通过前两种方式创建组件。
在 Preact 中创建组件的灵活性稍高一些。
体积
虽然 Preact 的网站上说它是一个只有 3kb 大小的库。
但是在 Bundlephobia 的报告中说,Preact 经过 Minified + Gzipped 压缩后体积为 4kb。
package-size 的结果也是 4kb。
这个现象的原因可能是最近的更新增加了源代码大小。
但是,Preact 通过定期删除不推荐使用的功能或将一些 API 放到单独的模块中来始终保持 4kb 以下的体积。
考虑到使用 React 需要超过 40kb 的内存,Preact 这么小实在是让人惊讶。
一个 React 应用最少需要 2.5kb 的 React 和 42 kb 的 react-dom。(同样经过 Minified + Gzipped)
性能
速度是选择框架时需要考虑的一个重要因素。
我将使用 Stefan Krause 这个 Javascript 框架基准工具来对 Preact 与 React 进行比较。
主要测试了三个指标,分别是:
- 持续运行时间:持续运行时间可以确定框架在页面上渲染和重新渲染所需的毫秒数。我分配给框架的任务是在表格中创建 1000 行、更新表的 1000 行、将 1000 行追加到 10000 行的表中,等等。虽然 React 似乎很快,但 Preact 在这项比较中的平均表现优于 React。这意味着,从平均数据而言,Preact 更新 DOM 的速度更快。
- 启动指标:这是使用 Lighthouse 测试的,并在移动设备上模拟网站。它会运行有关框架如何正确利用 CPU 的测试。还会衡量生产环境中框架的构建大小。这两个框架在这项测试中都表现良好,但 Preact 仍然击败了 React。
- 内存分配:这测量了框架在浏览器会话中使用的内存大小。内存以兆字节 (MB) 为单位。测量页面加载后的内存使用量、添加 1000 行后的内存使用量、创建 1000 行五次后的内存使用量等。平均来看,Preact 在所有场景中的性能都略好于 React。
人气
最后一个要考虑的因素是受欢迎程度。受欢迎程度决定了开发人员在项目碰到问题时可以获得多少帮助。
在最后一次 State of JS 调查中,Preact 在前端框架的认知度中排名第六(80%)。大多数受访者都听说过这个框架。
在实际使用中,只有 14% 的受访者在使用 Preact。
在兴趣和满意度中,Preact 每一年都在下降。
最后是 NPM 每周下载量和 GitHub 的 star 数。
- Preact
- Github star 数:32K
- NPM 下载:1.4M
- React
- Github start 数:194K
- NPM 下载:16.2M
总结
在本文中,我们详细对比了 Preact 和 React。
我们首先了解了 Preact 框架是如何产生的,然后我们研究了框架的特性。我们还在各个维度中与 React 进行了比较。
Preact 的小体积和高运行速度相对于 React 和 React DOM 来说确实是优势。
如果你要开发一个更轻量级的项目,或者开发的是一个运行在嵌入式环境中的网站,你可以尝试使用 Preact。