自研框架跻身全球 JS 框架榜单,排名紧随 React、Angular 之后!

本文主要是介绍自研框架跻身全球 JS 框架榜单,排名紧随 React、Angular 之后!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

终于实现了一个重要目标!我独立研发的 JavaScript 框架 Strve,最近发布了重大版本 6.0.2。距离上次大版本发布已经接近两个月,期间进行了大量的优化,使得框架性能和稳定性都得到了大幅度的提升。在上次的大版本更新中,成功实现了对 JSX 语法的全面支持,使得 Strve 在代码智能提示和代码格式化方面更加友好,进一步提高了开发效率。

介绍

相信有些小伙伴没有听说过 Strve 到底是什么,那我这里就大体介绍一下。

Strve 是一个可以将字符串转换为视图(用户界面)的 JavaScript 库。Strve 不仅易于使用,而且可以灵活地拆解不同的代码块。使用模板字符串开发用户界面,主要是利用 JavaScript 的能力,只关注 JavaScript 文件。Strve 又是一个易用性的 JavaScript 框架,它提供了很多实用的功能与生态工具。

我们可以通过一些简单的示例来了解 Strve 的使用方法。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>Strve.js</title></head><body><script src="https://cdn.jsdelivr.net/npm/strve-js@6.0.2/dist/strve.full.prod.js"></script><script>const { html, setData, createApp } = Strve;const state = {count: 0,};function add() {setData(() => {state.count++;});}function App() {return html`<h1 onClick=${add}>${state.count}</h1>`;}const app = createApp(App);app.mount('#app');</script></body>
</html>

在上述代码中,我们通过引入 Strve 库,并使用 createApp 方法创建了一个 App 组件,然后通过 mount 方法挂载到页面上,这里的 App 组件就是通过模板字符串来定义的。这样就可以在 JS 代码中编写用户界面,是不是很方便呢?我们发现,在模板字符串中,我们使用 ${} 来引用数据,并且使用 onClick 方法来绑定事件。这样就可以实现一个计数器的功能。

除了这种简单的示例,Strve 还支持很多复杂的功能,我们可以使用 JSX 语法来编写组件,也可以使用函数式组件来编写组件,还可以使用组件来编写组件,甚至可以编写一些自定义的组件。

如果想了解更多关于 Strve 的信息,稍后可以到文章末尾处查阅官方文档。

性能评估

我们既然发布了 Strve,那么肯定需要对其性能进行评估,我们评估的工具就用js-framework-benchmarkjs-framework-benchmark 是什么?我们这里就简单介绍下 js-framework-benchmark,它是一个用于比较 JavaScript 框架性能的项目。它旨在通过执行一系列基准测试来评估不同框架在各种场景下的性能表现。这些基准测试包括渲染大量数据、更新数据、处理复杂的 UI 组件等。通过运行这些基准测试,可以比较不同框架在各种方面的性能优劣,并帮助开发人员选择最适合其需求的框架。js-framework-benchmark 项目提供了一个包含多个流行 JavaScript 框架的基准测试套件。这些框架包括 Angular、React、Vue 等。每个框架都会在相同的测试场景下运行,然后记录下执行时间和内存使用情况等性能指标。通过比较这些指标,可以得出不同框架的性能差异。这个项目的目标是帮助开发人员了解不同 JavaScript 框架的性能特点,以便在选择框架时能够做出更加明智的决策。同时,它也可以促进框架开发者之间的竞争,推动框架的不断改进和优化

在评估之前,我们必须要了解 js-framework-benchmark 中有两种模式。一种是 keyed,另一种是 non-keyed。在 js-framework-benchmark 中,“keyed” 模式是指通过给数据项分配一个唯一标识符作为 “key” 属性,从而实现数据项与 DOM 节点之间的一对一关系。当数据发生变化时,与之相关联的 DOM 节点也会相应更新。而 non-keyed 模式是指当数据项发生变化时,可能会修改之前与其他数据项关联的 DOM 节点。

因为 Strve 支持keyed模式,所以我们将使用此模式来评估 Strve 的性能。

