今天给大家带来的主题是 InfernoJS,即一个速度极快、类似 React 的库,用于在客户端和服务器上构建高性能用户界面。话不多说,直接进入正题!
1.什么是 InfernoJS
InfernoJS 是一个速度极快、类似 React 的库,用于在客户端和服务器上构建高性能用户界面。InfernoJS 项目的主要目标是为 Web 应用程序提供最快的运行时性能(几乎与原生 JS 持平),尤其擅长渲染实时数据界面或大型 DOM 树。
同时,InfernoJS 性能是通过多重优化实现的,例如:
- InfernoJS 基于自己的 JSX 插件创建单态(monomorphic) createVNode 调用,而不是 createElement
- InfernoJS 的 diff 过程使用按位标志来记忆对象的形状
- 仅在需要时对子节点进行标准化
- 在编译时使用特殊的 JSX 标志来优化应用程序级别的运行时性能
- 许多微观优化
目前 InfernoJS 在 Github 上通过 MIT 协议开源,有超过 16k 的 star、0.7k 的 fork、10k 的项目依赖量、代码贡献者 200+,是一个值得关注的前端优质开源项目。
2.InfernoJS 有什么特点
InfernoJS 具有以下明显特征:
- 组件驱动+单向数据流架构、同时采用类似 React 的 API、概念和组件生命周期事件
- 部分合成事件系统(synthetic event system),标准化事件以获得更好的跨浏览器支持
- InfernoJS 的 linkEvent 功能消除了使用箭头函数或绑定事件回调的需要
- 通过 inferno-server 在客户端和服务器上实现同构渲染
- 与 React 和 Preact 不同,InfernoJS 在函数组件上有生命周期事件、支持用于 input/select/textArea 元素的受控组件
- 可以使用 createPortal API 在当前 html 层次结构之外渲染组件,同时支持旧版浏览器,无需任何 polyfills
- 函数组件的 defaultHooks,这样可以避免每次使用时重新定义生命周期事件
- InfernoJS 支持使用字符串 或使用对象文字语法 设置样式
- 从 v6 版本开始支持 Fragment、createRef 和 forwardRef API (v6),而 v8 版本开始支持 componentDidAppear、componentWillDisappear 和 componentWillMove ,类和函数组件回调以简化动画工作。
3.InfernoJS 与其他框架不同
3.1 InfernoJS 与 React
根据 InfernoJS 的官方描述,InfernoJS 和 React 的不同主要包含以下几个核心点:
- Inferno 没有像 React 那样的完全合成的事件系统(Fully Synthetic Event System),Inferno 只有一个部分合成的事件系统。
- Inferno 不支持 React Native, Inferno 仅为考虑到 DOM 的浏览器/服务器而设计。
- Inferno 不支持旧字符串引用,请使用 createRef 或回调 ref API
- Inferno 提供函数组件的生命周期事件, 对于那些喜欢轻量级组件而不是 ES2015 类的人来说,这是一个重大的利好。
- Inferno 样式是使用 CSS 属性名称 [background-color: blue] 而不是 [backgroundColor: blue] 设置的。 通过 inferno-compat 包支持驼峰命名风格。
3.2 InfernoJS 与 Preact
根据 InfernoJS 的官方描述,InfernoJS 和 Preact 的不同主要包含以下几个核心点:
- Inferno 有一个部分合成事件系统,通过委托某些事件来获得更好的性能。
- Inferno 在渲染、更新和从 DOM 中删除元素方面比 Preact 快得多。
- Inferno 完全支持“input”/“select”/“textarea”元素的受控组件,从而可以防止出现许多边界情况。 Preact 将事实来源推向 DOM 本身。
- Inferno 提供函数组件的生命周期事件,对于那些喜欢轻量级组件而不是 ES2015 类的人来说,这是一个重大利好。
4.InfernoJS 的性能表现
InfernoJS框架最引以为傲的就是独特的性能优势,接下来一起看看 InfernoJS 在多个性能对比测试中的数据表现。当然,对于性能的对比数据大家需要辩证的来看,毕竟框架只是决定应用性能的一部分,还有很大一部分依赖于写业务代码的实际开发者。
4.1 客户端/服务端渲染
该基准测试由 Marko.js 创建,用于比较各种框架的客户端渲染性能 ,数字显示每秒操作数,越高越好。
从上图来看,InfernoJS 一骑红尘,超过了 Marko.js、Preact、React、Vue 等一众前端热门框架。
在服务端渲染方面,InfernoJS 稍逊于 Marko.js,但是依然遥遥领先 Preact、React、Vue 等框架。
4.2 JS 框架对比
js-framework-benchmark 是一个简单的基准测试,比较了几个 JavaScript 框架的各种典型应用程序操作。 基准测试创建一个包含随机条目的大表,并测量各种操作的时间 ,数字越低越好。
如上图所示,在框架性能对比上,InfernoJS 仅次于 Vanilla JS、远远高于其他前端顶级框架,比如:Vue、Svelte、Preact、Angular、Marko.js、React 等等。
4.3 UI 渲染
UI Benchmark 被认为是对库中整体 UI 性能的更准确测试。 测试在启用完整渲染时间和 5 次迭代的情况下运行。 在得出进一步的结论之前,请阅读 UI Benchmark 的注意事项和规定 , 数字越低越好。
结果表明,在 UI 渲染性能上,InfernoJS 依然是排名第一,比 Vanilla JS、React、Preact、DIO、ivi 等更快。
5.使用 InfernoJS
正如上面所说,Inferno 在组件设计方面有意保留了与 React 相同的设计思想,即单向数据流和关注点分离。
在下面的示例中,通过 Inferno JSX Babel 插件使用 JSX 来提供表达 Inferno 虚拟 DOM 的简单方法。 不需要强制开发者使用 JSX,还可以使用诸如 hyperscript 或 createElement 等方法 (就像 React 一样)。 但是请记住,编译时优化仅适用于 JSX。
import { render } from "inferno";
const message = "Hello world";
render(<MyComponent message={message} />, document.getElementById("app"));
此外,Inferno 还使用了像 React 这样的 ES6 组件:
import { render, Component } from "inferno";
class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0,
};
}
render() {
return (
Header!
Counter is at: {this.state.counter}
);
}
}
render( , document.getElementById("app"));
由于性能是 InfernoJS 的一个重要方面,因此下面示例展示如何进一步优化应用程序。
在下面的示例中,通过使用 JSX $HasVNodeChildren 和 $HasTextChildren 来预定义子形状编译时间来优化比较过程。 在 MyComponent 渲染方法中,有一个包含 JSX 表达式节点作为其内容的 div。 由于 Javascript 的动态特性,变量节点可以是任何东西,Inferno 需要经历规范化过程以确保没有嵌套数组或其他无效数据。
Inferno 提供了一个名为 ChildFlags 的功能,供应用程序开发人员预先定义 vNode 子节点的形状。 在此示例中,它使用 $HasVNodeChildren 告诉 JSX 编译器,该 vNode 仅包含单个元素或组件 vNode。
import { createTextVNode, render, Component } from "inferno";
class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0,
};
}
_getText() {
return "Hello!";
}
render() {
const node =
this.state.counter > 0 ? (
0
) : (
{this._getText()}
);
return (
Header!
{node}
);
}
}
render( , document.getElementById("app"));
要卸载 inferno 应用程序,开发者需要在根元素上渲染 null。 渲染 null 将触发整个 vDOM 树的卸载生命周期 Hooks 并删除全局事件侦听器。 卸载未使用的 vNode 树以释放浏览器内存非常重要。
import { createTextVNode, render, Component } from "inferno";
const rootElement = document.getElementById("app");
// Start the application
render( , rootElement);
// Tear down
render(null, rootElement);
关于 InfernoJS 的更多示例可以参考文末资料,本文不再过度展开。
参考资料
https://www.InfernoJS.org/
https://github.com/InfernoJS/inferno
https://www.zhihu.com/question/65824137/answer/235159117
https://survivejs.com/blog/inferno-interview/
https://www.InfernoJS.org/benchmarks
https://InfernoJS.github.io/inferno/
https://www.InfernoJS.org/docs/guides/alternatives-to-jsx
发表评论
评论列表(0)