【译】来看看WebWindow,一个跨平台的.NET Core webview 库

本文翻译自 ASP.NET 项目组的 Steve Sanderson 的博客,发表于 2019 年 11 月 18 日。Steve Sanderson 是 Blazor 最早的创造者。


它类似于 Electron,但没有捆绑 Node.js 和 Chromium,也没有大部分 API。

我的上一篇文章研究了如何用 web 渲染的 UI 构建一个 .NET Core 桌面或控制台应用程序,而不需要引入全部的 Electron 部件。这似乎引起了很多人的兴趣,所以我决定将其升级到新的技术并添加跨平台支持。

最终成果是一个名为 WebWindow[1] 的小 NuGet 包,你可以将它添加到任何 .NET Core 控制台应用程序中。它可以打开一个包含基于 web 的 UI 的本机操作系统窗口(Windows/Mac/Linux),而无需您的应用程序绑定 Node 或 Chromium。

我还把它和 Blazor 解耦了。您现在可以在窗口内托管任何类型的 web UI。repo 中包含一个使用 Vue 的示例,还有一个使用了 Blazor。

注意: 这个库是超前 alpha 质量的。如果你想用它来构建一些真实的东西,请看这篇文章末尾的注释。到目前为止,这只是另一个原型。

“Hello World” 示例

创建一个新的 .NET Core 3 C# 控制台应用程序,然后添加一个引用到 WebWindow NuGet 包:

<ItemGroup><PackageReference Include="WebWindow" Version="0.1.0-20191120.3" />
</ItemGroup>

接下来,将代码添加到 Program 类中的 Main 方法。

static void Main(string[] args)
{var window = new WebWindow("My super app");window.NavigateToString("<h1>Hello, world!</h1> This window is from a .NET Core app.");window.WaitForExit();
}

这样就完成了!现在根据你运行的操作系统,你的应用程序会显示如下窗口:

这个示例使用 NavigateToString(html) 从硬编码的 .NET 字符串渲染 HTML。你也可以:

  • 使用 NavigateToUrl(url) 来显示来自 HTTP 服务器的内容(本地或远程)

  • 使用 NavigateToLocalFile(path) 来显示来自本地磁盘的 HTML 文件,其中 path 是绝对路径或相对于当前工作目录的路径。示例在这里[2]

作为一个稍微高级一些的选项,您可以配置 WebWindow 来处理自定义协议,如 myapp://,并指定一个委托(回调),它可以为该协议中的每个 URL 返回任意内容。示例在这里[3]和这里[4]

一旦您的 web 内容正在运行,JavaScript 和 .NET 之间的底层通信方式就是在 JS 中使用 window.external.sendMessage/receiveMessage API(示例[5])和在.NET 中使用 webWindowInstance.SendMessagewebWindowInstance.OnWebMessageReceived API -(示例[6])。但是,如果您正在构建一个 Blazor 应用程序,则不需要使用这些底层 API,而可以使用 Blazor 常规的 JS 互操作特性。

托管一个 Blazor 应用程序

WebWindow 并没有与 Blazor 耦合。这里是一个使用 Vue.js 在 WebWindow 内呈现一个简单的目录资源管理器应用程序的例子[7]

但如果你真的想用 Blazor,那是非常整洁和简单的。我还做了一个小插件包,WebWindow.Blazor[8],它可以让你在你的 Program.Main 中只用一行代码就能运行一个 Blazor 应用程序。

static void Main(string[] args)
{ComponentsDesktop.Run<Startup>("My Blazor App", "wwwroot/index.html");
}

概括地说,这 并不 涉及 WebAssembly、Node.js 或者是一份私有绑定的 Chromium。它只是在本地运行 .NET Core,直接与操作系统自己的 web 渲染技术进行通信。这一次在 macOS 上的运行结果是:

完整的 WebWindow+Blazor 示例在这里[9]

