WebAssembly(简称 Wasm)凭借其快速、接近原生的执行速度、多种编程语言选择以及强大的默认拒绝沙盒模型,一次又一次地证明了自己是一项革命性的技术。 它已在整个网络领域得到广泛应用,并且已成为服务器端的强大参与者。
每个新兴的生态系统都需要一个关于所有部分如何组合在一起的愿景,而这正是WebAssembly 组件模型的用武之地。 组件模型是一个促进 WebAssembly 代码各个单元之间交互以及 WebAssembly 代码与主机环境之间交互的系统。 这一切都围绕着 WebAssembly 组件的概念,它们本质上是具有编码数据类型的常规 Wasm 模块。 这些类型允许生成幕后粘合代码,使得组件可以无缝地相互通信。
组件模型开启了现代软件开发的新时代——开发人员可以从任何编程语言生态系统中挑选组件,并将它们组合成一个应用程序。有一个用 Python 编写的数据处理应用程序,但需要一个来自 Rust 的高效解析器? 没问题。 您所在组织的一个团队精通 Go,但另一个团队只会编写 JavaScript? 没有任何问题——每个团队都可以轻松制作 WebAssembly 组件。
WebAssembly 面临着我们在几乎每个新代码执行平台上都看到的一个问题——我们如何安全、可靠、高效地在可能由完全不同的编程语言工具链生成的单独代码单元之间共享数据? 通常,两个独立的 WebAssembly 模块可以完成许多系统所做的事情,并以 JSON、Protobuf 或任何其他丰富的数据交换格式在它们之间传递数据。 序列化和反序列化这些格式的成本相当高,毕竟,考虑到想要相互通信的两个模块很可能由同一个运行时并行执行,而不是通过网络执行,因此这种实现可能会更好。
困难之处在于每种编程语言表示数据的方式。 语言实现可以选择对字符串使用不同的编码,一种语言可能倾向于将顺序数据存储为数组,而另一种语言可能倾向于使用链表。 为了让不同语言的代码能够相互交流,他们需要就所有类型数据的通用形式达成一致。 这被称为application二进制接口(ABI)。实际上,它们并不一致。 通常,如果希望让用一种语言编写的代码与用另一种语言编写的代码进行对话,一些可怜的开发人员必须坐下来小心地(并且痛苦地)编写代码来在两种语言之间进行翻译。 它需要对两种语言的工作方式有深入的了解,而且极容易出错。 一些语言生态系统已成功开发出能够自动完成此操作的工具,但即便如此,它也只适用于部分语言。
值得庆幸的是,组件模型为所有语言定义了一种通用的数据形式,称为规范ABI。为了方便人类使用,还存在一种称为 WebAssembly 接口类型 (WIT) 的接口定义语言,用于描述组件接口。
现在,我们已经有了所有这些组件,但是我们如何知道可以在哪里使用它们呢? 毕竟,WebAssembly 可以在很多地方运行 - 网络浏览器、服务器、边缘、微型设备等等 - 并且都具有不同的功能。 WIT 为我们带来了世界的概念。 世界是组件遵循的接口——它是组件可以导入的一组函数和组件导出的一组函数。 它使我们能够相当轻松地推断组件以及它们的组成方式。 这是 `wasi:cli/command` 世界中组件的定义,它描述了在终端命令行上运行的组件:
来源: https ://github.com/WebAssembly/wasi-cli ,为简洁起见进行了修改
该组件关注文件系统和随机性之类的东西,同时还具有输入和输出流,但重要的是,它提供了一个在调用命令时运行的函数。
任何人都可以定义世界,但是对于可以处理 HTTP 请求、访问 USB 设备、使用 AI 模型等的组件,有许多标准轨道世界。 主机环境可以宣传它们所实现的世界,以便开发人员轻松了解哪些组件可以工作。 由于组件是可组合的,因此也可以根据其他世界来实现某些世界,并将两个组件组合起来。 例如,如果您有一个实现套接字世界的主机环境,但您有一个想要在 HTTP 世界中发出 HTTP 请求的组件,则可以编写一个使用套接字实现 HTTP 世界的适配器组件:
通过简单的组合,您的组件现在无需修改即可在套接字世界中运行! 可能性是无穷无尽的。
组件模型具有里程碑意义,不仅对于 WebAssembly 如此,对于世界各地的所有开发人员而言亦是如此。 这将从根本上改变开发人员推理和开发软件的方式——目前已经有大量实用功能,而且仍处于早期阶段。 请继续关注 WebAssembly 生态系统的发展,随着采用率的不断攀升,我们一定会看到越来越多引人注目的用例出现。