对以下操作进行了基准测试:

  • 创建行:页面加载后创建 1,000 行的持续时间(无预热)。
  • 替换所有行:替换表中所有 1,000 行的持续时间(5 次预热迭代)。
  • 部分更新:对于具有 10,000 行的表,每 10 行更新一次文本(进行 5 次预热迭代)。
  • 选择行:响应单击该行而突出显示该行的持续时间。 (5 次预热迭代)。
  • 交换行:在包含 1,000 行的表中交换 2 行的时间。 (5 次预热迭代)。
  • 删除行:删除具有 1,000 行的表的行的持续时间。 (5 次预热迭代)。
  • 创建多行:创建 10,000 行的持续时间(无预热)
  • 将行追加到大型表:在包含 10,000 行的表中添加 1,000 行的持续时间(无预热)。
  • 清除行:清除填充有 10,000 行的表的持续时间。 (无热身)
  • 就绪内存:页面加载后的内存使用情况。
  • 运行内存:添加 1,000 行后的内存使用情况。
  • 更新内存:1000 行的表点击 5 次更新后的内存使用情况。
  • 替换内存:点击 5 次创建 1000 行后的内存使用情况。
  • 重复清除内存:创建并清除 1,000 行 5 次后的内存使用情况。
  • 更新内存:1000 行的表点击 5 次更新后的内存使用情况。
  • 启动时间:加载和解析 javascript 代码以及渲染页面的持续时间。
  • 持续交互:灯塔指标 TimeToConstantlyInteractive:悲观 TTI - 当 CPU 和网络都非常空闲时。 (不再有超过 50 毫秒的 CPU 任务)
  • 脚本启动时间:灯塔指标 ScriptBootUpTtime:解析/编译/评估所有页面脚本所需的总毫秒数
  • 主线程工作成本:灯塔指标 MainThreadWorkCost:在主线程上工作所花费的总时间包括样式/布局等。
  • 总字节权重:灯塔指标 TotalByteWeight:加载到页面中的所有资源的网络传输成本(压缩后)。

对于所有基准测试,都会测量持续时间,包括渲染时间。

因为js-framework-benchmark是一个自动化测试的工具,只需要符合标准的代码就可以进行测试。Strve 支持 JSX 语法,所以我们将使用 JSX 语法来编写测试代码。

import { setData, createApp } from 'strve-js';
import { buildData } from './data.js';let selected;
let rows = [];function setRows(update = rows.slice()) {setData(() => {rows = update;},{name: TbodyComponent,});
}function add() {const data = rows.concat(buildData(1000));setData(() => {rows = data;},{name: TbodyComponent,});
}function remove(id) {rows.splice(rows.findIndex((d) => d.id === id),1);setRows();
}function select(id) {setData(() => {selected = id;},{name: TbodyComponent,});
}function run() {setRows(buildData());selected = undefined;
}function update() {for (let i = 0; i < rows.length; i += 10) {rows[i].label += ' !!!';}setRows();
}function runLots() {setRows(buildData(10000));selected = undefined;
}function clear() {setRows([]);selected = undefined;
}function swapRows() {if (rows.length > 998) {const d1 = rows[1];const d998 = rows[998];rows[1] = d998;rows[998] = d1;setRows();}
}function TbodyComponent() {return (<tbody>{rows.map((item) => (<tr class={item.id === selected ? 'danger' : ''} data-label={item.label} key={item.id}><td class='col-md-1'>{item.id}</td><td class='col-md-4'><a onClick={() => select(item.id)}>{item.label}</a></td><td class='col-md-1'><a onClick={() => remove(item.id)}><span class='glyphicon glyphicon-remove' aria-hidden='true'></span></a></td><td class='col-md-6'></td></tr>))}</tbody>);
}function MainBody() {return (<fragment><div class='jumbotron'><div class='row'><div class='col-md-6'><h1>Strve-keyed</h1></div><div class='col-md-6'><div class='row'><div class='col-sm-6 smallpad'><button type='button' class='btn btn-primary btn-block' id='run' onClick={run}>Create 1,000 rows</button></div><div class='col-sm-6 smallpad'><buttontype='button'class='btn btn-primary btn-block'id='runlots'onClick={runLots}>Create 10,000 rows</button></div><div class='col-sm-6 smallpad'><button type='button' class='btn btn-primary btn-block' id='add' onClick={add}>Append 1,000 rows</button></div><div class='col-sm-6 smallpad'><buttontype='button'class='btn btn-primary btn-block'id='update'onClick={update}>Update every 10th row</button></div><div class='col-sm-6 smallpad'><button type='button' class='btn btn-primary btn-block' id='clear' onClick={clear}>Clear</button></div><div class='col-sm-6 smallpad'><buttontype='button'class='btn btn-primary btn-block'id='swaprows'onClick={swapRows}>Swap Rows</button></div></div></div></div></div><table class='table table-hover table-striped test-data'><component $name={TbodyComponent.name}>{TbodyComponent()}</component></table><span class='preloadicon glyphicon glyphicon-remove' aria-hidden='true'></span></fragment>);
}createApp(() => MainBody()).mount('#main');

