您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > C/C++/C#

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

时间:2023-08-22 14:06:22  来源:今日头条  作者:高级前端进阶

前言

本文主要和大家讨论 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-dom

asm-dom 是用于构建 C++ SPA 单页应用程序的最小 WebAssembly 虚拟 DOM。 基于 asm-dom,开发者可以使用 C++ 编写整个 SPA,然后使用 Emscripten 将其编译为 WebAssembly(或作为后备的 asmjs),asm-dom 将自动处理 DOM API 调用,从而生成一个旨在通过利用通用硬件功能以本机速度执行的应用程序。

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 = (
    <div
      onclick={[](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="/foo">I'll take you places!</a>
    </div>
  );

服务器端渲染

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="/index.css" />"
    "</head>"

    "<body>"
      + appString +
    "</body>"

    "<script src="/bundle.js"></script>"
  "</html>"
);
// 客户端渲染
VNode* oldVNode = toVNode(
  emscripten::val::global("document").call<emscripten::val>("getElementById", emscripten::val("root"))
);
VNode* vnode = view();
patch(oldVNode, vnode);
// 附加事件处理器

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 集成类 JSX

asm-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 = (
    <div
      onclick={[](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="/foo">I'll take you places!</a>
    </div>
  );

  //插入到空的 DOM 元素,这会修改 DOM 作为副作用
  patch(
    emscripten::val::global("document").call<emscripten::val>(
      "getElementById",
      std::string("root")
    ),
    vnode
  );

  // 不借助于 gccx的语法
  VNode* newVnode = h("div",
    Data(
      Callbacks {
        {"onclick", [](emscripten::val e) -> bool {
          emscripten::val::global("console").call<void>("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` invocation
  patch(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 并解锁其威力了。

因为篇幅有限,文章并没有过多展开,如果有兴趣,可以在我的主页继续阅读,同时文末的参考资料提供了大量优秀文档以供学习。最后,欢迎大家点赞、评论、转发、收藏!

参考资料

https://mbasso.github.io/asm-dom/

https://github.com/mbasso/asm-dom-boilerplate

https://github.com/mbasso/gccx

https://mbasso.github.io/asm-dom/docs/inline-example.html

https://www.geeksforgeeks.org/explain-dirty-checks-in-react-js/

封面图版权:作者 swapnil074 的《Explain dirty checks in React.js》



Tags:C++   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
C++常见避坑指南
C++ 从入门到放弃?本文主要总结了在C++开发或review过程中常见易出错点做了归纳总结,希望借此能增进大家对C++的了解,减少编程出错,提升工作效率,也可以作为C++开发的避坑攻略。...【详细内容】
2024-04-03  Search: C++  点击:(4)  评论:(0)  加入收藏
C++ 之父反驳白宫警告:自诞生第一天起,C++ 的目标就一直是提高安全性
整理 | 郑丽媛上个月,美国白宫国家网络主任办公室(ONCD)在一份主题为《回到基础构件:通往安全软件之路》的 19 页 PDF 报告中,呼吁开发人员停止使用容易出现内存安全漏洞的编程语...【详细内容】
2024-03-25  Search: C++  点击:(4)  评论:(0)  加入收藏
八个 C++ 开源项目,帮助初学者进阶成长
通过参与或阅读开源项目的源代码,你可以获得丰富的实践机会。实际的项目代码比简单的教程更具挑战性,可以帮助你深入理解 C++ 的各种概念和技术。1.ThreadPool一个简单的 C++1...【详细内容】
2024-03-22  Search: C++  点击:(21)  评论:(0)  加入收藏
C++多线程编程:解锁性能与并发的奥秘
今天我们将深入探讨C++中的多线程编程,揭示多线程如何解锁性能潜力,提高程序的并发性能。什么是多线程?在计算机科学中,多线程是指一个进程(程序的执行实例)中的多个线程同时执行...【详细内容】
2024-02-03  Search: C++  点击:(69)  评论:(0)  加入收藏
C++代码优化攻略
今天我们将深入探讨C++性能优化的世界。在当今软件开发的浪潮中,高性能的代码是必不可少的。无论是开发桌面应用、移动应用,还是嵌入式系统,性能都是关键。1. 选择合适的数据结...【详细内容】
2024-01-26  Search: C++  点击:(113)  评论:(0)  加入收藏
C++质数检测器的设计与实现​
质数,作为数学中的一个基本概念,一直以其独特的性质吸引着众多研究者和爱好者。质数是指大于1的自然数中,除了1和它本身以外不再有其他因数的数。在实际应用中,质数检测也扮演着...【详细内容】
2024-01-15  Search: C++  点击:(111)  评论:(0)  加入收藏
指针变量在C/C++中的内存占用
在编程领域,尤其是C和C++这类底层语言中,指针是一个核心概念,它允许程序直接操作内存地址。然而,关于指针本身在内存中占用的空间大小,却常常让初学者感到困惑。本文将深入探讨这...【详细内容】
2024-01-09  Search: C++  点击:(95)  评论:(0)  加入收藏
C++的面向对象编程:深入解析与理解
当我们谈论C++时,面向对象编程(OOP)是一个无法回避的话题。那么,C++的面向对象究竟是什么?为什么它如此重要?本文将从基本概念到实际应用,为您详细解析C++中的面向对象编程。一、面...【详细内容】
2024-01-03  Search: C++  点击:(95)  评论:(0)  加入收藏
有什么好用的C/C++源代码混淆工具?
开始使用ipaguard前言iOS加固保护是直接针对ios ipa二进制文件的保护技术,可以对iOS APP中的可执行文件进行深度混淆、加密。使用任何工具都无法逆向、破解还原源文件。对APP...【详细内容】
2023-12-29  Search: C++  点击:(118)  评论:(0)  加入收藏
C++中new与malloc:内存分配机制深度解析
本文旨在深入探讨C++中new和malloc两种内存分配机制的区别。通过对比它们在内存分配、初始化、错误处理、调用构造函数/析构函数、类型转换和使用便捷性等方面的不同,我们将...【详细内容】
2023-12-27  Search: C++  点击:(127)  评论:(0)  加入收藏
▌简易百科推荐
C++常见避坑指南
C++ 从入门到放弃?本文主要总结了在C++开发或review过程中常见易出错点做了归纳总结,希望借此能增进大家对C++的了解,减少编程出错,提升工作效率,也可以作为C++开发的避坑攻略。...【详细内容】
2024-04-03  腾讯技术工程    Tags:C++   点击:(4)  评论:(0)  加入收藏
C++ 之父反驳白宫警告:自诞生第一天起,C++ 的目标就一直是提高安全性
整理 | 郑丽媛上个月,美国白宫国家网络主任办公室(ONCD)在一份主题为《回到基础构件:通往安全软件之路》的 19 页 PDF 报告中,呼吁开发人员停止使用容易出现内存安全漏洞的编程语...【详细内容】
2024-03-25    CSDN  Tags:C++   点击:(4)  评论:(0)  加入收藏
八个 C++ 开源项目,帮助初学者进阶成长
通过参与或阅读开源项目的源代码,你可以获得丰富的实践机会。实际的项目代码比简单的教程更具挑战性,可以帮助你深入理解 C++ 的各种概念和技术。1.ThreadPool一个简单的 C++1...【详细内容】
2024-03-22  AI让生活更美好  微信公众号  Tags:C++   点击:(21)  评论:(0)  加入收藏
C# 中15个值得收藏的开源项目推荐
在开源的世界里,C# 编程语言也占有一席之地。这些开源项目涵盖了多个领域,从框架、库到工具,它们为C#开发者提供了丰富的资源和工具,帮助他们更高效地开发、测试和部署应用程序...【详细内容】
2024-03-20  程序员编程日记  微信公众号  Tags:C#   点击:(30)  评论:(0)  加入收藏
C#异步编程:Task.Run vs. async-await,掌握基础与高级用法
概述:C#中的异步编程有两主要方式:Task.Run用于在后台线程执行同步操作,而async-await更适用于清晰表达异步流程。基础用法展示了它们的简单应用,高级用法则演示了它们的结合使...【详细内容】
2024-03-09  架构师老卢  今日头条  Tags:C#   点击:(23)  评论:(0)  加入收藏
C++多线程编程:解锁性能与并发的奥秘
今天我们将深入探讨C++中的多线程编程,揭示多线程如何解锁性能潜力,提高程序的并发性能。什么是多线程?在计算机科学中,多线程是指一个进程(程序的执行实例)中的多个线程同时执行...【详细内容】
2024-02-03     AI让生活更美好  Tags:C++   点击:(69)  评论:(0)  加入收藏
C++代码优化攻略
今天我们将深入探讨C++性能优化的世界。在当今软件开发的浪潮中,高性能的代码是必不可少的。无论是开发桌面应用、移动应用,还是嵌入式系统,性能都是关键。1. 选择合适的数据结...【详细内容】
2024-01-26  AI让生活更美好  微信公众号  Tags:C++   点击:(113)  评论:(0)  加入收藏
C# 线程本地存储为什么线程间值不一样
为什么用 ThreadStatic 标记的字段,只有第一个线程拿到了初始值,其他线程都是默认值,让我能不能帮他解答一下,尼玛,我也不是神仙什么都懂,既然问了,那我试着帮他解答一下,也给后面类...【详细内容】
2024-01-26  一线码农聊技术  微信公众号  Tags:C#   点击:(67)  评论:(0)  加入收藏
C++质数检测器的设计与实现​
质数,作为数学中的一个基本概念,一直以其独特的性质吸引着众多研究者和爱好者。质数是指大于1的自然数中,除了1和它本身以外不再有其他因数的数。在实际应用中,质数检测也扮演着...【详细内容】
2024-01-15  鲨鱼编程  微信公众号  Tags:C++   点击:(111)  评论:(0)  加入收藏
C# 登顶!超越Java或非空想
整理丨诺亚出品 | 51CTO技术栈(微信号:blog51cto)近日,TIOBE编程社区公布年度编程语言,此次摘得这一桂冠的是C#。这也是C#在TIOBE二十多年评选历史中首次赢得这一年度大奖。C#虽...【详细内容】
2024-01-15    51CTO  Tags:C#   点击:(114)  评论:(0)  加入收藏
站内最新
站内热门
站内头条