跑分方面,这款 JavaScript 库在全球框架榜单中的表现比 React 要好得多

最初的动机

2021 年 11 月 左右,Strve 第一个版本发布,社区的反馈大部分是支持,也有少部分小伙伴提出了质疑,这都正常。你只要在社区发布一些作品,就必须接受其他人对你的作品的评价。

当初,开发 Strve 的初衷只是受到 JSX 语法的影响,觉得在 JavaScript 中编写 HTML 很酷,所以想能不能自己也开发一个前端框架。我最初给自己的目标就是能在 JavaScript 中写 HTML,然后通过编写 JavaScript 来改变页面状态。经过两个多周的调研,发现自己在原地打转。JSX 语法不能直接在浏览器运行,你必须通过类似 Babel 这种编译工具编译才能运行。所以,我就打算在模版字段串内编写 HTML。但是,又遇到了另一个问题,如何精确更新 DOM。当时,第一个想法就是利用虚拟 DOM,所以就抽时间来学习前端框架中都是怎么利用虚拟 DOM 来精确更新。不懂得就去网上查资料,然后就记下来。可能有些小伙伴就会问,是什么力量让你去做可能完成了也没什么意义的事情。怎么说呢!当时,我就是想要做出点东西来,觉得自己能做出来。至于做出来有什么意义,我没有多想。有时候我们做一件事情之前,考虑很多未必是好事,这往往会阻碍了我们做事情的脚步。

就这样,靠着自己的热情,第一个版本就这么问世了。

有很多小伙伴感觉 Strve 写法很像lit-html。说实话,开发 Strve 之前,我并不知道这个框架。后来看社区反馈,才到网上查看了有关的资料。虽然写法像,但并不是它的复制品。就比如 Strve 内部使用的是虚拟 DOM,这时的虚拟 DOM 还只是一个初版,只能说是简单的比对。

全新的认识

之前有看过我的文章的小伙伴,多多少少会知道 Strve。但是可能也只是停留在知道这个层面上,现在我通过几点来重新介绍下 Strve。

Strve 是一个易用、快速、灵活且轻量级的 JavaScript 库,用于构建用户界面。基于 tagged template 的 HTML 模板引擎,利用 ES6 的模板字符串来进行模板的书写,利用浏览器的原生的能力进行模板渲染。

  • 更容易上手: 只要你对 HTML、CSS 和 JavaScript 已经基本熟悉,就可以直接上手。

  • 声明式渲染: 我们可以声明式地描述最终输出的 HTML 和 JavaScript 状态之间的关系,开发者可以更加专注于业务逻辑的开发,不需要过多地关心 DOM 操作的细节。

  • 顺滑的用户体验: 模板字符串来进行模板的书写,在一些场景中代码智能提示、代码格式化方面不是特别友好。所以,我们提供了新的一种编码方式,我们可以使用 JSX 语法编写 Strve,提升用户开发体验。

  • 性能出色: 采用了虚拟 DOM 的模式,虚拟 DOM 使用 diff 算法的方法来计算出真正需要更新的节点,最大限度地减少了 DOM 操作以及 DOM 操作带来的排版与重绘损耗,从而显著提高了性能。另外,我们的 JavaScript 库在全球知名的测评榜单(js-framework-benchmark)上赢得了优秀的成绩。

  • 组件化: 一个函数就是一个组件,可以根据应用规模任意组合。并且组件特有的 "孤岛特性",使得将虚拟 DOM 树计算的级别控制在组件级别。

  • 灵活的应用场景: 有无构建工具都可以使用,并且可以适配到其他前端框架开发的应用项目中去。

  • 轻量级: 压缩后的文件大小不足 10k。另外,可以根据不同应用场景,选择不同类型的文件。

想要了解更多关于 Strve 的特性,可以到官方中文文档中去探索。

(strvejs.gitee.io/strve-doc-z...)

贴心的优化

2023 年我陆续发布了几个大的版本,大部分时间都是在优化底层代码。包括虚拟 DOM 的算法优化、减轻使用 API 时 心智负担等等优化措施。

下面我们来展开看下。

如果你不打算使用构建打包工具开发项目,而是直接开发。推荐使用全局构建版本,通过 CDN 使用 Strve 时,不涉及"构建步骤",这使得设置更加简单。