以下页面就是将进行基准测试的页面:

在这里插入图片描述
我们大体看下测试过程,我们将使用动图来展示页面效果,这样会觉得更加直观。

在这里插入图片描述

最终,Strve 通过了压力测试!

在这里插入图片描述

基准测试结果

既然我们通过测试,我们就需要提交到js-framework-benchmark官方项目中,进行综合评估,与全球其他框架进行比较。

我们提交的 PR 在 2023 年 9 月 18 号被作者合并了。

在这里插入图片描述

在接下来的时间里,作者进行了一系列的测试。最终,Chrome 118 版本于上周发布,并在 GitHub 上公布了官方的测试结果。

在这里插入图片描述

我们打开下面的网址,看下 Strve 的官方测试结果:

https://krausest.github.io/js-framework-benchmark/2023/table_chrome_118.0.5993.70.html

经过查询,全球 JavaScript 框架榜单中共有 142 个框架。

性能测试基准分为三类:

  • 持续时间
  • 启动指标
  • 内存分配

【持续时间】

在此测试基准中,Strve 平均值 1.42,排名第 90 位。

React、Angular 和 Vue,平均值分别为1.401.381.20,分别排名第 85 位、第 83 位和第 51 位。

平均值越小,排名则越靠前。颜色越绿代表越优。

在这里插入图片描述

【启动指标】

在此测试基准中,Strve 平均值 1.07

React、Angular 和 Vue,平均值分别为 1.681.801.30

平均值越小,排名则越靠前。颜色越绿代表越优。

在这里插入图片描述

【内存分配】

在此测试基准中,Strve 平均值 1.33

React、Angular 和 Vue,平均值分别为 2.462.821.86

平均值越小,排名则越靠前。颜色越绿代表越优。

在这里插入图片描述

新特性

我们在上面的测试中,可以看到 Strve 性能表现非常不错。

这次我们发布的大版本号为 6.0.2,我们将这个具有里程碑意义的大版本命名为 Strve6,而 “Strve6,从芯出发!” 这个口号正是 Strve6 的核心理念。这一版本象征着我们从底层技术出发,致力于为用户提供更优质、更高效的开发体验。

此次版本我们在性能与体验之间做了权衡。在源码层面,我们将普通 Diff 算法升级为 双端 Diff 算法,大大提升了性能。另外,我们在用户体验层面也做了很大的改进。

这里,我们提到了双端 Diff 算法,我们在面试中经常提到这个概念,但是很少用到实际项目中去。那么,为了更好地理解双端 Diff 算法如何提高性能,我们来看一个关于 Strve 简单的示例。

我们来遍历一个数组,并且每次点击按钮,往数组头部中添加一个元素。

【普通 Diff 算法】

<script type="module">import {html,setData,createApp,} from 'https://cdn.jsdelivr.net/npm/strve-js@6.0.2/dist/strve.full-esm.js';const state = {arr: [1, 2],count: 3,};function useUnshift() {setData(() => {state.count++;state.arr.unshift(state.count);});}function App() {return html`<fragment><button onClick=${useUnshift}>Unshift</button><ul>${state.arr.map((todo) => html`<li>${todo}</li>`)}</ul></fragment>`;}const app = createApp(App);app.mount('#app');
</script>

我们可以看到右侧 DOM 树,每次点击按钮,都会重新渲染整个列表。这样是肯定耗损浏览器性能的。

在这里插入图片描述

【双端 Diff 算法】