他是如何工作的

  • Windows 上,WebWindow 通过 `webview2` 使用新的基于 Chromium 的 Edge[10],假设你已经安装了那个浏览器(如果你不安装,它可能会退回到旧的 Edge,但我还没有实现)

  • Mac 上,它使用了操作系统内置的WKWebView[11],这与 Safari 背后的技术相同

  • Linux 上,它使用了 WebKitGTK+2[12],这也是一种基于 WebKit 的技术

这一切的关键在于,与使用 Electron 相比,开发出下载体积更小和内存使用更少的应用程序。但事实果真如此吗?以下是下载大小的统计数据:

正如您所看到的,无论您选择“独立”(捆绑了.NET Core 运行时的一个副本)还是“依赖于框架”(依赖于已安装在目标系统中的 .NET Core),都会对最终的应用程序大小产生巨大的影响。依赖于框架的 WebWindow 应用程序真的可以很小,因为它们只包含您自己的应用程序的二进制文件,并且没有捆绑运行时或浏览器。

接下来,是内存使用统计:

在 Windows 上,WebWindow 和 Electron 使用的是相同的浏览器技术(Chromium),这种技术占用了大部分内存。这就解释了为什么他们之间的差异并不是很大。在 Linux 和 Mac 上,使用自绑定浏览器(指 Electron)与使用操作系统内置技术之间的区别更为明显。

这个项目会得到支持和维护吗?

目前我还没有做出任何承诺!现在最好把它看作是另一个实验。如果有足够多的人想参与进来,就有可能创建一个合适的开源社区项目。

最迫切需要的是有 C++ 经验的人来重写我的原型质量的 C++ 和 Objective-C 代码,使其真正完善。我已完成所有内存管理的概率接近于 0。也许它也应该使用 CMake 或其他健全的构建配置系统。(注意:它确实有一个基于 Azure DevOps 的跨平台 CI[13]。)

如果您打算在生产中使用它,那么您还需要添加大量的特性。例如,设置应用程序图标、添加本地菜单栏等功能。如果您有兴趣贡献这样的功能,并将使其跨平台工作,请来这个 repo[14]


本文翻译自:https://blog.stevensanderson.com/2019/11/18/2019-11-18-webwindow-a-cross-platform-webview-for-dotnet-core/

参考资料

[1]

WebWindow: https://www.nuget.org/packages/WebWindow

[2]

示例在这里: https://github.com/SteveSandersonMS/WebWindow/blob/a01537a9328b085075866a965191d6323ad2cf7d/samples/HelloWorldApp/Program.cs#L11

[3]

这里: https://github.com/SteveSandersonMS/WebWindow/blob/a01537a9328b085075866a965191d6323ad2cf7d/testassets/HelloWorldApp/Program.cs#L14

[4]

这里: https://github.com/SteveSandersonMS/WebWindow/blob/a01537a9328b085075866a965191d6323ad2cf7d/testassets/HelloWorldApp/wwwroot/index.html#L11

[5]

示例: https://github.com/SteveSandersonMS/WebWindow/blob/a01537a9328b085075866a965191d6323ad2cf7d/testassets/HelloWorldApp/wwwroot/index.html#L14-L20

[6]

示例: https://github.com/SteveSandersonMS/WebWindow/blob/a01537a9328b085075866a965191d6323ad2cf7d/testassets/HelloWorldApp/Program.cs#L21-L24

[7]

使用 Vue.js 在 WebWindow 内呈现一个简单的目录资源管理器应用程序的例子: https://github.com/SteveSandersonMS/WebWindow/tree/master/samples/VueFileExplorer

[8]

WebWindow.Blazor: https://www.nuget.org/packages/WebWindow.Blazor

[9]

WebWindow+Blazor 示例在这里: https://github.com/SteveSandersonMS/WebWindow/tree/master/samples/BlazorDesktopApp

[10]

通过 webview2 使用新的基于 Chromium 的 Edge: https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2

[11]

WKWebView: https://developer.apple.com/documentation/webkit/wkwebview

