通过WebAssembly,C++率先打响虚拟 DOM 第一枪!( 二 )

2.如何使用 asm-dom 构建应用程序asm-dom 是一个底层虚拟 DOM 库,与如何构建应用程序无关 。asm-dom 初始诞生于非游戏、VR、AR 或图像/视频编辑的常见用例中测试 WebAssembly 的强大功能的想法 。然而不幸的是,目前 GC/DOM Integration 仍然是一个面向未来的特性,所以,asm-dom 并不是完全在 wasm 中开发的 。
asm-dom 中所有与 DOM 的交互都是用 Javascript 编写的,这是一个很大的缺点,因为需要 JS 和 WASM 之间额外的绑定开销 。当然,未来 asm-dom 会更强大 。
如果想在没有任何配置的情况下开始使用 asm-dom,可以考虑 asm-dom-boilerplate(查看文末资料),这是一个非常简单的项目,包含需要的所有内容,只需克隆并运行它 。如果使用的是 webpack,为了使用 asm-dom,必须准备环境 。
首先需要安装 arraybuffer-loader:
npm install --save-dev arraybuffer-loader然后在 Webpack 的 loader 中添加下面的内容:
{test: /.wasm$/,loaders: ['arraybuffer-loader'],}另外,如果 fs 有一些问题,可以将下面代码添加到 webpack 配置中:
node: {fs: 'empty',},之后,可以使用 cpp 文件夹中的源代码构建应用程序:

  • asm-dom.hpp 和 asm-dom-server.hpp
  • asm-dom.cpp 和 asm-dom-server.cpp(或包含两者的 asm-dom.a)
并使用 emscripten (emcc cli) 编译它,下面是关于此步骤的一些提示:
  • 请确保在编译期间使用 --bind 选项,否则 asm-dom 将无法工作 。
  • emcc 有很多可以优化构建的设置,可以查看官方文档 。
  • 建议将应用程序编译为 .bc,然后使用它来生成一个 WebAssembly 版本和一个 asm.js 版本(作为回退版本)
编译后就可以在项目中导入应用程序,但是需要注意的是如果使用了 Babel,则需要忽略编译后的文件:
{test: /.js$/,loaders: ['babel-loader'],exclude: [/node_modules/,/compiled/, // folder that contAIns the compiled code (wasm and asmjs)/.asm.js$/ // ignore all .asm.js files],}3.asm-dom 的示例3.1 使用 gccx 集成类 JSXasm-dom 对类 JSX 语法的支持是通过 gccx 实现的,在使用之前需要导入它,然后就可以像 JSX 那样编写代码 。比如下面的例子:
import gccx from 'gccx';const code = `#include "../asm-dom/asm-dom.hpp"#include <emscripten/val.h>#include <string>using namespace asmdom;int main() {VNode* vnode = <h1>Hello world!</h1>;// jsx语法patch(emscripten::val::global("document").call<emscripten::val>("getElementById",std::string("root")),vnode);return 0;};`;const compiled = gccx.parse(code);// 编译代码为字符串3.2 官方示例下面是 asm-dom 官方提供的一个示例 。
#include "asm-dom.hpp"using namespace asmdom;int main() {Config config = Config();init(config);// 借助于 gccx,asm-dom 可以与类似 JSX 的语法一起使用VNode* vnode = (<divonclick={[](emscripten::val e) -> bool {emscripten::val::global("console").call<void>("log", emscripten::val("clicked"));return true;}}><span style="font-weight: bold">This is bold</span>and this is just normal text<a href=https://www.isolves.com/it/cxkf/yy/C/2023-08-22/"/foo">I'll take you places!
);//插入到空的 DOM 元素,这会修改 DOM 作为副作用patch(emscripten::val::global("document").call("getElementById",std::string("root")),vnode);// 不借助于 gccx的语法VNode* newVnode = h("div",Data(Callbacks {{"onclick", [](emscripten::val e) -> bool {emscripten::val::global("console").call("log", emscripten::val("another click"));return true;}}}),Children {h("span",Data(Attrs {{"style", "font-weight: normal; font-style: italic"}}),std::string("This is now italic type")),h(" and this is just normal text", true),h("a",Data(Attrs {{"href", "/bar"}}),std::string("I'll take you places!"))});// Second `patch` invocationpatch(vnode, newVnode);// asm-dom 有效地将旧视图更新为新状态return 0;};4.本文总结随着 Web 的不断发展,WebAssembly 会在 Web 应用程序的开发中发挥越来越重要的作用,很多高级语言如:C++/C、Rust、Go、Zig、C#、php、Java等等都已经能将 WebAssembly 作为编译目标。
同时在基于 WebAssembly 的高级语言 Web 框架层面也是层出不穷,比如 Rust生 态的Yew,Sycamore、percy、seed、MoonZoon 等等,又比如 Go 生态的 Vecty、Vugu、go-app、vue等等 。这对于希望扩展技能并保持技术领先地位的开发人员是时候考虑学习 WebAssembly 并解锁其威力了 。
因为篇幅有限,文章并没有过多展开,如果有兴趣,可以在我的主页继续阅读,同时文末的参考资料提供了大量优秀文档以供学习 。最后,欢迎大家点赞、评论、转发、收藏!


推荐阅读