<script type="module">import {html,setData,createApp,} from 'https://cdn.jsdelivr.net/npm/strve-js@6.0.2/dist/strve.full-esm.js';const state = {arr: [1, 2],count: 3,};function useUnshift() {setData(() => {state.count++;state.arr.unshift(state.count);});}function App() {return html`<fragment><button onClick=${useUnshift}>Unshift</button><ul>${state.arr.map((todo) => html`<li key=${todo}>${todo}</li>`)}</ul></fragment>`;}const app = createApp(App);app.mount('#app');
</script>

我们可以看到右侧 DOM 树,每次点击按钮,仅添加必要的元素,而不是重新渲染整个列表。这是因为我们在每个列表项中添加了 key 属性,并且这个 key 是唯一的。key 这个特殊的 attribute 主要作为 Strve 的虚拟 DOM 算法提示,在比较新旧节点列表时用于识别 vnode。只要标签类型与 key 值都相等,就说明当前元素可以被复用。

在这里插入图片描述

热门话题

文章接近尾声,让我们来回顾一下最近社区的几个热门话题。

  1. 为什么要开发这个框架?初衷是什么?

答:其实,我的动机特别简单,完全受 JSX 语法的影响。刚接触 JSX 语法的时候,就被它那种魔法深深地吸引住了,可以在 JS 中写 HTML。所以,我就想我自己可不可以也搞一个类似 JSX 语法的库或者框架呢!一方面可以锻炼自己的代码能力,另一方面体验开发框架的整个流程,也方便我以后更全面的学习其他框架(Vue.js、React.js 等)。

做自己喜欢的事情是特别有意义的!

  1. 为什么选择 Strve 作为框架的名字?

答:Strve 最初定位是可以将字符串转换为视图(用户界面)的 JavaScript 库,所以是由 StringView 两个单词缩减组成的新单词。

  1. 跟前端热门框架比较,是想超过它们吗?

答:不是,我主要是想学习一下前端热门框架的实现原理,然后自己实现一个框架。有一句话说得好:“只有站在巨人的肩膀上才能望得更远!”。

  1. 记得之前也写过登上框架榜单的文章,这次为什么还要写?

答:之前,Strve 测评的模式是使用"non-keyed"。现在,Strve 新的版本支持"keyed"模式,所以,我重新写了一篇文章,来介绍 Strve 的新特性。

  1. Strve 6.0.2 版本发布,普通 Diff 算法升级为双端 Diff 算法,可以简单讲下双端 Diff 算法的概念吗?

答:双端 diff 算法就是头尾指针向中间移动,分别判断头尾节点是否可以复用,如果没有找到可复用的节点再去遍历查找对应节点的下标,然后移动。全部处理完之后要对剩下的节点进行批量的新增和删除。

  1. Strve 是个 JavaScript 库还是 JavaScript 框架?

答:首先,我们来看下框架与库有什么区别?库更多是一个封装好的特定的集合,提供给开发者使用,而且是特定于某一方面的集合(方法和函数),库没有控制权,控制权在使用者手中,在库中查询需要的功能在自己的应用中使用,我们可以从封装的角度理解库;框架顾名思义就是一套架构,会基于自身的特点向用户提供一套相当于叫完整的解决方案,而且控制权的在框架本身,使用者要找框架所规定的某种规范进行开发。Strve 可以是框架,因为 Strve 提供了路由、插件等生态工具;Strve 也可以是库, 因为 Strve 可以单独作为一个渲染库。

  1. Strve 你还要继续维护下去吗?

答:是的,我还会继续维护下去,因为我也想学习下去,也希望能帮助到更多前端开发者。

关于

Strve 我是从 2021 年下半年开始开发,到现在也快两年了。在这两年中,从一个之前只会 调用 API 的码农,到现在可以独立开发一个框架,让我收获了很多。学习了如何去分析一个框架的实现原理,也学习了如何去设计一个框架。

Strve 源码仓库:https://github.com/maomincoding/strve

Strve 中文文档:https://maomincoding.gitee.io/strve-doc-zh/

如果大家觉得 Strve 还不错,麻烦帮我点下 Star 吧,谢谢!

结语

