wasm 是什么在此就不多做介绍了,我们直接开始写个 helloworld。
项目准备
首先需要安装依赖,默认是用当前 LTS 的.net 8。执行命令:
dotnet workload install wasm-tools
dotnet new install Microsoft.NET.Runtime.WebAssembly.Templates
#如果想要开启 AOT 功能,还需要安装下面这个依赖
dotnet workload install wasm-tools-net8
AOT 好处在于运行时会快一些,但是代价是dotnet.native.wasm
这个文件会从 2408kb 变成5434kb 。所以除非计算压力特别大,否则不推荐开启这个功能。开启方法为:在项目文件(XXX.csproj)中的PropertyGroup
里面添加下列两行:
<RunAOTCompilation>true</RunAOTCompilation>
<WasmStripILAfterAOT>true</WasmStripILAfterAOT>
依赖安装好了,我们开始新建项目。在新建项目里面选择WebAssembly Browser App
即可。这个模板项目其实就是一个完整的 hello world 程序了。但是为了学习,我们对它稍作修改。
了解项目文件
html 文件是一个简单的入口文件,我们可以不管它。main.js
是加载核心,Program.cs
则对应 wasm 文件。
// main.js
import { dotnet } from './_framework/dotnet.js'
const { setModuleImports, getAssemblyExports, getConfig } = await dotnet
.create();
//注入 c# 中
setModuleImports('main.js', {
bridge: {
location: {
href: () => window.location.href
}
}
});
const config = getConfig();
const exports = await getAssemblyExports(config.mainAssemblyName);
const text = exports.MyClass.Greeting();
document.getElementById('out').innerHTML = text;
if (exports.MyClass.CheckAuth()) {
console.log("错误!")
}
if (exports.MyClass.Auth("不好")) {
console.log("错误!")
}
if (!exports.MyClass.Auth("你好")) {
console.log("错误!")
}
if (!exports.MyClass.CheckAuth()) {
console.log("错误!")
}
//以上的运行结果是:
//Hello, World! Greetings from http://127.0.0.1/
//不好 验证失败
// 下面这行注释了就不会显示 Hello, Browser!
//await dotnet.run();
using System;
using System.Runtime.InteropServices.JavaScript;
Console.WriteLine("Hello, Browser!");
public partial class MyClass
{
private static bool auth = false;
[JSExport]
internal static string Greeting()
{
var text = $"Hello, World! Greetings from {GetHRef()}";
Console.WriteLine(text);
return text;
}
[JSExport]
internal static bool CheckAuth()
{
return auth;
}
[JSExport]
internal static bool Auth(string code)
{
if (code == "你好")
{
auth = true;
}
else
{
auth = false;
Log(code + " 验证失败");
}
return auth;
}
[JSImport("bridge.location.href", "main.js")]
internal static partial string GetHRef();
//globalThis就是window,可以直接引用
[JSImport("globalThis.console.log")]
internal static partial void Log(string message);
}
运行
编译成wasm不能直接点击VS的编译按钮,必须使用命令行才行。在命令行里面执行dotnet publish -c Release
,然后就会编译好,路径在项目路径+bin\Release\net8.0\publish\wwwroot
。使用 nginx 配置好路径后访问,可以在控制台看到以下内容:
Hello, World! Greetings from http://127.0.0.1/
不好 验证失败
首次访问需要下载 5.2M 内容(压缩前),再次访问因为会缓存 wasm 文件,所以只需要400kb。缓存文件会记录文件 hash,重新编译导致 hash 变化后会自动重新下载,这个功能还是相当好用的。
总结
用 C# 编译成 wasm 整体还是很简单的,工作流很完整。但是由于它相当于是引入了一个 C# 的解释器,所以效率会差一点,而且大小也不算小(gz 压缩也有差不多 4M)。除非对安全要求较高,否则没必要用这个功能。