1个不稳定版本

0.1.0 2020年10月19日

#1009 in WebAssembly

MIT/Apache

150KB
3K SLoC

Euca Crates.io

Euca是一个旨在模块化的实验性前端Web开发库。diffing、patching和主应用程序代码都通过一组允许替代实现按需替换的特性进行交互。

动机

许多用Rust编写的Web开发框架。大多数都是实验性的,处于早期阶段,并且它们都以独特的方式表示虚拟DOM。我认为DOM的表示对库的用户来说并不重要。用户应该能够以最舒适的方式表示DOM。如果是声明式、JSX 样式或面向函数的elm样式,框架应该接受任何作为输入。同样,每个框架都实现了自己的vDOM diffing和patching算法,这是多余的。为什么所有框架不都重用最好的算法呢?

我想,我们为什么要有框架呢?如果我们能将每个部分(vDOM表示、diffing、patching)拆分出来,按照我们的需求组合它们会怎样呢?Euca是一个探索这个领域的实验。

设计

库的用户界面部分主要遵循The Elm Architecture设计,其中有一个包含数据的模型、一个接受事件并更新模型的更新函数,以及一个将模型渲染为虚拟DOM的视图函数(我们称其为render)。在Elm中,一切都是不可变的,因此更新函数接受一个模型并返回对该模型的新更改作为新模型。在Rust中,我们不需要这种限制,因此我们的更新函数在这里直接修改模型。这对于不习惯于函数式编程的人来说更加直观。

内部,vDOM通过一个迭代器外观表示,该外观由diffing算法用来遍历vDOM。diff操作产生一系列描述对DOM进行更改的补丁,补丁算法将这些更改应用到浏览器的DOM上。所有这些操作都是松散耦合的,并且大部分可以独立修改和替换。

测试

没有测试的代码是糟糕的代码。无论它写得多么好;无论它多么漂亮或面向对象或封装得多么好。有了测试,我们可以快速且可验证地改变代码的行为。没有它们,我们真的不知道我们的代码是在变好还是变坏。

——迈克尔·费思,有效处理遗留代码

Euca的设计考虑了可测试性。Euca的设计(Elm架构)允许非常直接的单元测试。因为消息/事件是更新模型的唯一方式,所以验证应用程序的行为可以集中在更新函数上。给定一个模型,处理一个事件应该导致模型发生某些变化。同样,渲染函数不能修改模型,给定一个特定的模型,该函数应该生成特定的vDOM。

诸如HTTP请求和与存储或浏览器历史交互之类的副作用被隔离到更新函数返回的命令中。这样,用户可以验证更新函数产生了正确的副作用,而无需实际执行副作用。

灵感

这个库受到了ElmWillow的极大启发,并受到了DracoSeedReact的额外启发。

限制

没有闭包

由于闭包没有实现PartialEq,这是在比较vDOM节点时使用的,因此处理事件时不支持闭包。支持简单的函数指针,但这些无法捕获任何状态,并且仅操作提供的参数。在我的有限使用中,我没有发现这成为一个主要问题,但大多数其他Rust Web框架都支持闭包,所以与这些库集成Euca需要重大修改。这是一个主要的限制,因为整个想法是与现有库集成。

最近,Euca添加了带键的更新。理论上,可以使用带键的事件处理程序支持一些数据集,这些数据集被闭包捕获作为键。目前不支持这一点,但应该是可能的。

未优化

差异算法是完全未优化的。我的意图是证明构建模块化框架是可能的,而不是实现最快的算法。在我使用Euca开发的应用程序中,它的表现相当合理,但我不知道它有多快或多慢。我没有测试这一点。

组合

支持两种组合方式:通过函数(如Elm)和通过模块化的自包含组件(如React)。Elm的组合函数方法对于没有太多状态或特殊行为特征的简单本地组件工作得很好,并且所有组件都使用相同的消息类型。对于需要复杂状态和行为或消息类型与包含应用程序不同的复杂组件,Euca支持在父应用程序内有效挂载子应用程序。父应用程序可以向子应用程序发送单个消息,类似于react组件中的属性。组件可以使用命令与父应用程序通信。当组件初始化时,提供了将子父消息和命令类型之间进行转换的函数。

待办事项

  • 针对测试的DOM匹配。在测试渲染函数时,比较用于验证的DOM的小部分会很有用(可能使用css 选择器)。
  • 渲染函数的快照测试。简而言之,DOM将被渲染并手动检查。将捕获一个已知良好的快照,用于在未来的测试运行中检测更改。然后手动评估这些更改,以确定这是否是预期的行为。

依赖项

~6.5–8.5MB
~170K SLoC