[12]

WebKitGTK+2: https://webkitgtk.org/

[13]

基于 Azure DevOps 的跨平台 CI: https://dev.azure.com/SteveSandersonMS/WebWindow/_build?definitionId=2

[14]

来这个 repo: https://github.com/SteveSandersonMS/WebWindow

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/311457.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sql if 和insert_拼多多面试:Mybatis是如何实现SQL语句复用功能的?

在工作中&#xff0c;往往有这样的需求&#xff0c;对于同一个sql条件查询&#xff0c;首先需要统计记录条数&#xff0c;用以计算pageCount&#xff0c;然后再对结果进行分页查询显示&#xff0c;看下面一个例子。<sql id"studentProperties"><!--sql片段-…

上元节的灯会(亮)-dfs

题目背景 上元佳节&#xff0c;庙会里举办着各式各样的庆典活动&#xff0c;牛宝也兴奋地参与其中。突然&#xff0c;他被一个新颖的点灯游戏所吸引&#xff0c;游戏要求最终点亮所有在场的花灯&#xff0c;每盏灯都有开关两种状态&#xff0c;每一次点击在场的一盏任意状态的花…

代码演示C#各版本新功能

代码演示C#各版本新功能C#各版本新功能其实都能在官网搜到&#xff0c;但很少有人整理在一起&#xff0c;并通过非常简短的代码将每个新特性演示出来。代码演示C#各版本新功能C# 2.0版 - 2005泛型分部类型匿名方法可以为null的值类型迭代器协变和逆变C# 3.0版 - 2007自动实现的…

icoding复习5 树 感觉难度巨大....

icoding 复习5 1. 先序遍历 已知二叉树按照二叉链表方式存储&#xff0c;利用栈的基本操作写出先序遍历非递归形式的算法&#xff1a; void pre_order(BiTree root); 二叉树的相关定义如下&#xff1a; typedef int DataType; typedef struct Node{ DataType data; …

python 进行一元线性回归并输出相关结果_Python实现一元线性回归实战

回归是一种有监督的学习方式&#xff0c;需要根据历史数据对未知数据做出预测。在此&#xff0c;以房屋面积预测房屋价格为例&#xff1a;首先&#xff0c;读入数据&#xff1a;代码如下&#xff1a;import pandas as pdimport numpy as npfrom io import StringIOfrom sklearn…

《C++ Primer》第一章的 Sales_item.h头文件源码

Sales_item.h不是C自带的&#xff0c;需要自己安装&#xff0c;这个库作者已经写好了, Sales_item.h 头文件代码如下&#xff1a; #ifndef SALESITEM_H #define SALESITEM_H #include <iostream> #include <string>class Sales_item{ public:Sales_item(const std…

icoding复习7, 8

icoding复习7 哈希,AVL 查找 必考点!!! 1. 哈希表创建 typedef enum{ HASH_OK, HASH_ERROR, HASH_ADDED, HASH_REPLACED_VALUE, HASH_ALREADY_ADDED, HASH_DELETED, HASH_NOT_FOUND, } HASH_RESULT; typedef struct __HashEntry HashEntry; struc…

python加载模型包占用内存多大_加载pickle python对象会占用大量内存

我有一个python的pickle对象,它生成一个180 Mb的文件.当我取消它时,内存使用量会爆炸到2或3Gb.你有类似的经历吗&#xff1f;这是正常的吗&#xff1f;对象是包含字典的树&#xff1a;每个边是一个字母,每个节点都是一个潜在的单词.因此,要存储一个单词,您需要的边数与该单词的…

《C++ Primer》1.52节练习

练习1.23 #include <iostream> #include "Sales_item.h"using namespace std;int main() {Sales_item trans1, trans2;cout << "请输入若干销售记录:" << endl;if (cin >> trans1) {int num 1;while (cin >> trans2)if (t…

ASP.NET Core 反向代理部署知多少