html 复制代码
<script src="https://cdn.jsdelivr.net/npm/strve-js@6.6.6/dist/strve.full.prod.js"></script>
<script>
  const { html, defineComponent } = Strve;

  defineComponent(
    {
      mount: '#app',
    },
    ({ setData }) => {
      let count = 0;

      function add() {
        setData(() => {
          count++;
        });
      }

      return () => html`<h1 onClick=${add}>${count}</h1>`;
    }
  );
</script>

模板字符串来进行模板的书写,在一些场景中代码智能提示、代码格式化方面不是特别友好。所以,我们提供了一种新的编码方式,我们可以使用 JSX 语法编写 Strve 应用,这样就大大提升了用户开发体验。

js 复制代码
defineComponent(() => {
  const state = {
    msg: 'Hello',
  };
  return () => h1>{state.msg}</h1>;
});

另外,我们底层采用了虚拟 DOM 的模式,虚拟 DOM 使用 diff 算法的方法来计算出真正需要更新的节点,最大限度地减少了 DOM 操作以及 DOM 操作带来的排版与重绘损耗,从而显著提高了性能。

Strve 应用程序是由 组件 组成的。一个组件是 UI(用户界面)的一部分,它拥有自己的逻辑和外观。组件可以小到一个按钮,也可以大到整个页面。

在 Strve 中,组件就是一个函数。

js 复制代码
const MyComponent = defineComponent(({ setData }) => {
  let count = 0;

  function add() {
    setData(() => {
      count++;
    });
  }

  return () => (
    <div class='MyComponent'>
      <p>{count}</p>
      <button onClick={add}>MyComponent</button>
    </div>
  );
});

// 复用组件
defineComponent(
  {
    mount: '#app',
  },
  ({ setData }) => {
    let count = 0;

    const add = () => {
      setData(() => {
        count++;
      });
    };

    return () => (
      <div class='App'>
        <p>{count}</p>
        <button onClick={add}>App</button>
        <component $is={MyComponent} />
      </div>
    );
  }
);

Strve 内部的渲染系统是基于虚拟 DOM 构建的,虚拟 DOM (Virtual DOM,简称 VDOM) 是一种编程概念,意为将目标所需的 UI 通过数据结构"虚拟"地表示出来,保存在内存中,然后利用 Diff 算法来比对新老数据,将真实的 DOM 与之保持同步。

如何虚拟 DOM 树过于庞大,使得 Diff 计算时间大于 16.6ms,那么就可能造成性能的卡顿。组件有一个特性就是 "孤岛"。何为"孤岛",孤岛就是在 Strve 应用中我们可以理解成一个独立的模块。将一个庞大的虚拟 DOM 树分解成很多独立的模块,这样 Diff 计算时间就会控制在组件级别,大大缩减了计算的时间,提高了性能。

从 API 层面,我们尽可能的贴合易用的特性,将核心 API 缩减为 2 个。分别为defineComponentsetData。框架是需要容易使用的,太多繁琐的设置或者操作很容易增重心智负担。

丰富的生态

开发框架单单只有一个核心库肯定是不够的,你还需要其他生态工具来加以辅助。

你要有一套用于快速构建项目的命令行工具,也就是说用户可以通过输入命令快速搭建项目。CreateStrveApp 是一套用于快速构建 Strve 项目的命令行工具。 CreateStrveApp 是使用 Vite 构建的,这是一个新的前端构建工具,可以显着提升前端开发体验。它有几个模版可供选择:strvestrve-appsstrve-jsxstrve-jsx-apps

我们开发项目需要跳转多个页面,那么就需要路由管理器。StrveRouter 是 Strve 的官方路由管理器。 它与 Strve 的核心深度集成,轻松构建单页应用程序。

