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

前言本文主要和大家讨论 asm-dom,即通过 WebAssembly 技术 C++ 率先支持虚拟DOM 。在年初,我也确实使用 WebAssembly 将客户端应用成功移植到了 Web,这也是为什么我一直对 WebAssembly 充满好奇的原因 。我甚至在头条上开了一个合集《WebAssembly 前沿技术》来专门探讨 WebAssembly,并将持续关注 WebAssembly 的最新动态 。
下面是已发布部分文章传送门(更多文章可以阅读我的头条专题):

  • 《 2023 年让 WebAssembly 大火的 10+应用!》
  • 《 万字长文!2023 年 WebAssembly 各个运行时性能对比!》
  • 《 让 JAVAScript 在 WebAssembly 上加速运行!》
  • 《全网最火的5+优秀 WebAssembly 运行时!》
  • 《 在线表格再添一员猛将Excelize,支持 wasm! 》
正如大家所看到的,当我们还在迟疑是否要在日常开发中引入 WebAssembly 的时候,很多优秀的应用、工具已经开始吃 WebAssembly 的红利了,而且取得了不错的成就,这可能也是为什么各个浏览器厂商、开发者如此热衷 WebAssembly 的原因吧 。
1.什么是 asm-domasm-dom 是用于构建 C++ SPA 单页应用程序的最小 WebAssembly 虚拟 DOM 。基于 asm-dom,开发者可以使用 C++ 编写整个 SPA,然后使用 Emscripten 将其编译为 WebAssembly(或作为后备的 asmjs),asm-dom 将自动处理 DOM API 调用,从而生成一个旨在通过利用通用硬件功能以本机速度执行的应用程序 。
通过WebAssembly,C++率先打响虚拟 DOM 第一枪!

文章插图
asm-dom项目
此外,开发者可以基于原有 C/C++ 代码而无需任何更改,比如创建绑定层 。这相当于使用 C++ 中创建一个应用程序,在必要的时候会自动调用 JavaScript,而不是通过 Javascript 反向调用 C++ 。asm-dom 允许开发者只用 C++ 编写代码一次,并在桌面、移动应用程序和 Web 端实现代码共享 。
目前 asm-dom 在 Github 上通过 MIT 协议开源,有超过 2.7k 的 star、0.1k 的 fork、是一个值得关注的开源项目 。可以将 asm-dom 的典型特征归纳为以下几个核心要点,包括:
灵活性asm-dom 是一个底层虚拟 DOM 库,对于开发者应该如何构建自己的应用程序并无偏好 。
共享 C++ 代码库只用 C++ 编写代码一次,并与桌面/移动应用程序和 Web 端最大限度的实现代码共享 。
速度飞快asm-dom 允许开发者使用 C++ 编写整个 SPA,并使用 Emscripten 将其编译为 WebAssembly,同时保证应用速度 。这对于基于浏览器、WebView的应用程序来说绝对是福音 。
类似 JSX 的语法借助于 gccx,即一个允许简单语法(CPX)的解析器(和 JSX 有细微差异),asm-dom 会自动将 CPX 语法转换为标准 C++ 。通过这种方式,开发者可以编写出与 html 非常相似的文件,从而提供开发人员体验 。
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!
);服务器端渲染【通过WebAssembly,C++率先打响虚拟 DOM 第一枪!】asm-dom 支持服务器端渲染,开发者可以用 C++ 编写服务器并使用 WebAssembly 在 Node.js 上运行 。只需要两个核心步骤:
  • 使用 toHTML 在服务器上生成 HTML 并将其发送到客户端以加快页面加载速度,并允许搜索引擎出于 seo 目的抓取页面
  • 在服务器渲染的节点上调用 toVNode 并使用在客户端创建的 vnode 对其进行 patch(类似补水) 。通过这种方式,asm-dom 将保留它并仅附加事件处理程序,从而提供出色的首次加载体验
下面是服务端渲染的典型示例:
// 返回视图的函数,用于客户端和服务器VNode* view() {return (h("div",Data(Attrs {{"id", "root"}}),Children {h("h1", std::string("Title")),h("button",Data(Attrs {{"class", "btn"}},Callbacks {{"onclick", onButtonClick}}),"Click Me!")}));}// 服务端渲染VNode* vnode = view();std::string AppString = toHTML(vnode);std::string html = ("<!DOCTYPE html>""<html>""<head>""<title>My Awesome App</title>""<link rel="stylesheet" href=https://www.isolves.com/it/cxkf/yy/C/2023-08-22/"/index.css" />"""""+ appString +"""""");// 客户端渲染VNode* oldVNode = toVNode(emscripten::val::global("document").call("getElementById", emscripten::val("root")));VNode* vnode = view();patch(oldVNode, vnode);// 附加事件处理器


推荐阅读