引言最近在折腾统一认证中心&#xff0c;看到开源项目[IdentityServer4.Admin&#xff1a;https://github.com/skoruba/IdentityServer4.Admin]集成了IdentityServer4和管理面板&#xff0c;就直接拿过来用了。在尝试Nginx部署时遇到了诸如虚拟目录映射&#xff0c;请求头超长、…

函数传参string_JavaScript 高阶函数入门浅析

原文&#xff1a;https://www.freecodecamp.org/news/a-quick-intro-to-higher-order-functions-in-javascript-1a014f89c6b/译者&#xff1a;jingruzhang校对者&#xff1a;acusp高阶函数高阶函数可以接收函数作为参数&#xff0c;同时也可以返回一个新的函数。高阶函数之所以…

all()与any()

all():当可迭代对象为空时返回True。或者当可迭代对象中是否所有值都为True&#xff0c;所有值都为True,则返回True。否则返回False。any():当可迭代对象为空时返回False。或者当可迭代对象中是否存在一个为True的值&#xff0c;若存在&#xff0c;返回True,否则返回False 示例…

.NET Core开发实战(第13课:配置绑定:使用强类型对象承载配置数据)--学习笔记...

13 | 配置绑定&#xff1a;使用强类型对象承载配置数据要点&#xff1a;1、支持将配置值绑定到已有对象2、支持将配置值绑定到私有属性上继续使用上一节代码首先定义一个类作为接收配置的实例class Config {public string Key1 { get; set; }public bool Key5 { get; set; }pub…

Python--第3次平时作业

目录 一、单项选择题 二、程序填空题 三、所有测试代码如下: 一、单项选择题 题号 1 2 3 4 5 6 7 8 9 10 答案 C A A C C D D D D C 题号 11 12 13 14 15 16 17 18 19 20 答案 A A C C B C A C B A 题号 21 22 23 24 25 …

工业互联网白皮书_发布|《工业互联网平台安全白皮书(2020)》发布

12月4日&#xff0c;2020年中国工业信息安全大会暨全国工控安全深度行(京津冀站)在北京国际会议中心举行。大会由国家工业信息安全发展研究中心、工业信息安全产业发展联盟主办&#xff0c;以“贯彻总体国家安全观&#xff0c;把牢工控安全基准线”为主题。会上&#xff0c;国家…

UVA - 514 Rails-栈

某城市有一个火车站&#xff0c;铁轨铺设如图6-1所示。 有n节车厢从A方向驶入车站&#xff0c;按进站顺 序编号为1&#xff5e;n。 你的任务是判断是否能让它们按照某种特定的顺序进入B方向的铁轨并驶出 车站。 例如&#xff0c;出栈顺序(5 4 1 2 3)是不可能的&#xff0c;但(5…

全局思维

在这个复杂多变的时代&#xff0c;是时候提升我们的思维了&#xff0c;树立大局意识&#xff0c;在把握空间纵轴线和时间水平线中思考和谋划大局。全局思维能力&#xff0c;蕴含着从全局的、长远的、战略的高度来分析问题和解决问题的能力&#xff1b;是善于从大处着眼、小处着…

python中函数的参数类型( 位置参数、关键字参数、默认值参数和可变长度参数)

目录 位置参数: 关键字参数: 默认值参数: 可变长度参数: 1.元组可变长度参数 : 2.字典可变长度参数: 附上练习代码: 位置参数: 实参与形参个数完全相同,按位置按顺序将实参传递给形参 def f(x, y):print(x, y) f(2, 3) 2, 3 关键字参数: 在函数调用中使用关键字参数&…

python分布式存储文件_python如何分布式存储文件的方法

想了很久&#xff0c;还是跟大家聊一聊关于分布式吧&#xff0c;只是因为大家在编写代码&#xff0c;填充内容时候&#xff0c;最多肯定是涉及文字以及图片&#xff0c;因此对于这些内容后期做代码存储肯定至关重要&#xff0c;没有任何一个用户会直接看代码来认知你的产品&…