缝合怪系列-C#+TS客户端缝合怪,Webview2+Vue开发体验

发布时间 2023-07-25 00:36:05作者: popsicle

写在前面

最近几年天天听到网上说"大前端",这是一个比较新的行业术语,它涵盖了前后端、移动端等多领域的知识和技能。核心理念是:一体化,即从前端开发到后端开发,甚至包括移动端开发、设计等,都在一个团队内完成。
毕竟咱作为前端+非专业客户端开发者,还是想整点好玩的东西,今天没事搞Windows客户端开发,试下把前端和客户端缝合一下,刚好开个新坑,做一些多种语言或者框架交火缝合相关项目。

废话不多说,直接开始

winform + webview2的配置

winform项目使用nuget将webview2安装到项目中,然后将Webview2空间拖放至winform界面上,然后需要在窗体主类上编写webview2的初始化代码,具体就是WebView控件上的EnsureCoreWebView2Async方法,贴一下方法的定义:

public System.Threading.Tasks.Task EnsureCoreWebView2Async (Microsoft.Web.WebView2.Core.CoreWebView2Environment environment);

参数是预先创建的 CoreWebView2Environment 对象,如果传参是 null,则将自动创建并使用默认环境。就是说你可以通过这个 CoreWebView2Environment 对象控制 CoreWebView2 初始化方式,而 WebView2 控件使用 Microsoft Edge,以在控件中显示 web 内容,这个 CoreWebView2 就是 WebView2 控件的真正本体。
WebView2 需要你的运行环境有对应的webview运行时,而这个可以有两种选择,一种是常青版(Evergreen)就是你的运行环境需要额外安装的一个Runtime,另一种选择是固定版本(Fixed Version),一般是从官网下载下来Fix Version的Runtime,由你的客户端程序自己附带提供给用户。下图展示了webview2官网的两种版本下载页面。

webview2官网

刚刚铺垫的知识介绍了那么多,目的就是说明 CoreWebView2Environment 类上有一个静态方法(CreateAsync),可以使用已安装的常青版或固定版本号的 WebView2 运行时版本创建 WebView2 环境。下面是此方法的定义,第一个参数就是固定版本运行时的路径,如果不提供则默认使用常青版。

public static System.Threading.Tasks.Task<Microsoft.Web.WebView2.Core.CoreWebView2Environment> CreateAsync (string browserExecutableFolder = default, string userDataFolder = default, Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions options = default);

我的电脑上已经安装了常青版,因此就以常青版为例,初始化代码如下

public MainWindow()
{
    InitializeComponent();
    InitializeAsync();
}
async void InitializeAsync()
{
    await webView.EnsureCoreWebView2Async(null);
}

此时运行程序应该可以在webview2控件上右键可以看到edge的右键菜单被呼出,如下图所示。
webview2控件右键

接下来,就该为Webview2控件指定源了,我们使用 Uri 格式的本地文件路径(以file:///开头),假设前端页面被放到了winform程序同一级目录的web文件夹内的index.html

async void InitializeAsync()
{
    await webView.EnsureCoreWebView2Async(null);
    webView.Source = new Uri($"file:///{AppDomain.CurrentDomain.BaseDirectory.Replace("\\", "/")}/web/index.html");
}

如果不出意外,现在运行应该可以看到页面在webview2中被显示了出来。
运行截图

不过刚刚我们是使用了一个已经写好的前端页面index.html来实现的显示,并且采用的还是本地文件加载的方法显示,那有没有可能把vue编写的页面嵌入其中呢,其实完全是可以的。

vue+vite+typescript 无http服务器开发

一般的vue项目经过build,可能都需要放到http服务下才能正确访问,这是因为由于打包后采用了module引入的方式,会产生跨域请求,本地file协议不支持的,因此无法加载。
其实只需要把这些module改为非模块方式加载,就可以正确显示。刚好vite有这样一个插件 @vitejs/plugin-legacy ,由于Vite的runtime是基于native ESM 的,这个插件就是为那些不支持ESM的浏览器准备的通过Polyfill方式实现的js加载,这同时也绕过了跨域问题,刚好实现了我们的需求。因此只需要往vue+vite项目引入一个@vitejs/plugin-legacy插件,然后配置一下即可让打包好的页面在webview2中正常工作。