感谢各位读者的阅读,希望本文能对你有所帮助,如果喜欢本文,欢迎点赞,欢迎关注!

最后,分享一段话给大家:

很多时候

不是有希望才去坚持

而是在坚持的过程中慢慢看到希望

我们都是在暗夜里赶路的人

纵使满身疲惫也不肯轻言放弃

愿你所坚持的东西

终有一天反过来拥抱你

这篇关于自研框架跻身全球 JS 框架榜单,排名紧随 React、Angular 之后!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/386837

相关文章

全面解析HTML5中Checkbox标签

《全面解析HTML5中Checkbox标签》Checkbox是HTML5中非常重要的表单元素之一,通过合理使用其属性和样式自定义方法,可以为用户提供丰富多样的交互体验,这篇文章给大家介绍HTML5中C... 在html5中,Checkbox(复选框)是一种常用的表单元素,允许用户在一组选项中选择多个项目。本

HTML5 搜索框Search Box详解

《HTML5搜索框SearchBox详解》HTML5的搜索框是一个强大的工具,能够有效提升用户体验,通过结合自动补全功能和适当的样式,可以创建出既美观又实用的搜索界面,这篇文章给大家介绍HTML5... html5 搜索框(Search Box)详解搜索框是一个用于输入查询内容的控件,通常用于网站或应用程

CSS3中的字体及相关属性详解

《CSS3中的字体及相关属性详解》:本文主要介绍了CSS3中的字体及相关属性,详细内容请阅读本文,希望能对你有所帮助... 字体网页字体的三个来源:用户机器上安装的字体,放心使用。保存在第三方网站上的字体,例如Typekit和Google,可以link标签链接到你的页面上。保存在你自己Web服务器上的字

html 滚动条滚动过快会留下边框线的解决方案

《html滚动条滚动过快会留下边框线的解决方案》:本文主要介绍了html滚动条滚动过快会留下边框线的解决方案,解决方法很简单,详细内容请阅读本文,希望能对你有所帮助... 滚动条滚动过快时,会留下边框线但其实大部分时候是这样的,没有多出边框线的滚动条滚动过快时留下边框线的问题通常与滚动条样式和滚动行

Oracle修改端口号之后无法启动的解决方案

《Oracle修改端口号之后无法启动的解决方案》Oracle数据库更改端口后出现监听器无法启动的问题确实较为常见,但并非必然发生,这一问题通常源于​​配置错误或环境冲突​​,而非端口修改本身,以下是系... 目录一、问题根源分析​​​二、保姆级解决方案​​​​步骤1:修正监听器配置文件 (listener.

使用vscode搭建pywebview集成vue项目实践

《使用vscode搭建pywebview集成vue项目实践》:本文主要介绍使用vscode搭建pywebview集成vue项目实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录环境准备项目源码下载项目说明调试与生成可执行文件核心代码说明总结本节我们使用pythonpywebv

VS配置好Qt环境之后但无法打开ui界面的问题解决

《VS配置好Qt环境之后但无法打开ui界面的问题解决》本文主要介绍了VS配置好Qt环境之后但无法打开ui界面的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目UKeLvb录找到Qt安装目录中designer.UKeLvBexe的路径找到vs中的解决方案资源

使用Python获取JS加载的数据的多种实现方法

《使用Python获取JS加载的数据的多种实现方法》在当今的互联网时代,网页数据的动态加载已经成为一种常见的技术手段,许多现代网站通过JavaScript(JS)动态加载内容,这使得传统的静态网页爬取... 目录引言一、动态 网页与js加载数据的原理二、python爬取JS加载数据的方法(一)分析网络请求1

使用Python和Tkinter实现html标签去除工具

《使用Python和Tkinter实现html标签去除工具》本文介绍用Python和Tkinter开发的HTML标签去除工具,支持去除HTML标签、转义实体并输出纯文本,提供图形界面操作及复制功能,需... 目录html 标签去除工具功能介绍创作过程1. 技术选型2. 核心实现逻辑3. 用户体验增强如何运行

C++ HTTP框架推荐(特点及优势)

《C++HTTP框架推荐(特点及优势)》:本文主要介绍C++HTTP框架推荐的相关资料,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. Crow2. Drogon3. Pistache4. cpp-httplib5. Beast (Boos