另外,我们介绍两款编译时工具。BabelPluginStrve是一款 babel 插件,将 HTML 模板字符串转化为 Virtual Dom。从之前的运行时转移到编译时,大幅度提高渲染性能。如果你想使用 JSX 语法,BabelPluginJsxToStrve这款插件是必不可少的,它是一款 babel 插件,将 JSX 转换为与 Strve 一起使用的标记模板。CreateStrveApp 项目脚手架工具已默认安装,选择 strve-jsx 或者 strve-jsx-apps 模版即可。我们使用 CreateStrveApp 搭建完 Strve 项目你会发现,同时安装了 BabelPluginStrve、BabelPluginJsxToStrve,这是因为我们需要使用 BabelPluginJsxToStrve 将 JSX 转换为标签模版,之后再使用 BabelPluginStrve 将标签模版转换为 Virtual DOM。

我们最后压轴的一款生态工具可以说是近期更新力度最大的了。它被称为独立运行的可响应性 Strve,由 @vue/reactivitystrve-js 提供支持的自定义元素 JavaScript 库。

主要特性有以下几个:

  • Web Components
  • Hooks
  • Reactivity API
  • Props
  • Emit
  • Slot
  • Styles
  • Automatic registration component
  • Virtual DOM

Strve 结合 Vue 组合式 API 形成了一款新的 JavaScript 库。只要你熟悉组合式 API,就可快速上手。

js 复制代码
// MyComponent.jsx
import { ref, defineComponent, reactive } from 'strve-reactivity';

const MyComponent = defineComponent(() => {
  const items = reactive([
    {
      id: 1,
      tit: 'A',
    },
    {
      id: 2,
      tit: 'B',
    },
  ]);
  const count = ref(4);
  const increase = () => {
    items.unshift({
      id: count.value++,
      tit: 'C',
    });
  };

  return () => (
    <fragment>
      <button onclick={increase}>increase</button>
      <ul>
        {items.map((item) => (
          <li key={item.id}>
            <span>{item.id}</span>
            <span>-</span>
            <span>{item.tit}</span>
          </li>
        ))}
      </ul>
    </fragment>
  );
});

出色的跑分

我们只是口头说 Strve 性能是非常不错的,没有真凭实据那是说不过去的。跑分方面,Strve 在 js-framework-benchmark 中的表现比 React 要好得多。

(krausest.github.io/js-framewor...)

巨人的肩膀

前端框架最近几年来层出不穷,出现这种情况好吗?我觉得是个好现象。大家都在为前端社区贡献自己的力量,使得前端的生态生机勃勃。

大家可能非常讨厌跟知名框架比较,可能有些人会说蹭热度。其实不妨换个角度想想,为什么会比较,是因为要更好。怎么样才能更好,那只能不断地优化。那么在这优化的过程中你不光是做出一个 JavaScript 库或者前端框架,更多的是你可以从中获得你在平时工作中得不到的东西。比如,对设计一款框架需要考虑哪些方面。作者在设计 API 时为什么会这么设计等等一些非工作业务上的事情。

我开发这款 JavaScript 库,我是另辟蹊径吗?我感觉并不是,我只是学习其他优秀框架中可以借鉴的思想,并按照自己想要的方式去展现它。只有站在巨人的肩膀上才能望得更远!

有趣的事情

前不久,我在 Github 上创建了 Strve 组织。

如果,你愿意跟我一块做这件有趣的事情,欢迎加入 Strve 大家庭。

有意向的可以在 Strve 源码仓库提 issues或者在评论区私信我。

源码仓库:github.com/strveJs/str...

中文文档:strvejs.gitee.io/strve-doc-z...

相关推荐
Boilermaker199215 分钟前
【Java EE】SpringIoC
前端·数据库·spring
中微子26 分钟前
JavaScript 防抖与节流:从原理到实践的完整指南
前端·javascript
天天向上102441 分钟前
Vue 配置打包后可编辑的变量
前端·javascript·vue.js
芬兰y1 小时前
VUE 带有搜索功能的穿梭框(简单demo)
前端·javascript·vue.js
好果不榨汁1 小时前
qiankun 路由选择不同模式如何书写不同的配置
前端·vue.js
小蜜蜂dry1 小时前
Fetch 笔记
前端·javascript
拾光拾趣录1 小时前
列表分页中的快速翻页竞态问题
前端·javascript
小old弟1 小时前
vue3,你看setup设计详解,也是个人才
前端
Lefan1 小时前
一文了解什么是Dart
前端·flutter·dart
Patrick_Wilson1 小时前
青苔漫染待客迟
前端·设计模式·架构